Non-persistent data members: custom vs. automatic streamer

Hi
I already sent this message to the roottalk list with no response, actually
this is just an excuse to try the new ROOT forum. Any reply gratefully received!!
John

I have a problem with non-persistent data members in objects stored in a TTree when the objects in
question have a custom streamer. It seems that each call to TTree::GetEntry wipes the current value
of the non-persistent data member, by a call to the default ctor for the class. This behaviour is not
observed when using an automatically generated streamer, even if in fact the custom streamer is nothing
but a copy of the automatically generated one. I have attached some files which demonstrate the problem.

I am using the 3.05/07 binary for RH9 with gcc 3.2.2

The class TestPersist has two data members, a and b. a is persistent, b non-persistent.
The method TestPersist::IsOK() returns kTRUE if a > b, and kFALSE otherwise.
I generate a TTree filled with TestPersist objects using the script TestPersist_Tree.C.
100 ‘events’ are generated with “a” taking the values 0,1,2,…,99.
The AnalPersist analysis class was generated from the TTree with MakeSelector.
This analysis sets a “threshold” value b=50 in the Begin() method, and then fills
a histogram with the value of “a” for each “event” with TestPersist::IsOK() = kTRUE.

When I use an automatic streamer (rootcint -f TestPersist_Dict.cxx -c TestPersist.h)
I get the result I want, i.e. a histogram which is filled from a=51 up to 99.
The “b” histogram shows that the value I set in Begin() i.e. 50 is not affected by
the reading of objects from the TTree, as one expects.

However, with a customised streamer (rootcint -f TestPersist_Dict.cxx -c TestPersist.h-),
which is in fact an exact copy of the one generated in the previous case,
the “a” histogram is filled with all values from 0 to 99, and indeed this is because
the value of “b” is not 50 but 0. I checked that this is due to the default ctor being called
by changing the initialisation in TestPersist::TestPersist() to “b=20”. In this case I find that
the value of “b” is always 20.

In my “real-life” problem I have no choice but to use a customised streamer.
Can you tell me how to get the same behaviour for non-persistent members in this case
as when using an automatic streamer ? (preferably I would like to keep the initialisation
of the non-persistent members in the default ctor!!)

Thankyou very much.
John.

PS. I made the CINT dictionary for the class using
rootcint -f TestPersist_Dict.cxx -c TestPersist.h
Then I compiled the class and the dictionary and built an .so:
g++ -c root-config --cflags -oTestPersist.o TestPersist.C
g++ -c root-config --cflags -oTestPersist_Dict.o TestPersist_Dict.cxx
g++ -shared root-config --libs -olibTestPersist.so TestPersist.o TestPersist_Dict.o
Then at the ROOT command line I did:
.L libTestPersist.so
.L TestPersist_Tree.C+
write_tree()
in order to create and fill the TTree. Then in a new ROOT session I do:
.L libTestPersist.so
TFile f(“test_persist.root”)
t1->Process(“AnalPersist.C+”)
In the case of a customised streamer I uncommented the line
#define CUSTOM_STREAMER
in TestPersist.h, built the dictionary using
rootcint -f TestPersist_Dict.cxx -c TestPersist.h-
and then repeated all the other steps in order.
testpersist.h (1.53 KB)
analpersist.h (4.73 KB)
TestPersist_Tree.C (505 Bytes)

Hi John,

Sorry for this late reply. I was scarred by the length of your message ::slight_smile:

When you use a custom Streamer, the “AutoDelete” option for the
object in the branch is automatically set to kTRUE when the Tree is created.
When this option is set, the object in the branch is always deleted and
recreated
at each GetEntry. You can disable this option by calling
TBranch::SetAutoDelete(kFALSE);
You can do this, for example in your Analysis::Notify function
when the pointer to the branch is computed

b_b__tp = fChain->GetBranch(“b__tp”);
b_b__tp->SetAutoDelete(kFALSE); //add this line

see:
root.cern.ch/root/htmldoc/TBranc … AutoDelete

Rene Brun