TMultiGraph draw segfault

Hi all,

I’m using ROOT 5.27/04.
I have an ASCII file built the following way:

seconds/I:RH1/D:RH2/D:RH3/D:RH4/D:RH5/D:RH6/D:RH7/D:RH8/D
494377200 30.7 33.5 33.3 32.0 28.7 32.3 38.4 36.9
494380491 30.7 33.5 33.3 32.0 28.7 32.3 38.4 36.9

I’m trying to plot a TMultiGraph where each graph is a RHX vs seconds. This is the code I’m using to do it:

void drawColumns(const char* filename){
  TTree* tree = new TTree;

  tree->ReadFile(filename,"");
  int nSensors = 8;

  TMultiGraph* mg = new TMultiGraph;
  for (int iSensor = 0; iSensor < nSensors; ++iSensor) {
    int col = kRed;
    tree->Draw(Form("RH%d:seconds>>h%d", iSensor+1, iSensor), "", "goff");
    TGraph* g  = (TGraph*) gDirectory->Get(Form("h%d", iSensor));
    TGraph* cg = (TGraph*) g->Clone();
    cg->SetLineColor(col);
    cg->SetMarkerColor(col);
    mg->Add(cg,"LP");
    printf("cg = %x\n", cg);
  }
  TCanvas* c = new TCanvas("c");
  mg->Draw("A");
}

Unfortunately the last line causes a segfault:

#5  0x0000000102b9f19a in TH2F::AddBinContent ()
#6  0x0000000102bceb0f in TMultiGraph::Paint ()
#7  0x0000000101721e5b in TPad::PaintModified ()
#8  0x0000000101707314 in TCanvas::Update ()
#9  0x000000010001ed5e in TCint::UpdateAllCanvases ()

What am I doing wrong?

N.

I tried on my Linux machine. I do not get any crash with the data and the script you sent.

That’s odd. I’ve tried it with both SLC 4.6 and OSX 64bit ROOT and I get this segfault constantly.

N.

When I use this code:

TGraph* getGraph(TTree* t, const char* x, const char* y) {
  Long64_t N = t->Draw(Form("%s:%s>>h%s", y,x, y), "", "goff");

  TGraph* cg = NULL;
  bool segFault = true;
  if (segFault) {
    TGraph* g  = (TGraph*) gDirectory->Get(Form("h%s", y));
    cg = (TGraph*) g->Clone();
  } else {
    if (N == 0) return NULL;
    cg = new TGraph(N,t->GetV2(),t->GetV1());
  }
  return cg;
}

void drawColumns(const char* filename){
  TTree* tree = new TTree;

  tree->ReadFile(filename,"");
  const int nSensors = 8;

  TCanvas* c = new TCanvas("c");
  TMultiGraph* mg = new TMultiGraph;
  vector<int> cols = getColors(nSensors);
  for (int iSensor = 0; iSensor < nSensors; ++iSensor) {
    int col = cols[iSensor];
    TGraph* g = getGraph(tree, "seconds", Form("RH%d", iSensor+1));
    g->SetLineColor(col);
    g->SetMarkerColor(col);
    mg->Add(g,"LP");
  }
  mg->Draw("A");
}

It is possible to toggle between the segfault and an alternative method which does not produce the segfault.

N.

may be you meant something like in the code below?

Rene

[code]void columns() {
TTree* tree = new TTree;

tree->ReadFile(“columns.dat”,"");
int nSensors = 8;

TMultiGraph* mg = new TMultiGraph;
for (int iSensor = 0; iSensor < nSensors; ++iSensor) {
int col = kRed;
const char *expression = Form(“RH%d:seconds”,iSensor+1);
const char *selection = “”;

tree->Draw(expression,selection, "goff");
Long64_t npoints = tree->GetSelectedRows();
TGraph* cg = new TGraph(npoints,tree->GetV2(),tree->GetV1());
cg->SetLineColor(col);
cg->SetMarkerColor(col);
mg->Add(cg,"LP");
printf("cg = %x\n", cg);

}
TCanvas* c = new TCanvas(“c”);
mg->Draw(“A”);
}
[/code]

Hi Rene,

Yes. But what I wonder is - why does this method work and does not segfault, while cloning the TGraph segfaults. If you toggle the segFault param in the getGraph function, when it is set to true, the code segfaults. When it’s false, the code works.

Cheers,
N.

Your method does not work because TTree::Draw produces a TH2 and you cannot cast it to a TGraph.

Rene

Hi Rene,

I’m sorry, but according to root.cern.ch/root/html/TTree.html#TTree:Draw%2 documentation:

Granted, my method is slightly different, but I assumed it can be similarly used.

N.

In your first post you were not calling gPad->GetPrimitive, but gDirectory->Get !!
When you do Tree.Draw(“x:y>h”) you fill a histogram. In your case this is not required since you can take directly the vector of points in tree.GetV1, V2, etc. No need to create a histogram and an intermediate graph.
Proceed as I indicated.

Rene