Disclaimer: This post is not complete but it will be updated regularly. Feel free to give me suggestions to improve my workflow or add some missing information.

In this post I would like to discuss my workflow to produce appealing figures for scientific articles. In the latest releases of Matlab (>R2020a), Mathworks introduced a more streamlined approach to the way we can create good looking figures. We will start from the creation of a simple figure and build on top of it more complex figures. The goal is to have a final figure that integrates nicely with a Latex document.

Figure structure

Roughly, a figure in Matlab is composed by a collection of axes and a title. Every axes object has a title of its own, labels, ticks, and a legend.

figure
+-- title
+-- axes
    +-- title
    +-- labels
    +-- ticks
    +-- legend

Simple figure

A simple Matlab figure

The simplest figure should have some axes with data plotted.

First we can create a new figure with the figure() command

fig = figure();

Then we can plot our data with the plot() command

plot(x_data,y_data);

In the background Matlab uses a renderer in order to produce the graphics. I like to use the painters renderer since it has a better behaviour on my Linux laptop and it is the appropriate option to export vector graphics, since it supports also vector graphics for 3D plots. In order to enable painters by default we can include the following command at the start of our code file

set(0, 'DefaultFigureRenderer', 'painters');

By default, Matlab clears the figure when plotting new data. In order to be able to plot more (including adding a title) than once it is important to include the command

hold on;

after creating the figure. Then a second set of data can be plotted using the plot command

plot(x_data,0.5*y_data);

The whole code so far:

clear all
close all

set(0, 'DefaultFigureRenderer', 'painters');

%% DATA TO PLOT %%

x_data = linspace(0,3*pi,200);
y_data = sin(x_data);

%% FIGURE %%

fig = figure();
hold on;
plot(x_data,y_data);
plot(x_data,0.5*y_data);

Titles

A simple Matlab figure with title

A title can be added to the figure by using the title() command.

title('Simple figure with title');

If the title is too long to fit in one line, it can be split in two lines as follows

title({'Simple figure with title','split in two lines'});

Moreover, a subtitle can be given by passing a second argument to the command

title('Simple figure with title', 'Subtitle');
A simple Matlab figure with title in two lines A simple Matlab figure with title and subtitle

The whole code so far:

clear all
close all

set(0, 'DefaultFigureRenderer', 'painters');

%% DATA TO PLOT %%

x_data = linspace(0,3*pi,200);
y_data = sin(x_data);

%% FIGURE %%

fig = figure();
hold on;
title('Simple figure with title');
plot(x_data,y_data);

Legend

A legend can be added to the data using the legend command

legend('sin(x)','0.5sin(x)');

The location of the legend can be adjusted as follows

legend({'sin(x)','0.5sin(x)'}, 'Location','southeast');

The options for the value of the location property and other legend properties can be found in this documentation page

A simple Matlab figure with legend A simple Matlab figure with legend

A legend for specific plot can be created by passing as first argument to legend() an array of the plot handles

ph1 = plot(x,y);
legend_txt{1} = 'sin(x)';
ph2 = plot(x,0.5*y);
legend_txt{2} = '0.5sin(x)';
legend([ph1,ph2], legend_txt);

The code so far:

clear all
close all

set(0, 'DefaultFigureRenderer', 'painters');


%% DATA TO PLOT %%

x = linspace(0,3*pi,200);
y = sin(x);

%% FIGURE %%

fig = figure();
hold on;
title('Simple figure with legend'); % the title of the figure

ph1 = plot(x,y);
legend_txt{1} = 'sin(x)';

ph2 = plot(x,0.5*y);
legend_txt{2} = '0.5sin(x)';

% legend('sin(x)','0.5sin(x)');
legend({'sin(x)','0.5sin(x)'}, 'Location','southeast');
% lh = legend([ph1,ph2], legend_txt);

xlim([0,3*pi]);
ylim([-1,1]);

Labels

Basic labels on the x, y and z axes can be added by the xlabel(), ylabel() and zlabel() commands respectively. For our purposes the z axis label does not need to be set

xlabel('x data');
ylabel('y data');

A simple Matlab figure with labels

The code so far:

clear all
close all

set(0, 'DefaultFigureRenderer', 'painters');


%% DATA TO PLOT %%

x = linspace(0,3*pi,200);
y = sin(x);

%% FIGURE %%

fig = figure();
hold on;
title('Simple figure with legend'); % the title of the figure

plot(x,y);
plot(x,0.5*y);

legend('sin(x)','0.5sin(x)');

xlabel('x data');
ylabel('y data');

xlim([0,3*pi]);
ylim([-1,1]);

Axes

New axes can be created by the axes() command and the position can be specified as follows

axes('Position', [0.1 0.1 0.7 0.7]);
axes('OuterPosition', [0.1 0.1 0.7 0.7]);

The code so far:

clear all
close all

set(0, 'DefaultFigureRenderer', 'painters');


%% DATA TO PLOT %%

x = linspace(0,3*pi,200);
y = sin(x);

%% FIGURE %%

fig = figure();
ax1 = axes('OuterPosition', [0.05 0.05 0.4 0.9]);
hold on;
title('Title 1');
xlabel('x data 1');
ylabel('y data 1');
plot(x,y);
xlim([0 2*pi]);
ylim([-1,1]);

ax2 = axes('OuterPosition', [0.55 0.05 0.4 0.9]);
hold on;
title('Title 2');
xlabel('x data 2');
ylabel('y data 2');
plot(x,0.5*y);
xlim([0 2*pi]);
ylim([-1,1]);

A Matlab figure with two axes objects

Tiled layouts

The new tiled layout option in the newest versions of Matlab offers a more flexible and efficient way to create figures with multiple axes in a grid pattern compared to manual axis creation as described above or using the subplot() command available in older versions of Matlab.

The basic usage is the following:

fig = figure();
tl = tiledlayout(1,2);
nexttile;

The code for the tiled layout:

clear all
close all

set(0, 'DefaultFigureRenderer', 'painters');


%% DATA TO PLOT %%

x = linspace(0,3*pi,200);
y = sin(x);

%% FIGURE %%

fig = figure();
tl = tiledlayout(1,2);
title(tl,'Main Title');
nexttile;
hold on;
title('Title 1');
xlabel('x data 1');
ylabel('y data 1');
plot(x,y);
xlim([0 2*pi]);
ylim([-1,1]);

nexttile;
hold on;
title('Title 2');
xlabel('x data 2');
ylabel('y data 2');
plot(x,0.5*y);
xlim([0 2*pi]);
ylim([-1,1]);

A Matlab figure with two axes objects

Text

Beautification

Grid and Box

grid on;
box on;

Color palette

The color of a plot can be changed by specifying the 'Color' option when plotting

plot(x_data,y_data, 'Color', [1,0,0]);

or as

ph = plot(x_data,y_data);
ph.Color = [1,0,0];

More info can be found in the documentation.

Markers

When plotting with markers, usually the size of the markers has to be adjusted. Also, when the density of the data points is very high, the markers that are generated automatically may be too close together and completely cover the actual line. The properties of the markers can be adjusted by specifying the 'Markersize' and 'MarkerIndices' options

plot(x_data,y_data, '-o', 'Markersize', 5, 'MarkerIndices', 1:10:200);

Latexify

title('My Title', 'Interpreter', 'latex');
xlabel('$x_0$',  'Interpreter', 'latex');
legend({'$\sin x$', '$\frac{1}{2}\sin x$'}, 'Interpreter', 'latex');

My personal preferences

A Matlab figure with two axes objects

clear all
close all
set(0, 'DefaultFigureRenderer', 'painters');

%% DATA TO PLOT %%

x_data = linspace(0,3*pi,200);
y_data = sin(x_data);

%% FIGURE %%

figure_width = 160 % mm
figure_height = figure_width*0.8 % mm
axes_fontSize = 9 % pt
axes_tickInterpreter = 'latex'
axes_titleFontSizeMult = 1

linwidth = 0.3;
markersize = 5;
col{1} = [0,      0.4470, 0.7410];
col{2} = [0.8500, 0.3250, 0.0980];
col{3} = [0.9290, 0.6940, 0.1250];
col{4} = [0.4940, 0.1840, 0.5560];
col{5} = [0.4660, 0.6740, 0.1880];
col{6} = [0.3010, 0.7450, 0.9330];
col{7} = [0.6350, 0.0780, 0.1840];
linstyle{1} = '-';
linstyle{2} = '--';
linstyle{3} = '-.';
markerstyle{1} = 'o';
markerstyle{2} = 'd';
markerstyle{3} = 's';

secondary_linwidth = linwidth*0.5;
secondary_col = [1,1,1]*0.2;


fig = figure('units','centimeters','OuterPosition',[0,0,figure_width*0.1, figure_height*0.1]);

tl = tiledlayout(1,2, 'Padding','compact');

% --- First axes --- %
ax = nexttile;
ax.FontSizeMode = 'manual';
ax.FontSize = axes_fontSize;
% ax.LabelFontSizeMultiplier = 5;
ax.TickLabelInterpreter = axes_tickInterpreter;
ax.TitleFontSizeMultiplier = axes_titleFontSizeMult;

hold on; box on;
title('Title', 'interpreter','latex');

ph(1) = plot(x_data, y_data, [linstyle{1},markerstyle{1}],'color',col{1}, 'Markersize',markersize, 'MarkerIndices', 1:10:length(x_data));
legend_txt{1} = '$\sin(x)$';

index = 75;
xline(x_data(index), linstyle{2}, 'Linewidth', secondary_linwidth, 'Color', secondary_col);
yline(y_data(index), linstyle{2}, 'Linewidth', secondary_linwidth, 'Color', secondary_col);
ph(3) = plot(x_data(index), y_data(index), markerstyle{3}, 'Color', secondary_col, 'Markersize', markersize, 'MarkerFaceColor', secondary_col);
legend_txt{3} = 'Black marker';

xlabel('x data 1', 'interpreter','latex');
ylabel('y data 1', 'interpreter','latex');
xlim([0 2*pi]);
ylim([-1,1]);

% --- Second axes --- %
ax2 = nexttile;
ax2.FontSizeMode = 'manual';
ax2.FontSize = axes_fontSize;
% ax.LabelFontSizeMultiplier = 5;
ax2.TickLabelInterpreter = axes_tickInterpreter;
ax2.TitleFontSizeMultiplier = axes_titleFontSizeMult;

hold on; box on;
title('Title', 'interpreter','latex');

ph(2) = plot(x_data, 0.5*y_data, [linstyle{1},markerstyle{2}],'color',col{2}, 'Markersize',markersize, 'MarkerIndices', 1:10:length(x_data));
legend_txt{2} = '$0.5\,\sin(x)$';

xlabel('x data 2', 'interpreter','latex');
ylabel('y data 2', 'interpreter','latex');
xlim([0 2*pi]);
ylim([-1,1]);

legend(ax2, ph, legend_txt, 'interpreter','latex');