Partial merging - change a value inside a TBranchElement

Hello ROOT forums,

Title is not very explicit, let me explain:

I have a set of ROOT files which I want to merge. Every ROOT file is composed of two trees, let’s call them “Events” and “Metadata”.
Merging the event tree is straightforward and does not pose a problem. The metadata, on the other hand, is very similar between each file - to a point that in case of manual merging, I only need to change a single value, containing the original number of events.

Say the branch contains a single Long_t which evaluates to 2000. If I merge 4 files, I want that number to be 8000 (hard requirement). But what happens if I go the naive way is that the value changes to a histogram containing four entries each evaluating to 2000. Another method I used (see code below) led me to 1 entry at 2000 and 1 entry at 8000, again not what I want.

Maybe the code is clearer (Python):

evts = TChain("Events")
meta = TChain("MetaData")
for f in myfiles:
    evts.Add(f)
meta.Add(myfiles[0])       # Mostly same metadata for all files, so I take only the first file

nrofevents = get_events(myfiles)      # User-defined function to get info from metadata

tf = TFile('output.root',"RECREATE")
ot = evts.CloneTree(-1,"fast")
om = meta.CloneTree(-1,"fast")

header = SimuHeader()        # Specialised class from my experiment
om.SetBranchAddress("SimuHeader",header)
om.GetEntry(0)                   # Load first event to get access to its meta data
header.SetEventNumber(nrofevents)      # Does not change the old value by the new one - instead, appends a new entry :(
om.Fill()

tf.Write()
tf.Close()

Here is a TBrowser view of the file in case it’s needed (png file)

I hope you can help me on that!

TTree are a ‘write-once’ read many times containers. Once written the data can not be updated.

Already copy all the data (including SimuHeader. Calling ‘om.Fill()’ will request the filling of all branches with whatever values are loaded. So the net result of the script above is that one more entry is added the trees with the values of the first entry (plus the change you made).

The better option is usually to leave the input as is and create a new TTree with the corrected values and used it a s a TTree Friend.

A correction of your code (but it will run ‘slow’) is to do:

om = meta.CloneTree(0)

header = SimuHeader()        # Specialised class from my experiment
om.SetBranchAddress("SimuHeader",header)
for e from 1 to meta.GetEntries() # replace this line with copy python code :)
  meta.GetEntry(e)                  
  header.SetEventNumber(nrofevents)    
  om.Fill()

Cheers,
Philippe.

Dear Philippe,

Thank you for the help. I tried implementing the quick code you suggest, but I arrive to the same result (screenshot here, PNG file). I.e., the branch changes to two entries.

If I understand correctly, the option would then be to manually recreate the whole tree and fill all the data “by hand”, right? Is there a way to copy a tree with all its branches but one?

There was a ‘fatal’ typo in my copy/paste, I meant to change it to:

[quote=“pcanal, post:2, topic:24529”]
om = meta.CloneTree(0)
[/quote]which copies the structure of the TTree but not the data.

Cheers,
Philippe.

Dear Philippe,

Thank you very much, it works now! Well, almost: I also have to manually set the other variables as well, but there aren’t many of them so it’s not a problem.

Problem solved!

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