MATLAB: Axis Setup (Basic)

In my infernal quest to get everyone to make better figures, I thought I would discuss the function I use for custom axis setups. In two previous posts, I discussed how to set up the Figure window to generate figures to size and how to print those to file with arbitrary DPIs in both vector and raster formats. One of the things I left out in those discussions is how I format the contents inside of the figure box. This is to ensure font sizes, font types, grids, etc. all conform to a desired standard that is scaled appropriately for my figures. In the past when I blogged about this on the old GEARS blog, I used a function that was fixed and primarily used for formatting figures for publications that were designed to be single column figures. Since I have switched to lecturing using PowerPoint, I had to adapt the function to account for figures for lectures versus figures for publications. Also, I wanted something more adaptable that could account for figures that might need to span two columns or that might need two y-axes. In the past, I used to make separate template files for these but that has grown somewhat cumbersome to maintain through different MATLAB versions.

Objectives for Axis Setup Function

There are a few discrete things I wanted this function accomplish, all while requiring a minimal amount of input from me. The less input variables I must remember, the better. So with this function, I tried to accomplish the following:

  • Variable Axis Sizing: Since I wanted to make figures for lectures and for publications, there are times that I generate figures with vastly different figure sizes. Given that I like to draw all of my figures to scale, I wanted to pass into a full ‘Position’ matrix that will specify the starting horizontal and vertical locations, as well as width and height in units of centimeters. This way, whether I have a figure that is 8 cm wide for a single column, 16.5 cm wide for a figure spanning two columns, or some custom size for lectures, I can account for this.
  • Variable Font Sizing: The biggest different in making figure for lectures and figures for publication is the font size. Projecting to the board requires a minimum of 20 pt font sizes for the axis titles, while figures for publication usually have 9 pt or 10 pt font sizes for axis titles. Aesthetically, it is a little nicer to have a variation between the axis title and axis label. So for this function, I pass through a fontsize and adjust the axis labels to 1 pt smaller than the axis titles.
  • Dual Y-axis Plotting: The last pass through variable that I needed, after some trial and error, is an axis label other than ‘gca’. When formatting an axis in general, changing attributes can be solved by some form of ‘set( gca , ‘PropertyName’ , propertyvalue , …)’. Get Current Axis, or gca, is used to apply those property changes to the current axis without specifying any particular axis. If you have several plots open at once and you did not specify axis handles for them, this would require you to click on the figure you want to change to make it “active” (i.e., the current figure axis). When you generate a plot with two Y-axes, you are actually making two separate plots that must be overlaid. By generating your plots with a specific axis handle, you can the formatting properties of both of the overlaid axes to ensure uniform formatting.
  • Grid Lines: In previous versions of MATLAB, grid line color was tied to the ‘Box’ color attribute. Making a figure with a black border but with grey lines required overlaying two identical figures, one with grid lines changed to grey and one without gridlines whose ‘Box’ property was set to [0 0 0] (black in RGB space). Sidebar – when making a Dual Y-axis Plot, that meant 4 separate axes where needed. Some of my original GEARS posts discussed how to do this. However, all of that is not necessary anymore. Axes now have ‘GridColor’ and ‘MinorGridColor’ properties than can be changed using normal RGB commands. Also, I’ve changed the default ‘GridLineStyle’ to ‘-‘ (solid lines) as opposed to the native ‘:’ (dotted lines) format. I think this looks cleaner.
  • MinorGrids: Another change that MATLAB made in recent versions (well, at least since my original posts were written) is increase the number of minor grid lines that the figure natively prints. Their change has effectively ruined minor grid lines for non-log plots IMHO. However, for log axis plots, minor grid lines are handy and actually help convey that the data is on a log scale. For this function, I’ve included code in there to toggle minor grid lines on for axes that are plotted on a log scale and remove them for linear axes.
  • Trailing Zeros: Another pet-peeve of mine is non-uniform trailing zeros. If you ever have tick marks in spacings of 0.25, then each tick mark will have a different number of trailing zeros shown. I prefer to have all of my graphs with the same number of trailing zeros. This can be done by modifying the tick label and changing it to a string.
  • Fonts and Colors: The last major thing I have this function do for me is change the default fonts to ‘Times New Roman’. Most journals use some form of a serif font and if you use equations or variables in your axis labels, then I find it better to keep uniform formatting as equations should be in Times New Roman. This makes figure text slightly thinner for lectures but I didn’t want to institute yet another flag in the function inputs to account for this.

In addition to changing the fonts, I also pass through any ‘Color’ property on the axis labels (xlabel, ylabel, etc.). When making dual Y-axis plots, I find it helpful to convey the information with lines that have a similar color (e.g., reds) plotted with the axis label that same color (red), and the data on the other axis to be a different color (e.g., blue) with a correspondingly similar label color (blue).


AxisSetup Function

The AxisSetup function takes three input variables, ‘ax’ which is the axis handle, ‘pos’ which is a standard ‘Position’ matrix ([w0 h0 w h]) in units of centimeters, and ‘FS’ which is the desired font size. All of these must be described or the functions craps out. Also, remember, this function is meant to be used with the function FigureSetup (previously described). WordPress doesn’t like *.m-files so I have included a *.txt file here or you can copy the function below.

function AxisSetup(ax,pos,FS)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function ‘AxisSetup’:
%
% Establishes axes to fit inside a figure box. This function is intended to
% be combined with ‘FigureSetup’ for making custom sized figures for
% publications.
%
% Input Variables:
%
% ax: axis handle from the original plot.
% pos: standard 1×4 matrix for position in units of centimeters
% [x0 y0 w h] .
% FS: font size for the axis labels.
%
% Usage Notes: Before running this command, you should set your axis labels
% (xlabel, ylabel, etc.), axis limits (axis, XLim, YLim, etc.), and tick
% marks for the axes. The font size for the axes will be 1 point smaller
% than for the labels, which is set by input “FS”. Also, if you used a
% ‘Color’ command for you labels, this command will get carried over to the
% ‘XColor’, ‘YColor’ for each axis. This is useful for plotyy figures where
% the respective y-axes may be denoted by different colors.
%
% Written by Jonathan D. Ellis, PhD
% Updated September 25, 2015
% Version: 1.00
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

A = size(ax);

Xsize = 0;
Ysize = 0;

for i = 1:A(2)

% Create xlabel
xhold = get(ax(i),’xlabel’);
xlabel(get(xhold,’String’),’FontSize’,FS,’FontName’,’Times New Roman’);

% Create ylabel
yhold = get(ax(i),’ylabel’);
ylabel(get(yhold,’String’),’FontSize’,FS,’FontName’,’Times New Roman’);

% Create zlabel
zhold = get(ax(i),’zlabel’);
zlabel(get(zhold,’String’),’FontSize’,FS,’FontName’,’Times New Roman’);

% Make the Axes look sexy
set(ax(i),…
‘YGrid’,’on’,…
‘XGrid’,’on’,…
‘XColor’,get(xhold,’Color’),…
‘YColor’,get(yhold,’Color’),…
‘Units’,’centimeters’,…
‘Position’,pos,…
‘GridAlphaMode’,’manual’,…
‘GridColor’,[0 0 0],…
‘GridAlpha’,0.1,…
‘LineWidth’,0.25,…
‘GridLineStyle’,’-‘,…
‘FontSize’,FS-1,…
‘FontName’,’Times New Roman’);

% Add Minor Grids if X axis is log plot
if isequal( ax(1).XScale , ‘log’ ) == 1
set(ax(i),…
‘XMinorGrid’,’on’,…
‘MinorGridLineStyle’,’-‘,…
‘MinorGridColor’,[0 0 0],…
‘MinorGridAlpha’,0.05)
else
% Make uniform number of trailing zeros
xticks = ax(i).XTickLabel;
for j = 1:length(xticks)
B = char( xticks(j) );
N = length(B) – find( B == ‘.’, 1 , ‘first’ );
if N > Xsize
Xsize = N;
end
end
ax(i).XTickLabel = sprintf([‘%0.’,num2str(Xsize),’f\n’],ax(i).XTick);
Xsize = 0;
end

% Add Minor Grids if Y axis is log plot
if isequal( ax(1).YScale , ‘log’ ) == 1
set(ax(i),…
‘YMinorGrid’,’on’,…
‘MinorGridLineStyle’,’-‘,…
‘MinorGridColor’,[0 0 0],…
‘MinorGridAlpha’,0.05)
else
% Make uniform number of trailing zeros
yticks = ax(i).YTickLabel;
for k = 1:length(yticks)
B = char( yticks(k) );
N = length(B) – find( B == ‘.’, 1 , ‘first’ );
if N > Ysize
Ysize = N;
end
end
ax(i).YTickLabel = sprintf([‘%0.’,num2str(Ysize),’f\n’],ax(i).YTick);
Ysize = 0;
end
end
end


Simple AxisSetup Usage

First, start out by creating some fake data to plot.

>> t = linspace(0,10,1000)’;

>> A = sin(2*pi*1*t);

Next, generate your base figure box using FigureSetup, generate a generic axis with a handle (critical step!), and plot your data into that axis handle.

>> FigureSetup(1)

>> AX=axes;

>> plot( AX , t , A );

After that, you have your basic figure generated. Now, at this point, we’re missing some axis labels so let’s add those.

>> xlabel(‘Time [s]’);

>> ylabel(‘Signal [arb.]’);

At this point, your figure should look like this.

AxisSetup_Base

The fonts are still in sans serif and the font sizes aren’t specified. Also, there are no grids. Now, it is time for AxisSetup. You should notice there is some usable white space on the left and right sides of the figure. We can use the ‘pos’ matrix to stretch our axes a little bit to make things a bit wider.

>> AxisSetup( AX , [1.1 1.1 6.9 3] , 10 );

You may need to play around with the ‘pos’ values to get the axis the correct size. This is why it is helpful to always put your plotting commands in a separate cell and only call one figure at a time. If you are serious about making your data look good for publications, chances are that some asshole particular Reviewer may still want you to change something in figure. Should you need to do this, you should be able immediately reproduce this figure and quickly make changes to it. If you used the above commands, then you should see this as your figure.

AxisSetup_Fixed

Most people can stop right there in generating their figure. However, I prefer to spice it up a little more. For a figure like this, there’s two things that bother me. 1) I dislike when the data runs right up to the edge of the plot, and 2) there aren’t enough tick marks for me. These are easily solved with ‘axes’ and ‘XTick’/’YTick’ commands. The axis command lets you change the limits of the axes, so bumping the Y-axis limits to -1.2 and 1.2 gives a little room between the data and the end of the axis. Next the Ticks can be set to increase the number of ticks and number of lines that ‘Grid’ uses.

>> axis([0 10 -1.2 1.2])

>> set( AX , ‘YTick’ , -1.2:.4:1.2 );

>> set( AX , ‘XTick’ , 0:10 );

If you do this, then you should get a slightly fancier figure. One thing you should remember is that if you start changing the ‘YTick’ vector, if you start adding decimal places, you may need to resize your ‘pos’ command in ‘AxisSetup’ to make the figure fit.

AxisSetup_Fancy


Log AxisSetup Usage

Using AxisSetup is also possible for ‘loglog’, ‘semilogx’, and ‘semilogy’ plots. Remember, the function natively checks for a log axis and turns on the minor grid lines to make it more distinctly log-ish. Let’s assume you have a function that can take signal A from above and compute the single-sided Fourier Spectrum. (This is a simple task that I have my undergrad students do as part of their class; I’ll discuss this code at a later date.) In this case, I’ve added in some Gaussian noise so I don’t get weird loops in the Fourier Spectrum from calculating using a perfect signal. If I do that, and then plot the single sided Fourier Spectrum as a function of frequency, you get the following:

>> [freq,mag] = custom_fft( A+(.1.*randn(size(A))) , 1/mean(diff(t)));

>> FigureSetup(1)

>> AX = axes;

>> loglog( AX , freq , mag );

>> xlabel(‘Frequency [Hz]’)

>> ylabel(‘Amplitude [arb.]’)

AxisSetup_FFT_Basic

Like before, you need to generate your figure window, set up your axes, then ‘loglog’ your data. I’ve added labels here as well. The resulting figure illustrates a bunch of things that bother me when people don’t care about how they present their data. Aside from the fonts being incorrect and the grid missing, each of the axis tick marks have 2 orders of magnitude (100x) between their values! This is huge and there is plenty of room to add ticks. Also, on the low frequency and amplitude side, there is no reason you need to go to 10-2 Hz or 10-4 signal amplitude; both can be truncated.

To correct this, you first use the ‘axis’ command to set your limits correctly. Then, you can build ‘XTick’ and ‘YTick’ vectors as before. Even though the data is plotted on a log scale, the same rules apply.

>> axis([1e-1 1e2 1e-3 1e0])

>> set( AX , ‘XTick’ , [1e-1 1e0 1e1 1e2] , ‘YTick’ , [1e-3 1e-2 1e-1 1e0] );

>> AxisSetup( AX , [1.2 1.2 6.7 3] , 10 );

Now when you plot this, the axes are properly truncated and more tick marks better illustrate that this data is plotted on a log scale. Plus, the fonts, sizes, and axis placement are all fixed. There is even a subtle change for the grid. I’ve set the code to make a slightly darker line for the major axes as opposed to the minor axes. I find this better emphasizes the grid and is easier to delineate factors of ten.

AxisSetup_FFT_Fancy

Here is a AxisSetup (once again in *.txt format) that contains the plotting commands listed above in cell form.

I hope this give you some valuable info on how to format graphs for publications. In this template, only went over basic linear and log plots, and left off the Dual Y-axis Plots. I’ll save that for a follow up template. There, the functions for formatting the figure window (FigureSetup), changing the axes (AxisSetup), and printing to file (PrintRoutine) will be the same. The only difference will be in the basic setup commands for plotting.