Search code examples
matlabmatlab-figureaxes

Axes ticks of same length across subplots in MATLAB


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.


Solution

  • 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.