Hi all,
I am trying to use TTree:Draw to generate histograms from our experimental data. In this process I found an inconsistency when the draw selection string uses class methods vs. class attributes. I can reproduce this issue using the following short example scripts.
When drawing using the class attributes, the histogram is properly filled with the expected data. When drawing via the class methods the histogram has the correct number of entries, but all the entries are ‘0’.
tt.Draw("event.m_channels.m_data"); // <-- Histogram is correct
tt.Draw("event.channels().m_data"); // <-- Histogram is filled with zeros
I am using ROOT 5.26/00b, and can produce this problem on two platforms:
% uname -a
Linux pdsf4 2.6.18-194.11.3.el5.nersc_acct #1 SMP Wed Sep 1 10:56:10 PDT 2010 x86_64 x86_64 x86_64 GNU/Linux
and
$ uname -a
Darwin hahatonka 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:55:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_I386 i386
The script testClasses.C define toy classes for use in this example:
#include <vector>
class Channel
{
public:
Channel(){;}
~Channel(){;}
std::vector<int>& data(){return m_data;}
public:
std::vector<int> m_data;
};
class Event
{
public:
Event(){;}
~Event();
std::vector<Channel*>& channels(){return m_channels;}
public:
std::vector<Channel*> m_channels;
};
Event::~Event()
{
std::vector<Channel*>::iterator chanIter, chanEnd=m_channels.end();
for(chanIter=m_channels.begin(); chanIter!=chanEnd; chanIter++){
delete *chanIter;
*chanIter=0;
}
m_channels.clear();
}
#ifdef __MAKECINT__
#pragma link C++ nestedclasses;
#pragma link C++ class std::vector<int>+;
#pragma link C++ class Channel+;
#pragma link C++ class std::vector<Channel*>+;
#pragma link C++ class Event+;
#endif
The file writeClasses.C fills a tree with class data:
{
gROOT->ProcessLine(".L testClasses.C+");
Event* event = 0;
TFile f("test.root","RECREATE");
TTree* tt = new TTree("tt","Test Tree");
tt->Branch("event","Event",&event);
for(int i=0;i<10;i++){
event = new Event();
for(int j=0;j<5;j++){
Channel* channel = new Channel();
for(int k=0;k<3;k++){
channel.m_data.push_back(k);
}
event.m_channels.push_back(channel);
}
tt->Fill();
delete event;
}
tt->Write();
f.Close();
}
The file readTree.C displays the problem:
{
gROOT->ProcessLine(".L testClasses.C+");
TFile f("test.root");
TTree* tt = (TTree*)f.Get("tt");
TCanvas c1;
c1.Divide(0,2);
c1.cd(1);
tt.Draw("event.m_channels.m_data");
c1.cd(2);
tt.Draw("event.channels().m_data");
}
readTree.C (234 Bytes)
writeClasses.C (456 Bytes)
testClasses.C (742 Bytes)