Reading a TTree filled using a struct like class

Hi,

I am trying to read a root tree that I made using a struct like class (for ease of setting the branch address). And somehow it is not reading things correctly. If I ACLiC, it fails and if I don’t ACLiC, it works fine. But I don’t want to risk not compiling the macro. So can someone please tell me what it is that I am doing wrong?

The macro itself is as follows -
#include
#include
#include
#include
#include
#include
#include <stdlib.h>

#include “TGraph.h”
#include “TCanvas.h”
#include “TStyle.h”
#include “TPaveText.h”
#include “TLegend.h”
#include “TH2.h”
#include “TH2F.h”
#include “TH1F.h”
#include “TH1.h”
#include “TH3.h”
#include “TMath.h”
#include “TPostScript.h”
#include <TTree.h>
#include “TAxis.h”
#include “TFile.h”
#include “TChain.h”
#include “TROOT.h”
#include “TEllipse.h”
#include “TLine.h”
#include “TChain.h”
#include “TTree.h”

#include “/home/picasso/sujeewa/IWorkHere/VarProb.C”

using namespace std;

void LocalisationVisualisationAmateur();

void LocalisationVisualisationAmateur()
{

//run in root as root [0] .L macros/VarProb.C+
// root [2] .x macros/LocalisationVisualisationAmateur.C++()

//Montreal Chain
TChain *chain = new TChain(“StreeVar”);
chain->AddFile(“Montreal11000.root”);
chain->AddFile(“Montreal11050.root”);

//PhysVariables *skvarmc = new PhysVariables();
MontrealLoc *skvarmc = new MontrealLoc();
chain->SetBranchAddress(“PhysVariables”,&skvarmc);

Int_t nentmc=chain->GetEntries();

TH2F *xycom = new TH2F(“xycom”,“X vs Y”,80,-20.,20.,80,-20.,20.);

for (Int_t iUL=0; iUL<nentmc; iUL++)
{
Int_t nbytes = chain->GetEntry(iUL);

   xycom->Fill(skvarmc->udemposition[0],skvarmc->udemposition[1]);
}

TCanvas *cc = new TCanvas(“cc”,“cc”,100,100,400,400);
cc->cd();
xycom->Draw(“lego2z”);

}

============== And the struct like class, which I load at the beginning, VarProb.C is as follows===================
#include “TObject.h”

class MontrealLoc : public TObject
{
public:

//Physics Variables; these will be our leaves
Int_t runindex;
Int_t evindex;
Int_t totevents;

Double_t udemposition[3];
Double_t udemsigmaplus[3];
Double_t udemsigmaminus[3];
Double_t udemtzero[9];
Double_t udemsigmatzero[9];
Double_t velocity;
Double_t sigmavelocity;
Double_t chisquared;
Double_t nuctime;
Int_t numpzos;
Int_t goodpzos[9];
char* detname;
Int_t prodnum;
Char_t* runtype;

ClassDef (MontrealLoc,2);
};

#if !defined(CINT)
ClassImp(MontrealLoc);
#endif

=============Is it something wrong that I do when I make my root files in the first place? If I try to load one of these root files with a root MontrealLoc11000.root it complains that it can’t find the class that was used to make the tree? I remember seeing this in the past for other root files other people have made and given me. But we used to ignore them back then. Is this a normal warning message? I can actually browse and run uncompiled macros even though I get this warning… The warning message looks like the following-
root [0]
Attaching file Montreal11000.root as _file0…
Warning in TClass::TClass: no dictionary for class MontrealLoc is available ===================

Hi,

Did you generate and load the dictionary for the class MontrealLoc?
To remove the warning you can simply load the dictionary before opening the file.

Cheers,
Philippe

Hi Philippe,

Actually my real question is why I can not read this tree I make using the macro I attached at the beginning. Like I said if I don’t ACLiC it works, but if I ACLiC it doesn’t. I would like to be able to compile my code with ACLiC to avoid potentially sneaky bugs.

So if I in root do
.L VarProb.C+
.x LocalisationVisualisation.C
it works fine.

but if I do
.L VarProb.C+
.x LocalisationVisualisation.C++
It doesn’t. Why? It gives me a segmentation fault, but I don’t understand why? (I have attached the full error message below).

Is the way I use chain->AddFile or chain->SetBranchAddress not correct?

Thanks!

Hi,

The problem seems to be that the MontrealLoc objects are not initialized properly. In particular runtype is not set and hence as a random value (which in the interpreted case probably happens to be a sensible value … but that’s just luck :slight_smile: ).

Try adding a constructor like:MontrealLoc() : runtype(0) {}

Cheers,
Philippe

Hi Philippe,

I added the line MontrealLoc() {runtype=0;} towards the bottom of my VarProb.C macro, so now it looks like the attached. But I still get seg faults. Is this what you wanted me to do?

As a side question-
In the example root_v5.16.00/tutorials/tree/tree2a.C, Rene initializes every leaf in the tree with a separate line. Is this mandatory? I was able to get away without doing this in the past, when I had to read in trees with lots of leaves - it seems a little impractical to do so if the number of leaves is large.

[quote]In the example root_v5.16.00/tutorials/tree/tree2a.C, Rene initializes every leaf in the tree with a separate line. Is this mandatory?[/quote]It depends of the structure of the TTree. In that example, there is only one leaf for each branch and each is independent from the other, so there is no other choice. In your case, it sounds like you have one top level branch containing an object of type MontrealLoc and this branch may (or may not) have been split. In either case, a single SetBranchAddress is all you need.

Cheers,
Philippe.

Cheers,
Philippe.

Hi Philippe,

I think I need to initialize all the leaves likewise right? How do I initialize an array that I have declared as MyArray[n].

I have tried my ‘in-elegant’ way -
MontrealLoc():detname(0), runtype(0) {MyArray[n]=0;} for the lack of knowledge to do it like you did with the char*'s. But I don’t think they are initializing properly; i.e., when i compile, I get gibberish, if I don’t compile i get correct numbers…

Also this is a new leaf that I added. The old leafs, even the one that were arrays, work just fine… Why is this?

  • Sujeewa

[quote]Also this is a new leaf that I added. The old leafs, even the one that were arrays, work just fine… Why is this? [/quote]What do you mean ‘new’ leaf? What is the type of those new leaf? Are they really in the input file?

You can not initialize array value via the initializer list so you should do:

MontrealLoc():detname(0), runtype(0) { for(int i=0; i< sizeof(MyArray)/sizeof(MyArray[0]; ++i) { MyArray[i]=0; } }

Cheers,
Philippe

Hi Philippe,

Yes, I do initialize like that. But then it seems not to read the value properly.

So what I have done is this - I have made new root files, just like the ones I sent you, but now they have an additional leaf called PowerCutG[9]. In my C-struct-like calss VarProb.C I declare it as-
Double_t PowerCutG[9];

I know the tree fills fine, because if I just open the file in a TBrowser, and say Draw(“PowerCutG[0]”) etc… it will show me the correct values.

But now when I try to access this tree, just like with the code I sent you before, it gives me some weird number. So in accessing, in my C-struct like class I have -
Double_t PowerCutG[9];
MontrealLoc():detname(0), runtype(0)
{
for(Int_t ii=0; ii<9; ++ii)
{
PowerCutG[ii] = 0.;
}
}

and like before I access it with a
for (Int_t iUL=0; iUL<nentmc; iUL++)
{
Int_t nbytes = chain->GetEntry(iUL);
skvarmc->PowerCutG[0];
}
for example.

Again, like before, if I just do .x macros/TempTest.C it gives correct values; but if I do .L macros/QuickVar.C++ and .x macros/TempTest.C++, it won’t work, just for the PowerCutG values - other leaves are fine.

I’ll attach the 2 codes here again, let me know if you want me to send you a root file with this new leaf PowerCutG.

Thanks!

Hello Philippe!

I fixed it now. There was one sneaky little array that I had forgot to initialize.

Thanks!

  • Sujeewa