I have been scratching my head for a while on this, but since I am running against the wall continously I am seeking help here.
I have an analysis where I want to do the following:
I construct 2 (independent) TTrees from a DB query and save them to disk. Now I would like to load both trees into memory (possibly detaching them from their files and only keep a copy in memory),
add few new branches to one the trees, process all entries and save one of them to a file afterwards.
With various combination, and ruining my code in the process I did not find any solution which did not crash in one or the other place.
I get error messages such as:
Error in TFile::NoiseMaxENC/D: Unknown directory NoiseMaxENC when trying to create new branches, crashes when trying to call SetBranchAddress on one of the trees and others.
I attach three files which somehow outline the idea of what I am trying to do. In this case it works, so maybe there is simply some mistake in what I do in my larger code, but maybe there is already a flaw “by design”
Actually the exmple should continue with another cloning of the tree, handing it to another class which then operates solely on a memory resident tree.
[quote]Error in TFile::NoiseMaxENC/D: Unknown directory NoiseMaxENC when trying to create new branches, crashes when trying to call SetBranchAddress on one of the trees and others.
[/quote]Humm … this is an odd looking message. TFile has no member function named ‘NoiseMaxENC/D’ …
tree_ = tree->CloneTree();
tree_->SetDirectory(0);This probably does not do what you expect. The original tree is indeed copied but its data is stored in the ‘input file’. The call to SetDirectory(0) ‘only’ detach the TTree object and does not load/extract the data from the file (For that you also need to call LoadBaskets). Most likely you want to do:gROOT->cd(); // Make the non resident directory TROOT the current directory.
tree_ = tree->CloneTree();However this requires to have enough RAM to hold the full content of the TTree (i.e. this is usually not a good idea).
So what you might be wanting could also be:code] tree_ = tree->CloneTree(0); // Copy only the meta data and NOT the data.
tree_->SetDirectory(0);[/code]
and then in processTree.cpp you would want: TFile *f = new TFile("bla2.root","RECREATE");
tree2->SetDirectory(f);
Especially thanks for pointing out that CloneTree(); SetDirectory(0); might not have all the data available in memory. As these trees are rather small, I will probably still go for the LoadBaskets suggestion, as a purely memory resident object is really what I want. This is very likely not the cleanest solution, but unless there is some really big problem to it, I will most likely stick with it.
a small question, which is related to the above: Depending on the machine I am working on (ROOT version is the same including patch level), I get the characteristic warning:
as I am consciously working with a memory-resident tree, is there any easy (user accessible) way of disabling this message?
[quote]as I am consciously working with a memory-resident tree, is there any easy (user accessible) way of disabling this message?
[/quote]Sure (by setting gErrorIgnoreLevel or by adding your own error handler) but you most like do NOT want to. This indicates that the TTree is not filled correctly (you likely ran out of memory) and/or you need to increase the AutoSave (tree->SetAutoSave(huge_value) ).