See below for the detailed answer but in the end the essential question is “why” do you need to modify the file in place instead of simply creating a new file and possibly simply renaming it to the old name. The answer to that question will guide whether the cost (writing the correct code to really match the need of the “why”) and the risk (possibility of losing the original data if anything goes wrong in the update code) are really worth it or even really needed.
The code in the first post create a new TTree which the same structure, no data except for one entry of the branch ‘a’ (and no deletion of the existing data for the branch a) so the file will grow with at least that additional data.
In addition:
t->Write("", TObject::kWriteDelete);
does “write object, then delete previous key with same name” and thus the file will also grow of the size of the TTree
meta-data.
You *could* write code to find on the file all the baskets related to the branch a
release the space of those baskets on the file to add it to the list of free block, remove the branch a
from the list of branch of the tree (or maybe clear it, that may work or may not work), add a new branch a
and then store the new data for branch and update the meta-data. In the new file the space that was freed for the old baskets may or may not be large enough to hold the new data for the branch a depending on the compression ratio and thus of the values and the new meta data may or may not fit in the space used by the old meta-data. (And I am most likely forgetting some devil-is-really-in-the-details issues).
It is much simpler to just do:
auto f_old = new TFile("f.root", "read");
auto t_old = f->Get<TTree>("t");
t_old->SetBranchStatus("a", 0);
auto f = new TFile("f-new.root", "RECREATE");
auto t = t_old->CloneTree(0);
t->Branch("a", &a, "a/I");
for(Long64_t e = 0; e < t_old->GetEntries(); ++e)
{
t_old->GetEntry(e);
a = 2; // assign the correct value for each entries
t->Fill();
}
f->Write();
delete f_old
delete f;
// If we want to look like we did it in-place (at the expense of losing data if there is a bug)
gSystem->Unlink("f.root");
gSystem->Rename("f-new.root", "f.root");
If write performance (i.e. the speed of this operation) is more important that read speed (using the file for plotting), we can also use this alternative:
auto f_old = new TFile("f.root", "read");
auto t_old = f->Get<TTree>("t");
t_old->SetBranchStatus("a", 0);
auto f = new TFile("f-new.root", "RECREATE");
auto t = t_old->CloneTree(-1, "fast");
auto b = t->Branch("a", &a, "a/I");
for(Long64_t e = 0; e < t_old->GetEntries(); ++e)
{
a = 2; // assign the correct value for each entries
b->BackFill();
}
f->Write();
delete f_old
delete f;
// If we want to look like we did it in-place (at the expense of losing data if there is a bug)
gSystem->Unlink("f.root");
gSystem->Rename("f-new.root", "f.root");