Overwriting TTree branches in memory

Hi,

I am posting a problem which I sent to the roottalk list a week ago but got no answer to, maybe I am more lucky here:

I would like to modify some branches of an existing TTree I load to memory. I need to do that since I need to modify for example the jet energy and later use TTreeFormula or TBranchProxy to access the tree which should then contain the changed value. I do not want to save the modification to disk but do it transiently only.
Is this possible and if yes, how is it done?

I have figured out how to directly modify the baskets in a branch in the meantime which seems to do part of the job but also seems to mess with the loading of tree entries, so I need some more information on that.

If the problem is stated unclearly here is a code snippet which probably explains it better:

TBranch* branch = fChain->GetTree()->GetBranch(“ptAK4H1TPJ”);
TLeaf* leaf = branch->GetLeaf(“ptAK4H1TPJ”);
float* val = (float*) leaf->GetValuePointer();
for(unsigned int i = 0; i< njetsAK4H1TPJ; i++){
newpt = jetEMJESfixer->fixAntiKt4H1Topo(ptAK4H1TPJ[i],etaAK4H1TPJ[i]) * ptAK4H1TPJ[i];
val[i] = newpt;
}
leaf->FillBasket(*(branch->GetBasket(0)->GetBufferRef()));

Thanks a lot in advance!

Cheers,
Florian

First, I do not see any mails from you at roottalk last week or in the past few months.
Concerning your problem, I suggest the following code:

int njetsAK4H1TPJ;
double ptAK4H1TPJ[some max dimension];
double etaAK4H1TPJ[some max dimension];
double val[some max dimension];
fChain->SetBranchStatus("*",0);
fChain->SetBranchAddress("ptAK4H1TPJ", ptAK4H1TPJ);
fChain->SetBranchAddress("etaAK4H1TPJ", etaAK4H1TPJ);
fChain->SetBranchAddress("njetsAK4H1TPJ", &njetsAK4H1TPJ); //and possibly other branches too
fChain->SetBranchStatus("ptAK4H1TPJ", 1);
fChain->SetBranchStatus("etaAK4H1TPJ", 1);
fChain->SetBranchStatus("njetsAK4H1TPJ", 1); //and possibly other branches too
/then loop on the chain entries
Long64_t nentries = fChain->GetEntries();
for (Long64_t entry=0;entry<nentries;entry++) {
   fChain->GetEntry(entry);
   for(unsigned int i = 0; i< njetsAK4H1TPJ; i++){
      newpt = jetEMJESfixer->fixAntiKt4H1Topo(ptAK4H1TPJ[i],etaAK4H1TPJ[i]) * ptAK4H1TPJ[i];
     val[i] = newpt;
   }
}

Rene

Hi Rene,

thanks for the answer!
So does your example code provide that a later access to the tree via TTreeFormula reads the changed branch value? I thought that the TTreeFormula directly reads the branch again and does not care about the branch address I set in my code.

Cheers,
Florian

TTreeFormula does not read any data. It is simply a class doing some calculations with the variables in the formula using the values of the variables currently in memory.

Rene

Hi Rene,

so I tried:

root [1] float pt[128]
root [2] vtuple->SetBranchAddress(“ptAK4H1TPJ”,&pt)
root [3] TTreeFormula* formula = new TTreeFormula(“Selection”,“ptAK4H1TPJ>0”,vtuple)
root [4] vtuple->GetEntry(0) (Int_t)174576
root [5] formula->EvalInstance(0) (Double_t)1.00000000000000000e+00
root [6] pt[0]
(float)3.00864238281250000e+04
root [7] pt[0] = -1
(const float)(-1.00000000000000000e+00)
root [8] pt[0]
(float)(-1.00000000000000000e+00)
root [9] formula->EvalInstance(0) (Double_t)1.00000000000000000e+00

I would have expected 0 as return in the last line now given the formula string, can you tell me what’s going wrong in this example?

Cheers,
Florian

Florian,

Could you post the shortest piece of running code reproducing this problem, together with a small data file?

Rene

Hi Rene,

example script and root file are attached, just run with root test.C.

Cheers,
Florian
test.root (12.8 KB)
test.C (450 Bytes)

Hi Florian,

Unfortunately I told you something partially wrong. When calling EvalInstance(0) TTreeFormula will
take a copy from the input buffer in memory and store the value specified in the branch address.
This happens only for instance=0. if you call this function to access the second element of the array
it would work, but of course, it is not what you want.
I will discuss this oddity with Philippe (currently away) to see if we can modify this behavior.

Rene

Hi Rene,

thanks a lot for the help so far! Pending a fix for this behavior, could you suggest a workaround with which I can create the expected behavior?

Cheers,
Florian

Hi Rene,

I used TTreeFormula::SetQuickLoad(true) to disable the loading on first instance, this seems to work now.

Cheers,
Florian

Hi Florian,

The behavior is completely intentional. There is case where user expect that even if there do go ahead and modifying the underlying data that a ‘re-read’ will lead to having the original data back (this seems like the more straightforward default).

Cheers,
Philippe.