How to draw more than two histograms with adjacent axises

I am wondering if there is any easy way to display multiple histograms with a common x-axis keeping each height of the histogram frames equal to one another.
What I want to do is to place three or more histograms as done in zone.C, a tutorial macro.
zone.C works fine if the number of division is two along vertical or horizontal direction.
But in the case where one divides a Canvas into three or more sub pads via TCanvas::Divide(),
the histograms drawn in the top or bottom pads become smaller than others due to the margins the top and bottom pads have.
To avoid this, we need to create sub pads specifying their sizes calculated from the margins to be left.
But it is quite a hassle…
In PAW, combination of zone command and “set ywin 0” can set margin between histograms to zero without changing the size of histogram frames.
I hope ROOT also provides an easy way to do this.

–
kame

When you call TPad::Divide you can specify the distance between pads

void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0);

Rene

Thank you for the reply.

I am sorry if my explanation above was not very clear.

This function can specify the margin between pads, but I do not think that solves the problem, because the Canvas needs such division that top pad and bottom pad become larger than other pads to meet the requirement that the margins between axises of adjacent histograms are zero and the top and bottom pads have spaces for axis label, title, and so on.

By definition a division algorithm cannot do this work. What you want is an algorithm
that optimizes automatically the pad dimensions and margins such that the
internal frames have the same size.
This could be possibly implemented,but
requires more thinking.

Rene

In attachement you will find an example with 3x3

Rene
di33.C (2.53 KB)

It woluld be nice if this is implemented for any number of division
as a member function of TPad with name SmartDivide or somethng:)

Thank you anyway.

kame

In the CVS version, I have modified TPad::Divide such that when the function is called with xmargin=0 and ymargin=0
you get subpads with no space.
the frames in the subpads have the same size.
The macro below produces the picture in the attachement.

Rene

void divpad(Int_t nx=3, Int_t ny=2) {
TCanvas c1 = new TCanvas(“c1”);
c1->Divide(nx,ny,0,0);
Int_t number = 0;
TH1F h = new TH1F(“h”,“h”,100,-3.3,3.3);
h->GetXaxis()->SetLabelFont(53);
h->GetXaxis()->SetLabelSize(10);
h->GetYaxis()->SetLabelFont(53);
h->GetYaxis()->SetLabelSize(10);
h->SetMaximum(30
nx
ny);
h->SetFillColor(42);
for (Int_t i=0;i<nx*ny;i++) {
number++;
c1->cd(number);
h->FillRandom(“gaus”,1000);
h->DrawCopy();
}
}


1 Like

I built the cvs version and tested the new function of TPad::Divide.
It was almost exactly what I hoped. Thank you very much.

The followings are two ideas that occured to me.

First, I think it would be more useful if size of gap between adjacent axises
can be specified by additional argument.
Sometimes I leave a small gap between the axises as shown in attached image
because the minimum value of the orthogonal axis is important and
desired to be kept from being hidden.

The second, even more trivial, is that the label and title of axis become larger for larger pad
because their sizes are specified relatively to the pad size.
Is it possible to specify their sizes by pixel or relative value to the mother pad(canvas)?

–
kame


In my example above, I show how to set a font size in pixels (using precision 3)
see: root.cern.ch/root/htmldoc/TAttText.html

h->GetYaxis()->SetLabelFont(53);
h->GetYaxis()->SetLabelSize(10); 10 pixels

By default Tpad::Divide keeps a margin between pads (xmargin, ymargin).
You can also tune yourself the margin for each pad via eg:
pad->setTopMargin(0.02);

Rene

[quote=“brun”]In my example above, I show how to set a font size in pixels (using precision 3)
see: root.cern.ch/root/htmldoc/TAttText.html
[/quote]

I didn’t know that. Thanks.

[quote=“brun”]By default Tpad::Divide keeps a margin between pads (xmargin, ymargin).
You can also tune yourself the margin for each pad via eg:
pad->setTopMargin(0.02);
Rene[/quote]

The present TPad::Divide enforces zero space between adjacent axises
and enables the algorithm that keeps the size of internal frames equal
if the argument xmargin or ymargin is zero or nagative.
I want to leave small spaces between adjacent axis enabling this algorighm.
What about the idea that the space of |xmargin| or |ymargin| is made
when negative value of xmargin or ymargin is specified ?

–
kame

I realize right after I posted that pad->SetTopMargin(small) and pad->SetBottomMargin(small) can easily meet my requirement above,
and leaving margins between sub pads does not.
Sorry for bothering and thank you again.

–
kame

I found the height of the histogram frame drawn in the bottom pad to be slightly shorter than others
when sub pads are created via canvas->Divide(1, 4, 0, 0).
I guess the algorithm still needs some modification.
I read the source but found it a little too complicated for me to understand
in a short time.

–
kame

There are also one question for me. How to adjust the title position into the center with a common x- and/or y-axis?

Welcome to the ROOT forum

   your_histo->GetXaxis()->CenterTitle(true);
   your_histo->GetYaxis()->CenterTitle(true);