ROOT TCanvas, Draw("SAME") does not work in class

Hello,

I do have a little problem:

I have several Histograms and I want to draw all of them in one TPad. This works fine so far, but when I am trying to do that in a class it does not.

It looks like that:

class test{
public:
void GetHistogram();
void DrawHistogram(Int_t);

private:
TH1F* histogram;
TApplication* tApp;
TCanvas* canvas;
}

test::test()
{
tApp=new TApplication("data",0,0);
canvas=new TCanvas("canvas","data",10,10,900,600);
}

DrawHistogram looks the following:

void test::DrawHistogram(Int_t run)
{
    if(run==0) histogram->Draw();
    else histogram->Draw("SAME");
    canvas->Update();
}

What happens? Every single histogram is plotted on its own and the old one disappears. It is really confusing me as it works without using classes. Maybe there is just a little mistake but I do not see it.

Thanks for any help.

You run in the root interpreter or you compile your program standalone ?
Do you have a small example using this class ?

I run this program stand alone. What I do is the following:

main.c:

int main()
{
 test testclass;
   for(Int_t i=0;i<run.end();++i)
   {
   //this saves the pointer to a root histogram to TH1F* histogram (works fine)
   testclass.GetHistogram(i);   
   //now I want to draw each histogram into the same Canvas
   testclass.DrawHistogram(i);

   }
}

This works fine when I draw everything in the end, so after I ran through that for loop and pushed all Histogram pointers into a vector of Histogram pointers, to plot them.

But I want to plot every single Histogram “live” into the same Canvas, this does not work using that class and I do not know why.

Regards

P.S. it is Root version 5.32/01

ok… I quickly tired to put together your code in:

#include <stdlib.h>
#include <Riostream.h>
#include <time.h>
#include <TROOT.h>
#include <TApplication.h>
#include <TH1.h>

class test{
public:
void GetHistogram();
void DrawHistogram(Int_t);

private:
TH1F* histogram;
TApplication* tApp;
TCanvas* canvas;
}

test::test()
{
tApp=new TApplication("data",0,0);
canvas=new TCanvas("canvas","data",10,10,900,600);
}

int main()
{
 test testclass;
   for(Int_t i=0;i<run.end();++i)
   {
   //this saves the pointer to a root histogram to TH1F* histogram (works fine)
   testclass.GetHistogram(i);   
   //now I want to draw each histogram into the same Canvas
   testclass.DrawHistogram(i);

   }
}

but I get:

ctest.cxx:32: error: new types may not be defined in a return type
ctest.cxx:32: note: (perhaps a semicolon is missing after the definition of ‘test’)
ctest.cxx:32: error: return type specification for constructor invalid
ctest.cxx:32: error: definition of implicitly-declared ‘test::test()’
ctest.cxx:32: error: declaration of ‘test::test()’ throws different exceptions
ctest.cxx:21: error: from previous declaration ‘test::test() throw ()’
ctest.cxx: In constructor ‘test::test()’:
ctest.cxx:35: error: invalid use of incomplete type ‘struct TCanvas’
/Users/couet/roottrunkX11/include/TROOT.h:36: error: forward declaration of ‘struct TCanvas’
ctest.cxx: In function ‘int main()’:
ctest.cxx:41: error: ‘run’ was not declared in this scope
ctest.cxx:44: error: no matching function for call to ‘test::GetHistogram(Int_t&)’
ctest.cxx:23: note: candidates are: void test::GetHistogram()

I would help if you provide something I can compile.

Hi,

it should look like this:



#include <iostream>
#include <vector>
#include <string>
#include "TROOT.h"
#include "TH1F.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TRandom.h"


class test{
public:
	test();
	~test();
	void GetHistogram(Int_t);
    void DrawHistogram(Int_t);



private:
	TH1F* energyHistogram;
	TApplication* tApp;
	TCanvas* canvas;
};




test::test()
{
	energyHistogram = new TH1F();
	tApp=new TApplication("Data",0,0);
	canvas=new TCanvas("canvas","Data",10,10,1100,600);
}

test::~test()
{
tApp->Run();
}

void test::GetHistogram(Int_t i)
{
	energyHistogram->FillRandom("gaus",i*100);
}

void test::DrawHistogram(Int_t counter)
{
	if(counter==0) energyHistogram->Draw();
	else	energyHistogram->Draw("SAME");
	canvas->Update();
}


int main()
{
	test testclass;

	for(Int_t i=0;i<10;++i)
	{
		testclass.GetHistogram(i);
		testclass.DrawHistogram(i);
	sleep(2);
	}

	return 0;
}

I was able to compile and run, the same problem occured, it just writes the latest histogram.

[code]#include “TApplication.h”
#include “TCanvas.h”
#include “TH1.h”
#include <unistd.h> // for “sleep”

class test{
public:
test();
~test();
void GetHistogram(Int_t);
void DrawHistogram(Int_t);
private:
TH1F* energyHistogram;
TApplication* tApp;
TCanvas* canvas;
};

test::test()
{
energyHistogram = new TH1F(“energyHistogram”, “My Energy Histogram”, 100, -5.0, 5.0);
tApp=new TApplication(“Data”,0,0);
canvas=new TCanvas(“canvas”,“Data”,10,10,1100,600);
}

test::~test()
{
tApp->Run();
}

void test::GetHistogram(Int_t i)
{
energyHistogram->FillRandom(“gaus”, (i+1)*10000);
}

void test::DrawHistogram(Int_t counter)
{
canvas->cd(0); // make sure it will be drawn in the "canvas"
if(counter==0) energyHistogram->Draw(); // or Draw(“AXIS”);
// energyHistogram->DrawClone(“SAMES”); // TObject::DrawClone
energyHistogram->DrawCopy(“SAMES”); // TH1F::DrawCopy
canvas->Update(); // or canvas->Modified(); canvas->Update();
}

int main()
{
test testclass;

for(Int_t i=0;i<10;++i)
{
testclass.GetHistogram(i);
testclass.DrawHistogram(i);
sleep(2);
}

return 0;
}[/code]



#include <iostream>
#include <vector>
#include <string>
#include "TROOT.h"
#include "TH1F.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TRandom.h"


class test{
public:
   test();
   ~test();
   void GetHistogram(Int_t);
    void DrawHistogram(Int_t);



private:
   TH1F* energyHistogram;
   TApplication* tApp;
   TCanvas* canvas;
};




test::test()
{
   energyHistogram = new TH1F("h1","h1",100,-4,4);
   tApp            = new TApplication("Data",0,0);
   canvas          = new TCanvas("canvas","Data",10,10,1100,600);
}

test::~test()
{
tApp->Run();
}

void test::GetHistogram(Int_t i)
{
   energyHistogram->FillRandom("gaus",i*100);
}

void test::DrawHistogram(Int_t counter)
{
   if (counter==0) energyHistogram->Draw();
   else   energyHistogram->DrawClone("SAME");
   canvas->Update();
}


int main()
{
   test testclass;

   for(Int_t i=0;i<10;++i)
   {
      testclass.GetHistogram(i);
      testclass.DrawHistogram(i);
   sleep(2);
   }

   return 0;
}

There are two problems with Olivier’s code:

  1. the very first “histogram slice” (i = 0) is gone from the picture -> in the end one gets 9 “lines” instead of 10 (with my code one always gets 10)
  2. the statistics box is wrongly displayed (I also had this problem in my code but I fixed it)

There’s also a question: what is more suitable -> TH1F::DrawCopy or TObject::DrawClone

Hi,
thanks for your help, works fine here, but still not in my program, strange.
Does the re-definition of
energyHistogram = new TH1F();
for every single histogram have any influence? I mean the borders are the same but the name changes constantly. In fact the energyHistogram points to Histograms in a root file, so the name is changed every time.

And the second thing as Pepe mentioned, is DrawCopy or DrawClone the better way (considerung CPU power) :slight_smile:

Regards

It was just to show “the idea”… :slight_smile:

You can’t find any call to the default constructor “new TH1F();” in my code, can you?

If you read your histograms from a file, try something like this … [code]void test::GetHistogram(Int_t i)
{
// MyTFile resident “MyTH1F_0”, “MyTH1F_1”, “MyTH1F_2”, …
MyTFile->GetObject(TString::Format(“MyTH1F_%d”, i), energyHistogram);
if (!energyHistogram) {
std::cout << “Warning: histogram : " << i << " : NOT FOUND!” << std::endl;
}
}

void test::DrawHistogram(Int_t counter)
{
canvas->cd(0); // make sure it will be drawn in the "canvas"
if (energyHistogram) { // just a precaution
if (!counter) energyHistogram->Draw(); // or Draw(“AXIS”);
// energyHistogram->DrawClone(“SAMES”); // TObject::DrawClone
energyHistogram->DrawCopy(“SAMES”); // TH1F::DrawCopy
}
canvas->Update(); // or canvas->Modified(); canvas->Update();
}[/code]

The TH1F::DrawCopy versus TObject::DrawClone question is not about “CPU power”. It’s about what owns these “clones”, where they reside, who deletes them (when the canvas is cleared or deleted) and so on.