Changing entries in TTrees - request for feature

Hi, rooters,
I did store my data in a TTree (v4.0/08 on Suse9.1) using a custom class MyClass. One of its members, MyClass::energy, has an offset, which is not known at the beginning, but which I can find out in ROOT using serveral TCuts. So far, so good for one file, there I can always use for processing TTree->Draw(“energy-offset”), and I’m happy. But this offset varies in each file, and if I chain them together at the end, things get complicated, when I cut from the chain the elements of one file, read the offset I saved somewhere, add this selection to an histogramm, go to next file…
One way I could proceed is to copy each element of the original tree to a new one, substracting the offset, but for this I have to read all data and not just the branch I change.
Other possibility: Add a friend to the Tree, which uses additional storage place.

I disliked both possibilities, so I tried to add a method to MyClass, in which I substract my offset:
int MyClass::Substract(int offset){ energy-=offset; return energy;}
and did draw this. The histogramm looked allright, but the data members weren’t changed.

Any other possibility? And wouldn’t that be a nice to have this feature?
Thank you!

I suggest using TTree::GetUserInfo to store any user object (but deriving from TObject, or better TNamed)
Assumimg TTree* tree, you can do
TFile f(“myfile.root”,“update”);
TTree tree = (TTree)f.Get(“tree”);
MyUtil *myobject = new MyUtil(“myoffsets”); //object has a name
tree->GetUserInfo()->Add(myobject);
tree->Write();

Your new Tree header in the fileill contain now your object myobject that in turn may contain information like your offset or any other quantity independent of the entry number.

When processing a TChain, you can use this object (specific to each Tree)
from your MyClass::Subtract function via
MyUtil *myobj = chain->GetTree()->GetUserInfo()->FindObject(“myoffsets”);
Double_t offset = myobj->GetOffset();

Instread of a user defined object like the class MyUtil above, you can store any ROOT object (eg a TH1F) to store multiple values.

Rene

Thank you for this quick reply! I’ve known there must be an elegant way…

Ok, I did this, works fine for one file…
Just to know I got the chain mechanism right:

  1. I have to set the chain to the first element with GetEntry(0)
  2. Then I can get the TTree of the first file-> my variables for this tree and the number of elements numelements
  3. Then I add these elements (0 to numelements) minus my offset for these elements to an histogramm
  4. Then I get the entry chain->GetEntry(numelements) ->goto 2)

Is this in priciple right (and thje easiest way)?
Thank you

In my mail I was suggesting to make a first pass on all your files and for each file add an object to the Tree header, save the new Tree header
to the file (open in update mode). You do not need to use a TChain
for this first pass.
Then, each time you will process the Trees in the chain, you will automatically get the offset object from the current Tree.

Rene

I knew there would be an misunderstanding…

I added my offsets while producing my files, not in a chain.
But to get back this offsets right, I thought I’d have to get each Tree in a loop, because in TChain->GetTree() gets just the tree at the position in the chain you got the last entrie.

Here’s a example of my code. It seem’s to work, but if there’s something more elegant…

[code]//----------- Example code ----------------------
void MyOwnLoop(TChain *chain, TH1F *h1, TCut cut, int additional_deadtime=0)
{
if(!TClassTable::GetDict(“MyEvent”))
gSystem->Load(“libEvent.so”);
Int_t TreeEntries=0;
Int_t EntriesTillNow=0;
MyInfo *TotalTime;
MyInfo *ReadyTime;
long Events;

long long completeReadyTime=0;

chain->GetEntry(0);
long allEntries=(chain->GetEntries());
	
while(EntriesTillNow < allEntries )
{
	chain->GetEntry(EntriesTillNow);
	TreeEntries=((TTree*)chain->GetTree())->GetEntries();
	if (additional_deadtime)
	{
		
		TotalTime=(MyInfo<long> *)((TTree*) chain->GetTree() )->GetUserInfo()->FindObject("actTotalTime");
		stringstream TimeCut;
		TimeCut<<"GlobalTime>"<<additional_deadtime;
		Events=((TTree*)chain->GetTree())->Draw("GlobalTime",TimeCut.str().c_str());
		completeReadyTime+=(TotalTime->data - Events*additional_deadtime);
	}
	else
	{
		ReadyTime=(MyInfo<long> *)((TTree*) chain->GetTree() )->GetUserInfo()->FindObject("actReadyTime");
		completeReadyTime+=ReadyTime->data;
	}
	TFile *LoopFile=(TFile*)chain->GetFile();
                    //In my programm filling the tree, I did also fit the pedestals (8),  it's saved now as bin contents in a TH1D
	TH1D* mean_ped_root=(TH1D*)LoopFile->Get("mean_ped");
	double pedestal=0;
	for(int i=1;i<9;i++)
	{
		pedestal+=(double)mean_ped_root->GetBinContent(i); 
	}
	stringstream drawcommand;
	drawcommand<<"(GetEnergy()-"<<pedestal<<")/32>>+"<< h1->GetName();
	EntriesTillNow+=TreeEntries;
	chain->Draw(drawcommand.str().c_str(),cut,"",TreeEntries,EntriesTillNow);
}
h1->Scale((1./(double)completeReadyTime)*1.e6);

}
//--------End Example code ----------------------[/code]