How to modify a TLeaf value and reliably write it to disk

I am trying to use TTree-s in a rather odd way, and predictably enough, I’m running into all sort of weird situations. But it feels like one more trick and the whole thing will work, so I’m not giving up yet.

I read a TTree from a TFile. Currently, this TTree has one row, but in general it may have more.
I clone this TTree with CloneTree(). From previous posts I understand that the new cloned tree is now memory resident, and can be modified. And I succeed in adding branches to it, as needed, and in modifying the contents of existing leafs like so (for a TLeafL):

      auto *leaf_data = (Long64_t*) leaf->GetValuePointer();
      *leaf_data = value;

At this point, everything looks fine. I can read the leaf value (with leaf->GetValueLong64()) and see the new value.
I then write the TTree to disk.
Since I may have added new branches, this is a bit tricky, but it mostly works like this:

    // some branches have a previous value, some do not ==>  Some trickery is required,
    // and TBranch::BackFill's documentation sounds promising...
    auto lob = _tree->GetListOfBranches();
    // We have to reach the point where all branches have the same number of entries.
    // Hopefully, any changes we made to the existing fields will be propagated to the last entry
    long long max_entries = 0;
    for( auto obj : *lob ) {
      auto branch = static_cast<TBranch*>(obj);
      max_entries = std::max( max_entries, branch->GetEntries() );
    }
    for( auto obj : *lob ) {
      auto branch = static_cast<TBranch*>(obj);
      while( branch->GetEntries() < max_entries ) {
	branch->BackFill();
      }
    }
    // The SetEntries is needed, even though sometimes the tree comes out fine without it, just to muddy the waters.
    _tree->SetEntries(); // this incantanation came from https://root-forum.cern.ch/t/using-tbranch-fill/8004.

and later:

auto Nbytes = _tree->Write( "", TObject::kOverwrite ); // save only the new version of the tree (i.e. with any new fields)

This almost works, but the values that were modified in memory (and are seen with TLead::GetValue() and friends), are not written to disk. Instead, the old values are written.
Any ideas how to get the current TTree content to disk?


Please read tips for efficient and successful posting and posting code

_ROOT Version: 5.18/04
_Platform: Ubuntu
Compiler: Not Provided


Even for a “in memory” TTree you can not update the values that have already been filled.

I clone this TTree with CloneTree(). From previous posts I understand that the new cloned tree is now memory resident, and can be modified.

Note that “memory resident” could have 2 distinct meaning here. One is that the TTree object is in memory and can be manipulated (for example by appending new rows or adding new branches).

Another possible meaning of “memory resident” TTree (I usually called those “in-memory” TTree) is when the TTree is not attached to a file and not only is the meta-data (the TTree object itself) but also the data (the content of the branches) is memory resident.

The tutorials ROOT: tutorials/tree/copytree3.C File Reference gives an ideas of how to “update” the existing data. (whether instead of fillering some entries, you would update some of the branche values instead). Basically, you would need to Clone the structure of the TTree and then copy the rows one by one.

Many thanks you for the authoritative answer.
Now I know this is a dead end and will instead make “copy the rows one by one” work for my use case.

Hope this answer comes up the next time someone searches for how to modify a TTree / TBranch /TLead entry, instead of the misleading old answers.

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