Inconsistent tick length

I have noticed this problem with tick length for years, but recently I made a concerted effort to figure it out and still had no luck.

I have a canvas with a large pad and a small pad (to display histograms and data/MC ratios). I want the tick lengths to be the same for every axis on each pad. TAttAxis:SetTickLength just says:

[quote] Set tick mark length
The length is expressed in per cent of the pad width[/quote]

I think this cannot be correct. I try to set their sizes as follows:

	double pad1W = pad1->GetWw()*pad1->GetAbsWNDC();
	double pad1H = pad1->GetWh()*pad1->GetAbsHNDC();
	double pad2W = pad2->GetWw()*pad2->GetAbsWNDC();
	double pad2H = pad2->GetWh()*pad2->GetAbsHNDC();
	//ratio->GetYaxis()->SetTickLength(12/pad2W);
	ratio->GetYaxis()->SetTickLength(12/pad2H);
	ratio->GetXaxis()->SetTickLength(12/pad2H);
	//histo->GetYaxis()->SetTickLength(12/pad1W);
	histo->GetYaxis()->SetTickLength(12/pad1H);
	histo->GetXaxis()->SetTickLength(12/pad1H);

This produces equal lengths for the x-axes, but not for the y-axes. If I switch the y-axis definitions to be in terms of the width instead of height (commented lines above), it still does not produce equal lengths. A full working macro and associated plot image are attached to demonstrate the problem.

The question here is: how are the displayed tick lengths actually calculated?



ticktest.C (2.68 KB)

If the pads have the same width the Y ticks will have the same size.
You have nothing to do.

{
   TH1F* h1 = new TH1F ("h1", "h1", 100, 0, 1);
   TH1F* h2 = new TH1F ("h2", "h2", 100, -1, 0);

   TCanvas *c = new TCanvas("c","c",600,400);
   c->Draw();

   TPad *p1 = new TPad("p1","p1",0.1,0.3,0.9,0.9);
   p1->SetFillColor(kYellow);
   p1->Draw(); p1->cd();
   h1->Draw();
   h1->GetYaxis()->SetNdivisions(5);

   TPad *p2 = new TPad("p2","p2",0.1,0.1,0.9,0.3);
   p2->SetFillColor(kGreen);
   c->cd(); p2->Draw(); p2->cd();
   h2->Draw();
   h2->GetYaxis()->SetNdivisions(5);
}

I think I’ve figured out what causes the problem based on your example, but I’m still not sure how to solve it.

Another macro is attached, with everything removed except the cause of the problem: changing the pad margins. Even though both pads have the same width and are set to have the same left and right margins, the y-axis tick length changes. Do you know why setting the margins would change the tick length?

Scaling the x-axis tick lengths by the pad heights still works to make them equal (commented out in the attached macro).
ticktestmin.C (1.38 KB)

If you play interactively with the pad size you can see that the tick size varies when you change the size/margins. I will try to figure out a way to have the same tick size.

Thanks for looking at this. Any progress yet? Do you know where the displayed tick length gets modified in the code?

Yes I looked at it… but it is more due to the fact the tickling is a percentage of the access length define in % of the Pad (not canvas) coordinates… I was thinking to have a way to define the tick length some absolute way… but this requires more developments. Not sure I’ll be able to do it before the Christmas break.

Have you had any more time to look at this yet? If you point out where in the code it modifies the tick length, I can try to look at it myself.

It is in TGaxis::PaintAxis. You are welcome to look. I had some other bugs to fix.

Thanks! I was able to figure it out after some inspection of the source code.

The tick size in TGaxis::PaintAxis() is calculated here: root.cern.ch/root/html/src/TGaxis.cxx.html#980

The additional scaling by the factor axis_length is key here. I followed the calls of axis.PaintAxis() from THistPainter::PaintAxis() (root.cern.ch/root/html/src/THis … tml#leUXUC) to see what quantities were used to calculate axis_length. Essentially, it is the fractional length of the axis within the pad. The attached macro tickfix1.C shows how to scale the user-input tick length using the calculation of the axis length from pad quantities. It multiplies the relevant axis length by the relevant pad dimension (y-axis length * pad width, or x-axis length * pad height).

However, to do the calculation in this way, it is necessary to draw the histogram, update the pad, and then draw it again after rescaling the tick marks. Because I set the margins by hand, it is possible to determine the axis_length value in a simpler way without needing to update the pad. The attached macro tickfix2.C shows this simpler calculation. The results for both macros (which are identical, as intended) are attached as pngs.



tickfix2.C (1.76 KB)


tickfix1.C (1.98 KB)

1 Like