Saving a TList

I a longer program, I have a save method which saves a TList of 15 trees into a ROOT file. The program works fine on XP. It also seems to run fine on Linux, but when I open ROOT output file, it’s empty.

Any ideas? On Linux ROOT is version v4_04_02b_fbits_trefarray7_eh-GCC_3_4_3-opt. On XP it’s version 5.08.

[code] void looPDE::SaveData( ){

	gFile = this->rootOutputFile;
	printf("saving %d objects . . .\n", this->PDEObjectList->GetEntries() );
	this->rootOutputFile->ls();
	this->rootOutputFile->WriteTObject( this->PDEObjectList, "pde_objects", "SingleKey" );
	this->rootOutputFile->WriteObject( this->PDEObjectList, "pde_objects_try2");
	this->rootOutputFile->Save();
}

[/code]

results:

saving 15 objects . . .
TFile**         ./B3_0001/pde_output.root
 TFile*         ./B3_0001/pde_output.root
  OBJ: TTree    dimu_bg_DIMUON_qcd       : 0 at: 0xd4c0210
  OBJ: TTree    dimu_bg_DIMUON_z5m15     : 0 at: 0xe9d2ed0
  OBJ: TTree    dimu_bg_DIMUON_z15m60    : 0 at: 0xf398b90
  OBJ: TTree    dimu_bg_DIMUON_z60m130   : 0 at: 0xd27c778
  OBJ: TTree    dimu_bg_DIMUON_z130m250  : 0 at: 0xeaad528
  OBJ: TTree    dimu_bg_DIMUON_tau_z15m60        : 0 at: 0x112fa808
  OBJ: TTree    dimu_bg_DIMUON_tau_z60m130       : 0 at: 0xe1c4b50
  OBJ: TTree    dimu_bg_DIMUON_tau_z130m250      : 0 at: 0xe5d0df8
  OBJ: TTree    dimu_bg_DIMUON_ww        : 0 at: 0xb6ba1b8
  OBJ: TTree    dimu_bg_DIMUON_ups1      : 0 at: 0xe501130
  OBJ: TTree    dimu_bg_DIMUON_ups2      : 0 at: 0xab1e9f0
  OBJ: TTree    dimu_bg_DIMUON_top-dilept        : 0 at: 0xfd54590

but when I open ROOT output file, it’s empty.

How do you assert this?
Instead of this->rootOutputFile->Save(); trythis->rootOutputFile->Write();
Also check that the TTree are not already associated with another file (in which the ‘basket’ might be in a different file.

On a side note, why do you have a list of 15 trees?

Cheers,
Philippe.

So I changed that Save to Write. Now XP gives 2 lists: “pde_objects” and “pde_objects_try2”. The file on Linux has only 13 of my 15 trees.

I can’t explain why the Linux version doesn’t have the lists or why the XP version doesn’t have the 13 trees. I know why the 2 signal trees are missing.

My program opens files for 13 backgrounds and upto 27 signals and pulls out trees while applying some basic cuts greatly reducing the memory footprint. I then add leaves to trees with new variables and then save all the trees. I use a single file but it doesn’t have to be.

What is the best way to do this? I tried a million things that didn’t work. Sticking the trees in a list and then writing the list did work. So I stuck with it. In fact, I could swear it used to work on Linux. I used to be able to run my program on my laptop or clued0. I’m wondering if they changed something at D0.

humm strange.
Could you provide a way to reproduce your problem?

Philippe

I’m not sure a demo is possible. I could point you to my working area. Then running it is not a problem.

[quote]I could point you to my working area. [/quote]Go ahead :slight_smile:

I’ll send instruction via email.

Hi,

Most likely the problem is related to the way your produce the trees that are part of the list.

In your current code, you end up attempting (and faling) to write some of the tree to read-only files and use ‘truncated’ trees.

you do (sometime)
tree->SetDirectory(0);
rootFile->Close();
However this does NOT load the data in memory and since the file
is closed (and disconnected from the TTree), the TTree not longer has
access this is data … and if you attempt to use later, it is very
likely to lead to incorrect result (except in a subset of cases where
the tree is small).

So instead of TFile *rootFile = new TFile(rootFilePath.c_str(), "READ"); TTree *tree; TTree *tempNoCuts = (TTree *)rootFile->Get( treeName.c_str( ) ); if (cuts.Sizeof() > 5){ //5 is size of empty TCut object tree = tempNoCuts->CopyTree( cuts ); tempNoCuts->Delete(); }else{ tree = tempNoCuts; } tree->SetDirectory(0); rootFile->Close();

You have to do: TFile *rootFile = new TFile(rootFilePath.c_str(), "READ"); TTree *tree; TTree *tempNoCuts = (TTree *)rootFile->Get( treeName.c_str( ) ); gROOT->cd(); if (cuts.Sizeof() > 5){ //5 is size of empty TCut object tree = tempNoCuts->CopyTree( cuts ); }else{ tempNoCuts->LoadBaskets(); tree = tempNoCuts; } tree->SetDirectory(0); rootFile->Close();

In addition, you should review your scheme. It seems to require for 15 trees and all their data to fit in memory at the same. You need to check that the TTrees are small enough that it can fit safely in your pcs memory. If this is not the case, you will have to attach them immediately to the output file (aka in the above, replace gROOT->cd() by myoutputfile->cd() and remove the SetDirectory(0)).

Cheers,
Philippe.

Philippe,

Thanks so much for your help. Just getting rid of those error messages is worth so much.

Do I have to get rid of:

Are you going to say something like “copyTree doesn’t really copy the tree. The copy reference the original and if you delete the original, the copy will reference nothing”?

You do not need to delete the original tree since it ‘belongs’ to the TFile and will be deleted when you close the file (and do not use nocut->Delete() but use delete nocut).

Cheers,
Philippe