# How to Make Better Plots in MATLAB: Plot Wrapper

This is third and final of a series of posts on plotting in MATLAB. This series is focusing on suggestions and considerations to get your plot looking “just right” for your paper or presentation. In the first post, I talked about how to improve the look of curves. In the second post, I talked about fixing up the text, including axis labels and legends. Here, I will talk about using a plot wrapper to automate most of your work. I will also talk about exporting your figure to whatever format you need.

## Recap

Where were we? At the end of the previous post, our last version of the plotting function was the following:

 numPlotPoints = 50; x = 1e-2:1e-2:100; % Smooth curves y1 = exp(-x); y2 = 1-exp(-x); % Noisy curves n = length(x); z1 = y1.*(1+0.005*randn(1,n)); z2 = y2.*(1+0.005*randn(1,n)); plotInd = unique(floor(logspace(0, log10(n), numPlotPoints))); hFig = figure; hAxes = axes('Parent',hFig,… 'FontSize',12,'XGrid','on', 'YGrid','on', 'Box', 'on',… 'TickLabelInterpreter', 'latex'); set(hFig, 'Color', 'w') hold('on'); plot(hAxes, NaN,NaN,'LineStyle', '-', 'Color', [0 0 0],… 'LineWidth', 1); plot(hAxes, NaN,NaN,'LineStyle', 'none', 'Color', [0 0 0],… 'LineWidth', 1, 'Marker', 'o'); plot(hAxes, x(plotInd),y1(plotInd),'LineStyle', '-', 'Color', [0 0 0],… 'LineWidth', 1); plot(hAxes, x(plotInd),y2(plotInd),'LineStyle', '-', 'Color', [0 0 1],… 'LineWidth', 1); plot(hAxes, x(plotInd),z1(plotInd),'LineStyle', 'none', 'Color', [0 0.6 0],… 'LineWidth', 1, 'Marker', 'o'); plot(hAxes, x(plotInd),z2(plotInd),'LineStyle', 'none', 'Color', [1 0 0],… 'LineWidth', 1, 'Marker', 'o'); xlabel('Time [s]', 'interpreter', 'Latex'); ylabel('Exponential Observation', 'interpreter', 'Latex'); legend(hAxes, 'Analytical', 'Simulation') set(hAxes,'XScale','log');

view raw
matlab_plot_take6
hosted with ❤ by GitHub

Which produces the following figure: We did a bit more tweaking with the figure to add some annotations, but they’re a bit harder to automate so I won’t discuss them here.

## Wrapping it Up

Now, we want to make the plot wrapper. This will be a custom function that will apply our common figure changes and that we can call for any plot we want. I previously wrote about wrapper functions here.

We want as much flexibility as we can so that the wrapper will be useful. The input arguments will be:

1. Handle to the existing axes
2. Data to plot
3. Changes to apply to the wrapper’s default settings

Below is a sample plot wrapper. It has 3 subfunctions to set the default properties for the figure, axes, and curve. 2 other subfunctions are used to change structure and object settings. These last 2 subfunctions use MATLAB’s ability to reference structure fields like they are an array.

 function [hFig, hAxes, hCurve] = my_plot_function(hAxes, … xData, yData, myFigProp, myAxesProp, myCurveProp, xStr, yStr) % A plotting wrapper function. Designed to plot one curve per call. % % INPUTS % hAxes – handle to existing axes (set to 0 to create new figure and axes) % xData – x data to plot (set to [] to not plot) % yData – y data to plot (set to [] to not plot) % myFigProp – structure of figure properties to change from defaults. See % subfunction buildFigureStruct for defaults. Ignored if hAxes == 0. Set % to [] to not change any defaults % myAxesProp – structure of axes properties to change from defaults. See % subfunction buildAxesStruct for defaults. Ignored if hAxes == 0. Set % to [] to not change any defaults % myCurveProp – structure of curve properties to change from defaults. See % subfunction buildCurveStruct for defaults. Ignored if xData == [] or % yData == 0. Set to [] to not change any defaults % % OUTPUTS (All optional) % hFig – handle to figure % hAxes – handle to axes. Store to plot more curves later % hCurve – handle to curve % % Created by Adam Noel, 2016-09-16 % Adapted from function accordPlotMaker.m, part of AcCoRD's MATLAB utilities % https://github.com/adamjgnoel/AcCoRD % % Options to expand % – control for type of plot (e.g., plot3, bar, surf) % Create figure and apply properties if it does not exist if hAxes == 0 figProp = buildFigureStruct(myFigProp); axesProp = buildAxesStruct(myAxesProp); % Create Figure hFig = figure; hFig = applyObjChanges(hFig, figProp); % Create Axes hAxes = axes('Parent',hFig); hAxes = applyObjChanges(hAxes, axesProp); hold(hAxes, 'on'); xlabel(xStr, 'interpreter', 'Latex'); ylabel(yStr, 'interpreter', 'Latex'); else hFig = get(hAxes, 'Parent'); end if ~isempty(xData) && ~isempty(yData) % Load curve properties curveProp = buildCurveStruct(myCurveProp); hCurve = plot(hAxes, xData, yData); hCurve = applyObjChanges(hCurve, curveProp); end end % Set default figure properties and apply changes function figProp = buildFigureStruct(myFigProp) figProp.Color = 'w'; figProp = applyStructChanges(figProp, myFigProp); end % Set default axes properties and apply changes function axesProp = buildAxesStruct(myAxesProp) axesProp = struct(… 'Box', 'on', … % If on, draw complete box outline along axis limits 'FontSize', 12, … 'XGrid', 'on', … 'YGrid', 'on', … 'TickLabelInterpreter', 'latex'); axesProp = applyStructChanges(axesProp, myAxesProp); end % Set default curve properties and apply changes function curveProp = buildCurveStruct(myCurveProp) curveProp = struct(… 'LineStyle', '-', … % Line style. Options: '-', '–', ':', '-.', 'none' 'LineWidth', 1, … % Line width 'Color', 'black', … % Line color 'Marker', 'o', … % Marker shape. Options: 'o', '+', '*', '.', 'x', 's', 'd', '^', 'v', '>', '<', 'p', 'h', 'none' 'MarkerSize', 6, … % Marker size 'MarkerEdgeColor', 'auto', … % Marker edge color. Options: 'auto', 'none', 'RGB triplet', 'color string' 'MarkerFaceColor', 'none', … % Marker edge color. Options: 'auto', 'none', 'RGB triplet', 'color string' 'DisplayName', ''); % Display string (if legend turned on) curveProp = applyStructChanges(curveProp, myCurveProp); end % Change specified elements of structure function curStruct = applyStructChanges(curStruct, changeStruct) if ~isempty(changeStruct) propFields = fieldnames(changeStruct); numProp = numel(propFields); for j = 1:numProp curStruct.(propFields{j}) = changeStruct.(propFields{j}); end end end % Apply changes to object with handle function h = applyObjChanges(h, changeStruct) if ~isempty(changeStruct) propFields = fieldnames(changeStruct); numProp = numel(propFields); for i = 1:numProp set(h, propFields{i}, changeStruct.(propFields{i})); end end end

view raw
matlab_plot_wrapper
hosted with ❤ by GitHub

A few comments on this plot wrapper:

1. It can be called with empty data to just build the figure and axes without plotting anything
2. You don’t need to include any of the figure, axes, or label arguments if you already have the axes handle from a previous call (or elsewhere)
3. You can pass your own custom structures for the figure, axes, and curve properties. As long as the structures have fields with the proper naming convention, then you can change (almost) any property this way. Disclaimer: I haven’t seen this work well when properties are also structures.

Now let’s try a simple script to build the figure we have above:

 clear; numPlotPoints = 50; x = 1e-2:1e-2:100; % Smooth curves y1 = exp(-x); y2 = 1-exp(-x); % Noisy curves n = length(x); z1 = y1.*(1+0.005*randn(1,n)); z2 = y2.*(1+0.005*randn(1,n)); plotInd = unique(floor(logspace(0, log10(n), numPlotPoints))); % My axes properties axesProp.XScale = 'log'; hAxes = 0; % Create 'Ghost curves' for legend curveProp.Marker = 'none'; [~, hAxes, ~] = my_plot_function(hAxes, NaN, NaN,[],axesProp,curveProp,… 'Time [s]', 'Exponential Observation'); curveProp.Marker = 'o'; curveProp.LineStyle = 'none'; [~, hAxes, ~] = my_plot_function(hAxes, NaN, NaN,[],axesProp,curveProp,… 'Time [s]', 'Exponential Observation'); hLegend = legend(hAxes, 'Analytical', 'Simulation'); set(hLegend, 'Interpreter', 'latex'); % Add smooth curves curveProp.Marker = 'none'; curveProp.LineStyle = '-'; [~, hAxes, ~] = my_plot_function(hAxes, x(plotInd),y1(plotInd),[],[],curveProp,… [], []); curveProp.Color = [0 0 1]; [~, hAxes, ~] = my_plot_function(hAxes, x(plotInd),y2(plotInd),[],[],curveProp, [], []); % Add noisy curves curveProp.LineStyle = 'none'; curveProp.Marker = 'o'; curveProp.Color = [0 0.6 0]; [~, hAxes, ~] = my_plot_function(hAxes, x(plotInd),z1(plotInd),[],[],curveProp, [], []); curveProp.Color = [1 0 0]; [~, hAxes, ~] = my_plot_function(hAxes, x(plotInd),z2(plotInd),[],[],curveProp, [], []);

This script produces the following: