Saving multiple TTrees (in an array) to multiple files: only first file can be read

I have created an array of (pointers to) instances of TTree. I loop over this array and save each TTree to its own file using an array of pointers to TFile class instances. When I attempt to open branches the TTrees in TBrowser, the branches of the TTree stored in the first file filled by the arrays open and display normally. However, when I try to open branches of trees in any other file, one of two things happens: either TBrowser closes and I see repeated instances of the message “Error in TFile::ReadBuffer: error reading all requested bytes from file EventFile001900102.root, got 0 of 3287”, or Root closes and I’m given the message “Error in TBasket::Streamer: The value of fNevBufSize is incorrect (-1408112851) ; trying to recover by setting it to zero
Error in TBranch::GetBasket: File: EventFile001900103.root at byte:25607, branch:TOF, entry:-1, badread=1, nerrors=1, basketnumber=0
Error in TBasket::Streamer: The value of fNevBufSize is incorrect (-1408112851) ; trying to recover by setting it to zero
terminate called after throwing an instance of 'std::bad_alloc’
what(): std::bad_alloc

Any help would be appreciated. The relevant portions of my code are below:

int main(int argc, char **argv)
{
	int N_of_File = atoi(argv[5]);
	TFile** FinalOutputRoot = new TFile*[10];
	TTree **BetaTree = new TTree*[N_of_File];
	TTree **IonTree = new TTree*[N_of_File];
	for (int i=0;i<N_of_File;i++){
		BetaTree[i] = new TTree(treename.c_str(),"The Post-Processed Beta Dataset");
		BetaTree[i]->Branch("ScintEnergy",&(OutData.ScintEnergy),"ScintEnergy/i");
		BetaTree[i]->Branch("MWPCEnergy",&(OutData.MWPCEnergy),"MWPCEnergy/s");
		BetaTree[i]->Branch("MWCPHitPos",&(OutData.MWPCHitPos[0]),"MWPCHitPosX/S:MWPCHitPosY/S");
		//several more branches are added.  Variables such as OutData.ScintEnergy are declared (not shown here)
		
		IonTree[i] = new TTree(treename.c_str(),"The Post-Processed Ion Dataset");
		IonTree[i]->Branch("TOF",&(OutData.TOF),"TOF/i");
		IonTree[i]->Branch("HitPos",&(OutData.HitPos[0]),"HitPosX/I:HitPosY/I");
		IonTree[i]->Branch("HitAngle",&(OutData.HitAngle),"HitAngle/s");
		
		FinalOutputRoot[i]=new TFile(rootFilename,"recreate");
	}
	while(1)
	{
		if(IonInput.eof() && BetaInput.eof())//the number of data points in these files is the same
			break;
		for (int i=0;i<N_of_File;i++)
		{
			//The variables associated with the branches (OutData.ScintEnergy, etc.) are filled (not shown here).
			BetaTree[i]->Fill();
			IonTree[i]->Fill();
		}
	}
	 for (int i=0;i<N_of_File;i++)
	 {
		FinalOutputRoot[i]->cd();
    		IonTree[i]->Write();
		delete IonTree[i];
    		BetaTree[i]->Write();
 		delete BetaTree[i];
	}
	for (int i=0;i<N_of_File;i++)
	{
   		FinalOutputRoot[i]->Close();
  		delete FinalOutputRoot[i];
  	}
	delete[] FinalOutputRoot;
	delete[] IonTree;
	delete[] BetaTree;
	return 0;			
}

Try (I assume that you use “N_of_File” different “rootFilename” and different “treename” for “BetaTree[i]” and “IonTree[i]”): [code]int main(int argc, char **argv)
{
int N_of_File = atoi(argv[5]);
TFile *FinalOutputRoot = new TFile[N_of_File];
TTree *BetaTree = new TTree[N_of_File];
TTree *IonTree = new TTree[N_of_File];
for (int i=0;i<N_of_File;i++){
FinalOutputRoot[i]=new TFile(rootFilename,“recreate”); // first create the file

  BetaTree[i] = new TTree(treename.c_str(),"The Post-Processed Beta Dataset");
  BetaTree[i]->Branch("ScintEnergy",&(OutData.ScintEnergy),"ScintEnergy/i");
  BetaTree[i]->Branch("MWPCEnergy",&(OutData.MWPCEnergy),"MWPCEnergy/s");
  BetaTree[i]->Branch("MWCPHitPos",&(OutData.MWPCHitPos[0]),"MWPCHitPosX/S:MWPCHitPosY/S");
  //several more branches are added.  Variables such as OutData.ScintEnergy are declared (not shown here)
  
  IonTree[i] = new TTree(treename.c_str(),"The Post-Processed Ion Dataset");
  IonTree[i]->Branch("TOF",&(OutData.TOF),"TOF/i");
  IonTree[i]->Branch("HitPos",&(OutData.HitPos[0]),"HitPosX/I:HitPosY/I");
  IonTree[i]->Branch("HitAngle",&(OutData.HitAngle),"HitAngle/s");

}
while(1)
{
if(IonInput.eof() && BetaInput.eof())//the number of data points in these files is the same
break;
for (int i=0;i<N_of_File;i++)
{
//The variables associated with the branches (OutData.ScintEnergy, etc.) are filled (not shown here).
BetaTree[i]->Fill();
IonTree[i]->Fill();
}
}
for (int i=0;i<N_of_File;i++)
{
FinalOutputRoot[i]->cd();
IonTree[i]->Write();
BetaTree[i]->Write();
delete FinalOutputRoot[i]; // automatically deletes IonTree[i] and BetaTree[i], too
}
delete[] FinalOutputRoot;
delete[] IonTree;
delete[] BetaTree;
return 0;
}[/code]

Thank you! Creating the file before creating the trees fixes the problem. Why is this?

ROOT User’s Guide -> Object Ownership
BTW. Note that I not only changed where the file is created but I also modified the “write” and “delete” sequence.

I understand that with the correction you provided, creating the file sets the working directory to one associated with that file, and so all subsequent operations I perform with the new TTree become associated with that file, but why is it that using my way didn’t work, where I created the file after the TTree but used FinalOutputRoot[i]->cd(); to change the directory of the tree to the file before using IonTree[i]->Write();?

Hi,

[quote]TTree but used FinalOutputRoot[i]->cd(); to change the directory of the tree to the file before using IonTree[i]->Write();?[/quote]This only affects the meta-data (the TTree itself) and the data itself is stored in the file the TTree was attached to (whichever was currently at the time the TTree object was constructed or the parameter of tree->SetDirectory(file); )

Cheers,
Philippe.