Filling new trees in TSelector

Hello:
I’m using TSelector to pull pertinent data from one Tree and build some smaller trees, including ggMat. Running the selector, I get some infrequent errors such as:


Processed Events: 89 % (171741 events out of 194014)
Processed Events: 89 % (171760 events out of 194014)
Error in TTree::Fill: Failed filling branch:ggMat.entries, nbytes=-1
Error in TTree::Fill: Failed filling branch:ggMat.mul, nbytes=-1
Processed Events: 89 % (171779 events out of 194014)
Processed Events: 89 % (171798 events out of 194014)

Despite the errors, I haven’t found any missing events in the resultant tree compared to the parent. I’m assuming the error message is prompt, so that any missing events/branches should be close to the error.
Is there a chance that these errors in filling are being caught and corrected?
(Sorry not to send an example, I haven’t gotten a simplified version to recreate the problem yet)
Thank you!
Caleb Mattoon

Ok, I do have a script to recreate the problem (two scripts attached)
first, maketree.C makes and fills a tree.
then, tsel.C (and .h) are the TSelector-derived files.

t->Process(“tsel.C+”)
gives back a few errors (and we get more errors as the size of parent tree increases)

(using version 4.04)
Thank you again!
Caleb Mattoon
tsel.h (2.41 KB)
maketree.C (461 Bytes)
tsel.C (4.2 KB)

Hi,

The issue is that you new TTree is associated with the input (read-only) file. The fact that it seems to work in the end is only due to the low amount of data you have.

You should do something like:

[code]void tsel::Begin(TTree *tree)
{
// The Begin() function is called at the start of the query.
// When running with PROOF Begin() is only called on the client.
// The tree argument is deprecated (on PROOF 0 is passed).
ggMat = new TTree(“ggMat”,“g’s in coincidence”);
ggMat->SetDirectory(0);
TBranch *b = ggMat->Branch(“mult”,&mult,“mult/I”); TBranch *b1 = ggMat->Branch(“Ge”,Ge,“Ge[mult]/F”); TBranch *b2 = ggMat->Branch(“entries”,&entries,“entries/I”);

TString option = GetOption();

TChain *t = (TChain*)gROOT->FindObject("t");
nentries = Int_t(t->GetEntries()); //I should now have global access to nentries!
printf("total events to be processed: %d \n \n",nentries);

}
[/code]

If you want the output TTree to be first filled in memory.

It would be even better to do:

[code]TTree *ggMat = 0;
TFile *f = 0;

void tsel::Begin(TTree *tree)
{
f = new TFile(“subtreehouse.root”,“recreate”);
ggMat = new TTree(“ggMat”,“g’s in coincidence”);
TBranch *b = ggMat->Branch(“mult”,&mult,“mult/I”); TBranch *b1 = ggMat->Branch(“Ge”,Ge,“Ge[mult]/F”); TBranch *b2 = ggMat->Branch(“entries”,&entries,“entries/I”);

TString option = GetOption();

TChain *t = (TChain*)gROOT->FindObject("t");
nentries = Int_t(t->GetEntries()); //I should now have global access to nentries!
printf("total events to be processed: %d \n \n",nentries);

}
[/code]

Cheers,
Philippe

Ok, that fixes the trouble! Thank you for the help.

A note for reference, the order of the code should be switched:

[code]TTree *ggMat=0;
TFile *f = 0;

void tsel::Begin(TTree *tree)
{
// The Begin() function is called at the start of the query.
// When running with PROOF Begin() is only called on the client.
// The tree argument is deprecated (on PROOF 0 is passed).

TString option = GetOption();

TChain *t = (TChain*)gROOT->FindObject("t");
nentries = Int_t(t->GetEntries()); //I should now have global access to nentries!
printf("total events to be processed: %d \n \n",nentries);

f = new TFile("subtreehouse.root","recreate");
ggMat = new TTree("ggMat","g's in coincidence");	
ggMat->Branch("mult",&mult,"mult/I"); ggMat->Branch("Ge",Ge,"Ge[mult]/F"); ggMat->Branch("entries",&entries,"entries/I");		

}[/code]

Otherwise opening the newer file causes the gROOT->FindObject(“t”) statement to come up empty.

Hi cmattoon,

If you get an object from a file, use SetDirectory(0) on the object’s pointer to keep access to the object after the file is closed.

If you use f->cd(), you can have multiple open TFiles and move between them.

Cheers,

Sebastian