TTree::GetUserInfo() does not operate as advertised?

Dear ROOT users community,

I have rounded up the articles about GetUserInfo() and I could not find a problem w/what I attempted, but it just does not work. I want to have some global values and settings for the data set that is in the root file, to be saved there as well, that’s all.

I have defined a simple TObject to hold three floats for example, like so:

[code]================ ParseACM.h ==================
class ACMHeaderInfo: public TObject {

public:

Float_t  blah1, blah2, blah3;

ACMHeaderInfo(): TObject();
~ACMHeaderInfo(): TObject();

void clear() {

	        blah1 = -999.;
	blah2 = -999.;
 	blah3 = -999.;
}

void printInfo() const{

	cout << ACMHeaderInfo::blah1 << "\n";
            cout << ACMHeaderInfo::blah2 << "\n"; 
            cout << ACMHeaderInfo::blah3 << "\n"; 
}

void setBlah1(Float_t val){
	this->blah1=val;
}

Float_t getBlah1(){
	return this->blah1;
}
 
ClassDef(ACMHeaderInfo, 1) // ver 1: just a test 

};
[/code]

then I fill it like so

[code]===================== ParseACM.C =====================

#include “ParseACM.h”

ClassImp(ACMHeaderInfo)

void ParseACM()
{
// create the output ROOT file/tree
//------------------------------
TFile fileroot(“acmfile.root”,“recreate”);
TTree *ACMTree = new TTree(“ACMTree”,“acmtree”);

ACMHeaderInfo* acmHeader = new ACMHeaderInfo("acmHeader");
acmHeader->setBlah1(1234.5);
cerr << acmHeader->getBlah1() << "\n"; // prints 1234.5

//------ define tree branches, loop, filling etc, works in the middle…

// writing my test header class ;)
ACMTree->GetUserInfo()->Add(acmHeader);
acmHeader->printInfo(); // prints 1234.5. -999, -999 as it should

// Finalize and write the ROOT file etc.
fileroot.Write();

}// end ParseACM()
[/code]
… and try to read the float from the tree as intended, but no luck!

[code]============================ DrawACM.C ===========================
// a very crude example
#include “ParseACM.h”

void DrawACM() {

//connect Tree generated by ParseACM.C
TFile *file = new TFile("acmfile.root");
TTree *T = (TTree*) file->Get("ACMTree");

// try to access my test header class
ACMHeaderInfo *header = (ACMHeaderInfo*) T->GetUserInfo()->FindObject("acmHeader");

//quiet up to above lines
header()->printInfo();// and this throws error
}
[/code]

I get the error:

Error: illegal pointer to class object header 0x0 2248 DrawACM.C:15: *** Interpreter error recovered ***

I have tried all combinations and permutations :wink: seems like the object is not in the tree…
What am I doing wrong? Thank you so much in advance,

Sincerely,
Eugene.

Hi Eugene,

ACMHeaderInfo* acmHeader = new ACMHeaderInfo("acmHeader");should not work within the example in the post since there is no constructor taking a const char* nor any place to stored the name within the object … However this is also the essential problem …

ACMHeaderInfo *header = (ACMHeaderInfo*) T->GetUserInfo()->FindObject("acmHeader");FindObject retrieves the object by ‘name’ with the name being the return value of theobject->GetName() … which in the example provided returns the class name (so T->GetUserInfo()->FindObject(“ACMHeaderInfo”); should work).

The easiest way to solve you problem is to derived your class from TNamed rather than TObject:class ACMHeaderInfo: public TNamed { public: ACMHeaderInfo(const char *name) : TNamed(name),blah1(-999.),blah2(-999.),blah3(-999.) {} etc.

Cheers,
Philippe.