Discussion:
[ROOT] Histograms on TCanvas without space between them
(too old to reply)
Kay Ulbrich
2004-04-06 18:12:31 UTC
Permalink
Hello,

there was a similar thread some time ago about creating simple
"PAW-style" plots, i.e., histograms stacked right one above the other
and one next to the other without space between them, thus making them
share axes:
http://root.cern.ch/root/roottalk/roottalk02/1939.html

Following the advices, I am able to generate such figures
by using TCanvas::Divide(nx, ny, 0, 0) and in sub pads the
TAttPad::Set[Left,Right,Top,Bottom]Margin(0) - functions in an
appropriate manner.

However, as the histograms "outside" have to have axes and axis
labels, they will be narrower than the ones inside. If only four
histograms are arranged 2x2, this is no problem, all histograms can be
"trimmed" symmetrically. But if "inner" histograms exist, they
invariably will be bigger than the outer ones, because all the margins
of the pads containing them have to be set to 0 in order for them to
touch the neighbouring histograms.

Is there a straightforward way to avoid this?

Furthermore, I could find no way of taking the thus generated figure
and then adding margins to the figure as a whole without changing the
size ratios of the histograms in the figure. I would need such margins
in order to add axis titles common to all x- or y-axes, thus placing
them relative to the coordinates of a structure containing the figure
with all the histograms. My first guess was, to draw the old TCanvas
in a new one via DrawClone() and then setting the margins of the new
TCanvas appropriately. This did not work.

Maybe I am doing something simple in a too complicated manner?

Thank you for hints,
Kay
Olivier Couet
2004-04-06 19:12:40 UTC
Permalink
Hi,

Have you a little example illustrating your problem ?

Cheers, Olivier
Post by Kay Ulbrich
Hello,
there was a similar thread some time ago about creating simple
"PAW-style" plots, i.e., histograms stacked right one above the other
and one next to the other without space between them, thus making them
http://root.cern.ch/root/roottalk/roottalk02/1939.html
Following the advices, I am able to generate such figures
by using TCanvas::Divide(nx, ny, 0, 0) and in sub pads the
TAttPad::Set[Left,Right,Top,Bottom]Margin(0) - functions in an
appropriate manner.
However, as the histograms "outside" have to have axes and axis
labels, they will be narrower than the ones inside. If only four
histograms are arranged 2x2, this is no problem, all histograms can be
"trimmed" symmetrically. But if "inner" histograms exist, they
invariably will be bigger than the outer ones, because all the margins
of the pads containing them have to be set to 0 in order for them to
touch the neighbouring histograms.
Is there a straightforward way to avoid this?
Furthermore, I could find no way of taking the thus generated figure
and then adding margins to the figure as a whole without changing the
size ratios of the histograms in the figure. I would need such margins
in order to add axis titles common to all x- or y-axes, thus placing
them relative to the coordinates of a structure containing the figure
with all the histograms. My first guess was, to draw the old TCanvas
in a new one via DrawClone() and then setting the margins of the new
TCanvas appropriately. This did not work.
Maybe I am doing something simple in a too complicated manner?
Thank you for hints,
Kay
--
Org: CERN - European Laboratory for Particle Physics.
Mail: 1211 Geneve 23 - Switzerland Mailbox: J25910
E-Mail: ***@cern.ch Phone: +41 22 7676522
WWW: http://cern.ch/Olivier.Couet/ Fax: +41 22 7677155
Kay Ulbrich
2004-04-07 12:17:57 UTC
Permalink
--5SvK5nHaes
Content-Type: text/plain; charset=us-ascii
Content-Description: message body and .signature
Content-Transfer-Encoding: 7bit
Post by Olivier Couet
Hi,
Have you a little example illustrating your problem ?
Cheers, Olivier
Post by Kay Ulbrich
Hello,
[ ... a lot loquatious of talk by me ... ]
Thank you for hints,
Kay
--
Org: CERN - European Laboratory for Particle Physics.
Mail: 1211 Geneve 23 - Switzerland Mailbox: J25910
WWW: http://cern.ch/Olivier.Couet/ Fax: +41 22 7677155
Hello Olivier,

thank you for your prompt answer. Sorry, that it took me some time to
give an example, because I have encapsuled the
margin-set-functionality in a separate class derived from TCanvas.

Anyway, the example (a modfied one from Rene Brun in the thread I
mentioned first) does the same. So one sees, that the "middle"
histograms are wider than the outer ones. The same would apply to
the height, if I had more than 2 rows.

I actually want to have all histograms the same size. On the other
hand, I do not want to set ALL margins to 0 (this would do it),
because then I would have to add the axis labels manually i.e. by
using xfig.

I could live with adding the axis titles by an external program, but
here it would be nice as well to "embed" the canvas (c1 in the
example) centrally in a slightly bigger one and position
TPaveText-objects relative to the NDC of the bigger canvas.

I have seen PAW generated plots which looked as I would like, but I
have abstained from PAW and started with ROOT right away ...

Greetings,
Kay
--
======================================================================
Kay Ulbrich
Helmholtz-Institut fuer
Strahlen- und Kernphysik
der Universitaet Bonn Tel.: +49-228-73 1768
Nussallee 14-16 Institute FAX: +49-228-73 2505
D-53115 Bonn, Germany E-mail: ***@iskp.uni-bonn.de
======================================================================


--5SvK5nHaes
Content-Type: text/plain
Content-Description: The macro
Content-Disposition: inline;
filename="stack.C"
Content-Transfer-Encoding: 7bit

// example of script showing how to divide a canvas
// into adjacent subpads + axis labels on the top and right side
// of the pads.

#define ASPECT_RATIO (2.0/3.0) // Y / X
#define SCALE 10
#define X (100 * SCALE)
#define Y (X * ASPECT_RATIO)
void stack() {

TCanvas *c1 = new TCanvas("c1","multipads", X, Y);
c1->SetFixedAspectRatio(true);
gStyle->SetPadBorderMode(0);
gStyle->SetOptStat(0);
gStyle->SetOptTitle(0);
c1->Divide(3,2,0,0);
TH1F *h1 = new TH1F("h1","test1",20,-3,3);
h1->SetMarkerStyle(21);
h1->Sumw2();
TH1F *h2 = (TH1F*)h1->Clone("h2");
TH1F *h3 = (TH1F*)h1->Clone("h3");
TH1F *h4 = (TH1F*)h1->Clone("h4");
TH1F *h5 = (TH1F*)h1->Clone("h5");
TH1F *h6 = (TH1F*)h1->Clone("h6");

h1->FillRandom("gaus",500); h1->SetMaximum(80);
h2->FillRandom("gaus",300); h2->SetMaximum(80);
h3->FillRandom("gaus",900); h3->SetMaximum(130);
h4->FillRandom("gaus",500); h4->SetMaximum(130);
h5->FillRandom("gaus",500); h5->SetMaximum(130);
h6->FillRandom("gaus",500); h6->SetMaximum(130);

c1->cd(1);
gPad->SetBottomMargin(0);
gPad->SetRightMargin(0);
h1->Draw();

c1->cd(2);
gPad->SetLeftMargin(0);
gPad->SetBottomMargin(0);
gPad->SetRightMargin(0);
h2->Draw();

c1->cd(3);
gPad->SetLeftMargin(0);
gPad->SetBottomMargin(0);
h3->Draw();

c1->cd(4);
gPad->SetTopMargin(0);
gPad->SetRightMargin(0);
h4->Draw();

c1->cd(5);
gPad->SetTopMargin(0);
gPad->SetRightMargin(0);
gPad->SetLeftMargin(0);
h5->Draw();

c1->cd(6);
gPad->SetTopMargin(0);
gPad->SetLeftMargin(0);
h6->Draw();
}

--5SvK5nHaes--
Olivier Couet
2004-04-07 15:23:35 UTC
Permalink
Hi Kay,

When you do "Divide()" on a Pad it divides it in sub-pads laying on a
regular grid. Each TPad produced from that division contains a TFrame. The
SetXXXMargin methods act on the distances between that TFrame and the TPad
borders. So when you set the Left and right margins to zero for the middle
TPad(s) the TFrame inside get twice more space than its colleagues laying
in TPad(s) on borders. So TPads sizes should be adapted to handle that.
Here is a very small macro showing a possible way to do it:

void stack() {

TCanvas *c1 = new TCanvas("c1","multipads", 600, 500);
gStyle->SetOptStat(0);
gStyle->SetOptTitle(0);

Double_t W = 0.3; // Pad Width
Int_t Nx = 3; // Number of pads along X
Double_t Xm = (1-(Nx*W))/2; // X Margin
Double_t dw = (W*0.1)/4;

TPad *p1 = new TPad("p1", "p1", Xm, 0.2, Xm+W+dw, 0.8, 0, 0, 0);
p1->SetRightMargin(0);
p1->Draw();

TPad *p2 = new TPad("p2", "p2", Xm+W+dw, 0.2, Xm+2*W-dw, 0.8, 0, 0, 0);
p2->SetRightMargin(0);
p2->SetLeftMargin(0);
p2->Draw();

TPad *p3 = new TPad("p3", "p3", Xm+2*W-dw, 0.2, Xm+3*W, 0.8, 0, 0, 0);
p3->SetLeftMargin(0);
p3->Draw();

TH1F *h1 = new TH1F("h1","test1",20,-3,3);
TH1F *h2 = (TH1F*)h1->Clone("h2");
TH1F *h3 = (TH1F*)h1->Clone("h3");

h1->FillRandom("gaus",500); h1->SetMaximum(80);
h2->FillRandom("gaus",300); h2->SetMaximum(80);
h3->FillRandom("gaus",900); h3->SetMaximum(130);

p1->cd(); h1->Draw();
p2->cd(); h2->Draw();
p3->cd(); h3->Draw();
}

Cheers, Olivier
Post by Kay Ulbrich
Post by Olivier Couet
Hi,
Have you a little example illustrating your problem ?
Cheers, Olivier
Post by Kay Ulbrich
Hello,
[ ... a lot loquatious of talk by me ... ]
Thank you for hints,
Kay
--
Org: CERN - European Laboratory for Particle Physics.
Mail: 1211 Geneve 23 - Switzerland Mailbox: J25910
WWW: http://cern.ch/Olivier.Couet/ Fax: +41 22 7677155
Hello Olivier,
thank you for your prompt answer. Sorry, that it took me some time to
give an example, because I have encapsuled the
margin-set-functionality in a separate class derived from TCanvas.
Anyway, the example (a modfied one from Rene Brun in the thread I
mentioned first) does the same. So one sees, that the "middle"
histograms are wider than the outer ones. The same would apply to
the height, if I had more than 2 rows.
I actually want to have all histograms the same size. On the other
hand, I do not want to set ALL margins to 0 (this would do it),
because then I would have to add the axis labels manually i.e. by
using xfig.
I could live with adding the axis titles by an external program, but
here it would be nice as well to "embed" the canvas (c1 in the
example) centrally in a slightly bigger one and position
TPaveText-objects relative to the NDC of the bigger canvas.
I have seen PAW generated plots which looked as I would like, but I
have abstained from PAW and started with ROOT right away ...
Greetings,
Kay
--
Org: CERN - European Laboratory for Particle Physics.
Mail: 1211 Geneve 23 - Switzerland Mailbox: J25910
E-Mail: ***@cern.ch Phone: +41 22 7676522
WWW: http://cern.ch/Olivier.Couet/ Fax: +41 22 7677155
Loading...