TClonesArray data partially lost when reading from TTree

Dear RootTalk,

I was following the example in $ROOTSYS/tutorials/tree/tcl.C to write a TClonesArray of objects to a TTree and then read them back.

I populate the TClonesArray with MyClass objects. MyClass (code is below) is derived from TNamed and is essentially the same as TNamed, with the addition of one new data member, a float called “value.”

When I write the TFile to disk and then read from it, I can recover the TNamed data members (name and title), but not the additional data member, “value.”

I imagine that I am either doing something incorrect in the reading of the TClonesArray, or in the MyClass class definition (perhaps relating to the constructors)?

The .hh and .cc file for MyClass follow, as does my read/write code.

MyClass.hh

[code]#ifndef MYCLASS_HH
#define MYCLASS_HH

#include “TROOT.h”
//#include “TObject.h”
#include “TNamed.h”
class TString;

class MyClass : public TNamed {

public:
MyClass();
MyClass(TString name, TString title);
MyClass(const MyClass &other);
virtual ~MyClass();
float value;

private:

ClassDef(MyClass,0)

};
#endif[/code]

MyClass.cc

[code]#include “MyClass.hh”
#include “TROOT.h”

#include
using std::cout;
using std::endl;

ClassImp(MyClass)

MyClass::MyClass(TString name, TString title) : TNamed(name, title) { cout << “ctor” << endl;}
MyClass::MyClass(const MyClass &other) : TNamed(other), value(other.value) {
cout << “copy ctor” << endl;
cout << "other.value = " << other.value << endl;
cout << "value = " << value << endl;
}
MyClass::MyClass() { cout << “def ctor” << endl; }
MyClass::~MyClass() {}[/code]

And the code, called testtcamyclass.cxx to write/read the TFile:

[code]#include “…/MyClass.hh”
#include “TClonesArray.h”
#include “TString.h”
#include “TFile.h”
#include “TTree.h”
#include “TNamed.h”

#include
using namespace std;

void tcawrite() {

TClonesArray *tca_ptr = new TClonesArray(“MyClass”);

MyClass entry(“myName”, “myTitle”);
entry.value = 15.0;

cout << "entry going into TCA: "; entry.Print();
cout << “[” << entry.value << “]” << endl;

new ( (tca_ptr)[0] ) MyClass(entry);
cout << "entry read from TCA (prefill): ";
((MyClass
)tca_ptr->At(0))->Print();
cout << “[” << ((MyClass*)tca_ptr->At(0))->value << “]” << endl;

TFile *file = new TFile(“junk.root”, “RECREATE”);
TTree *tree = new TTree(“mytree”, “mytree”);
tree->Branch(“myentries”, “TClonesArray”, &tca_ptr, 32000, 0);

tree->Fill();
tree->Print();

cout << "entry read from TCA (postfill): ";
((MyClass*)tca_ptr->At(0))->Print();
cout << “[” << ((MyClass*)tca_ptr->At(0))->value << “]” << endl;

tree->Write();
file->Close();
}

void tcaread() {

TFile *f = new TFile(“junk.root”);
TTree t = (TTree)f->Get(“mytree”);

TClonesArray *tca_ptr2 = new TClonesArray(“MyClass”);
t->GetBranch(“myentries”)->SetAutoDelete(kFALSE);
t->SetBranchAddress(“myentries”, &tca_ptr2);

tca_ptr2->Clear();
t->GetEntry(0);

cout << "read from file: ";
((MyClass*)tca_ptr2->At(0))->Print();
cout << “[” << ((MyClass*)tca_ptr2->At(0))->value << “]” << endl;

}[/code]

Here is sample output when I run the .cxx file:

[code]root [0] .L testtcamyclass.cxx++
Info in TUnixSystem::ACLiC: creating shared library /home/jbattat/projects/DarkMatter/MaxCam/examples/./testtcamyclass_cxx.so
root [1] tcawrite()
ctor
entry going into TCA: OBJ: MyClass myName myTitle
[15]
copy ctor
other.value = 15
value = 15
entry read from TCA (prefill): OBJ: MyClass myName myTitle
[15]
def ctor


*Tree :mytree : mytree *
*Entries : 1 : Total = 1036 bytes File Size = 0 *

  •    :          : Tree compression factor =   1.00                       *
    

*Br 0 :myentries : *
*Entries : 1 : Total Size= 749 bytes One basket in memory *
*Baskets : 0 : Basket Size= 32000 bytes Compression= 1.00 *

entry read from TCA (postfill): OBJ: MyClass myName myTitle
[15]
root [2] tcaread()
def ctor
read from file: OBJ: MyClass myName myTitle
[0]
root [3] tcaread()
def ctor
read from file: OBJ: MyClass myName myTitle
[0]
root [4] tcaread()
def ctor
read from file: OBJ: MyClass myName myTitle
[nan]
root [5] tcaread()
def ctor
read from file: OBJ: MyClass myName myTitle
[5.35497e-33][/code]

So, I verify that I have populated the TClonesArray correctly before the TTree->Fill() call. I also verify that “value” is not disrupted by the Fill() call (not sure why it would be, but can’t hurt to check).

Then, on the tcaread() call, I can successfully read “myName” and “myTitle” from the file, but I get garbage for “value.” I don’t always get the same quantity for “value” (in the above, I get zero, nan and 5.3e-33 for successive calls to tcaread()).

Any suggestions are greatly appreciated.

root-config --version
5.14/00i
uname -a
Linux XXX.XXX.mit.edu 2.6.18-128.1.1.el5PAE #1 SMP Tue Feb 10 12:05:11 EST 2009 i686 i686 i386 GNU/Linux

Thank you,
James

Simply replace;

ClassDef(MyClass,0) by

ClassDef(MyClass,1)

A class with version=0 cannot be streamed.

Rene

Thank you for the quick reply. As expected, that solved the problem. Much appreciated!

James