CloneTree fast results in spurious dictionary warnings

Greetings,

Given a ROOT file containing two TTree’s, if I CloneTree(-1, “fast”) and save only one of the two trees to a new file, despite the fact that the new file contains only the one tree, I receive “no dictionary for class” warnings for the classes in the other tree that was neither cloned nor saved. Is this expected behavior? For everything that follows, I am using a pre-compiled 64-bit ROOT v5.22/00 on Linux, but I have seen this also in 5.18 on both 64 and 32-bit Linux systems.

Attached is all the code used to produce the demonstrative terminal snippets copied and pasted below, and here I will briefly describe the files:

  • Makefile.txt produces a library libClass.so containing dictionaries for classes Class1 and Class2
  • makeTwoTrees.cpp creates a ROOT file (twotrees.root) containing two TTree’s: tree1 has one branch that stores objects of type Class1, and tree2 has one branch that stores objects of type Class2
  • skimOneTree.cpp takes as input twotrees.root, and produces two files: onetree.root contains tree2 after a CloneTree(), and onetree_fast.root contains tree2 after a CloneTree(-1, “fast”)

Here now are terminal snippets to demonstrate the behavior:

[cms-tas03] /home/jribnik/devel/tmp > ls
Class1.h  Class2.h  ClassLinkDef.h  Makefile.txt  makeTwoTrees.cpp  skimOneTree.cpp
[cms-tas03] /home/jribnik/devel/tmp > make -f Makefile.txt 
g++ -O -Wall -fPIC -m64 -shared -I/opt/root/include ClassDict.cc -o libClass.so
[cms-tas03] /home/jribnik/devel/tmp > root
****************************
* Welcome to ROOT v5.22/00 *
****************************
root [0] gSystem->Load("libClass.so")                
(int)0
root [1] .L makeTwoTrees.cpp++                       
Info in <TUnixSystem::ACLiC>: creating shared library /home/jribnik/devel/tmp/./makeTwoTrees_cpp.so
root [2] makeTwoTrees()                              
root [3] .q
[cms-tas03] /home/jribnik/devel/tmp > root twotrees.root 
****************************
* Welcome to ROOT v5.22/00 *
****************************
root [0] 
Attaching file twotrees.root as _file0...
Warning in <TClass::TClass>: no dictionary for class Class1 is available
Warning in <TClass::TClass>: no dictionary for class Class2 is available
root [1] .q
[cms-tas03] /home/jribnik/devel/tmp > root
****************************
* Welcome to ROOT v5.22/00 *
****************************
root [0] .L skimOneTree.cpp++                        
Info in <TUnixSystem::ACLiC>: creating shared library /home/jribnik/devel/tmp/./skimOneTree_cpp.so
root [1] skimOneTree()
Warning in <TClass::TClass>: no dictionary for class Class1 is available
Warning in <TClass::TClass>: no dictionary for class Class2 is available
root [2] .q
[cms-tas03] /home/jribnik/devel/tmp > root onetree.root 
****************************
* Welcome to ROOT v5.22/00 *
****************************
root [0] 
Attaching file onetree.root as _file0...
Warning in <TClass::TClass>: no dictionary for class Class2 is available
root [1] .q
[cms-tas03] /home/jribnik/devel/tmp > root onetree_fast.root 
****************************
* Welcome to ROOT v5.22/00 *
****************************
root [0] 
Attaching file onetree_fast.root as _file0...
Warning in <TClass::TClass>: no dictionary for class Class1 is available
Warning in <TClass::TClass>: no dictionary for class Class2 is available
root [1]

As you can see, while CloneTree() results in warnings for the class stored in tree2 as expected, CloneTree(-1, “fast”) results in warnings for the class stored in tree2 and also the class stored in tree1 which was neither cloned nor saved.

Okay, so this is just a warning message, but I still prefer not to see it. If twotrees.root was actually a huge file, and Class2 was actually an extremely complicated class, it would take a long time to CloneTree() compared to CloneTree(-1, “fast”) for the reward of not seeing this message about Class1.

Suppose I don’t know the definition of Class1, or just that I want to reduce the size of the library I must build to rid myself of this warning message. Can I rest assured that as a (temporary?) workaround I can write a simple definition for Class1, i.e. just class Class1 {};, and in no way corrupt the data I’m reading from Class2 in tree2? Remember that in this file there should be no trace of tree1 or Class1, except of course for the warning message.

Thanks for reading this far, and for any comments you may have,

Jake
skimOneTree.cpp (479 Bytes)
makeTwoTrees.cpp (507 Bytes)
Makefile.txt (776 Bytes)
ClassLinkDef.h (155 Bytes)
Class2.h (260 Bytes)
Class1.h (260 Bytes)

[quote]As you can see, while CloneTree() results in warnings for the class stored in tree2 as expected, CloneTree(-1, “fast”) results in warnings for the class stored in tree2 and also the class stored in tree1 which was neither cloned nor saved. [/quote]The ‘fast’ cloning is saving time by not opening the buffer associated with the TTree. In consequence, it does not know which of the classes registered with the TFile is being used in that TTree or not [In the general case, you class Class2 might be well be containing a Class1 object …]. So the ‘fast’ cloning just carries over all the class definitions.

[quote]Suppose I don’t know the definition of Class1, or just that I want to reduce the size of the library I must build to rid myself of this warning message. Can I rest assured that as a (temporary?) workaround I can write a simple definition for Class1, i.e. just class Class1 {};, and in no way corrupt the data I’m reading from Class2 in tree2? Remember that in this file there should be no trace of tree1 or Class1, except of course for the warning message. [/quote]Yes this should work since you are guaranteeing yourself that Class1 is not used.

Cheers,
Philippe.

Makes sense; I guess the 113 lines of proof-of-concept code weren’t necessary to describe the behavior :slight_smile:

Great, thanks Philippe.

Jake