3

I am creating a multi-panel figure in MATLAB (with multiple axes of different size). I would like all tick marks to have the same absolute size across all subplots.

According to the MATLAB user guide, tick length is normalized with respect to the longest axis:

TickLength. Tick mark length, specified as a two-element vector of the form [2Dlength 3Dlength]. [...] Specify the values in units normalized relative to the longest of the visible x-axis, y-axis, or z-axis lines.

In order to make all ticks of the same length, I am running the following code:

fixlen = 0.005;                       % Desired target length
for i = 1:numel(h)                    % Loop over axes handles
    rect = get(h(i),'Position');      % Get the axis position
    width = rect(3);                  % Axis width
    height = rect(4);                 % Axis height     
    axislen = max([height,width]);    % Get longest axis
    ticklen = fixlen/axislen;         % Fix length
    set(h(i),'TickDir','out','TickLength',ticklen*[1 1]);
end

Unfortunately, the above code does not produce a figure in which all tick lengths are equal. Perhaps I am missing something?


Solution. There were two problems in my code.

  1. First of all, I needed to switch from Normalized units to some fixed units (such as pixels). See the answer below.

  2. In some part of the code, before the above snippet, I was resizing the figure and I had a drawnow to update it. However, MATLAB would reach the code snippet before the graphics commands had been executed, and therefore the reported sizes were not correct. I solved the issue by placing a pause(0.1) command after the drawnow.

lacerbi
  • 174
  • 7

1 Answers1

1

By default, Axis objects have their Units property set to normalized. This means that the values in the Position property are normalized by the size of the figure. Hence your code may not be producing the desired behavior if the figure is not square.

One way to fix this is the following:

rect = get(h(i),'Position');     % Axis position (relative to figure)
hfig = get(h(i),'Parent');       % Handle to parent figure
rectfig = get(hfig, 'Position'); % Figure position (in pixels)
width = rect(3) * rectfig(3);    % Absolute width of axis (in pixels)
height = rect(4) * rectfig(4);   % Absolute height of axis (in pixels)

This will give you width/height in terms of pixels on your screen (assuming that you didn't change the Units property of the figure).

And if you use rectfig = get(hfig,'PaperPosition') then you will get width/height in terms of inches on the printed page (again, assuming default value for the figure's PaperUnits property).

Note, however, that you will need to adjust the value you use for fixlen to match the new units we're using here.

KQS
  • 1,547
  • 10
  • 21
  • (+1) Thanks. Yes, in the meanwhile I figured out that Units might be the key. However, I implemented one solution that *should* have fixed it, but didn't. Now I also tried your proposed solution too, and the problem persists; ticks still end up being of different sizes. – lacerbi Sep 08 '16 at 00:56
  • 1
    Well, my code assumed that the axis `Units` were still set to `normalized` and the figure `Units` set to `pixels`, so if that has changed then it wouldn't work. What was the other solution that *should* have fixed it? Can you add some code to your question that produces example axes with unequal ticks? And just to check: you're not resizing/maximizing the figure after setting the tick length, are you? – KQS Sep 08 '16 at 01:08
  • Okay, found the solution. In some part of the code, *before*, I was resizing the figure and I had a `drawnow` to update it. However, MATLAB would reach the part below probably before the graphics engine. I solved the issue by placing a `pause(0.1)` command after the `drawnow`. – lacerbi Sep 08 '16 at 01:08
  • 1
    Ah, that's a good catch! Yeah, sometimes there can be some weird synchronization issues with the graphics – KQS Sep 08 '16 at 01:09