My Matlab plotting workflow
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
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 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');
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 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');
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]);
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]);
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
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');