Alex Bikfalvi
Adding LaTeX to Plot Tick Labels in Matlab
Overview
Matlab plots generally support LaTeX markup for the various components, including axes labels, legends, annotations, etc. However, one of the few exceptions are the axis tick labels, that is the data values alongside each axis, regardless of whether they are set automatically or manually by the user. Since in many situations it becomes necessary to use LaTeX in the tick labels, either to include mathematical expressions such as fractions, or simply to maintain a uniform look-and-feel, the Matlab code on this page enables this functionality without any change to normal plotting functions.
Download
- plotTickLatex2D.m (M/14.7 KB)
- plotTickLatex2DExample.m (M/3.05 KB)
Beta 4 version as of December 13, 2011.
Usage
After you finished plotting, and for every axis, call the following function:
plotTickLatex2D;
or:
plotTickLatex2D('argument_name', argument_value, ...);
Currently, the following optional arguments are supported:
| Argument name | Argument description |
|---|---|
'Axis' |
A handle of the axis. The default is the current axis. |
'FontSize' |
The font size of the tick labels. The default is the font size of the current or specified axis. |
'XLabelDy' |
An argument of value double, representing a shift of the X-axis label on the vertical direction. The value is in the coordinate system of the figure where the bottom-left is (0,0) and top-right is (1,1). |
'YLabelDx' |
An argument of value double, representing a shift of the Y-axis label on the horizontal direction. The value is in the coordinate system of the figure where the bottom-left is (0,0) and top-right is (1,1). |
Example
This example demonstrates the use of LaTeX in horizontal and vertical axes tick labels. Check out the following differences:
- The font changes from Helvetica to Computer Modern, the standard LaTeX font in Matlab. Hence, the look-and-feel is consistent with the other LaTeX annotations.
- The labels on the vertical axis contain mathematical expressions, including fractions and symbols.
Move the mouse to zoom in.
Before
After
Limitations
The current version is limited to two-dimensional plots; three-dimensional plots are not yet supported.
Version History
| Version | Date | Description |
|---|---|---|
| Beta 1 | August 31, 2011 | Initial beta release. |
| Beta 2 | October 23, 2011 | Fixed an issue where scaled negative axis labels would not display properly. |
| Beta 3 | November 19, 2011 | Better support for multiple axes in the same figure with the possibility of selecting the plot axis. Support for axis tick labels in non-default location (top or left). |
| Beta 4 | December 13, 2011 | Included font size support. |
Code
% % Copyright (C) 2011 Alex Bikfalvi % % This program is free software; you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation; either version 3 of the License, or (at % your option) any later version. % This program is distributed in the hope that it will be useful, but % WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % General Public License for more details. % You should have received a copy of the GNU General Public License % along with this program; if not, write to the Free Software % Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. % function plotTickLatex2D(varargin) % Optional arguments optargin = size(varargin,2); if mod(optargin,2) ~= 0 error('The number of optional arguments must be even'); end xLabelDy = 0; yLabelDx = 0; hAxis = gca; i = 1; while i <= optargin switch lower(varargin{i}) case 'xlabeldy' xLabelDy = varargin{i+1}; case 'ylabeldx' yLabelDx = varargin{i+1}; case 'axis' hAxis = varargin{i+1}; case 'fontsize' fontSize = varargin{i+1}; end i = i + 2; end % Get properties for the specified axis xLimit = get(hAxis,'XLim'); xTick = get(hAxis,'XTick'); xTickLabel = get(hAxis,'XTickLabel'); xTickLabelMode = get(hAxis,'XTickLabelMode'); xScale = get(hAxis,'XScale'); xAxisLocation = get(hAxis,'XAxisLocation'); yLimit = get(hAxis,'YLim'); yTick = get(hAxis,'YTick'); yTickLabel = get(hAxis,'YTickLabel'); yTickLabelMode = get(hAxis,'YTickLabelMode'); yScale = get(hAxis,'YScale'); yAxisLocation = get(hAxis,'YAxisLocation'); if ~exist('fontSize','var') fontSize = get(hAxis, 'FontSize'); end % Get properties for the current axis xLimitCurr = get(gca,'XLim'); xScaleCurr = get(gca,'XScale'); yLimitCurr = get(gca,'YLim'); yScaleCurr = get(gca,'YScale'); % Clear the current labels set(hAxis,'XTickLabel',[]); set(hAxis,'YTickLabel',[]); % Get position of the specified axis posAxis = get(hAxis,'Position'); % Get position of the current axis posCurr = get(gca, 'Position'); % Convert x point between figure and axis data coordinates on linear scale xFig2DatLinAxis = @(x)(xLimit(1) + diff(xLimit)*(x-posAxis(1))/posAxis(3)); xDat2FigLinAxis = @(x)(posAxis(1) + (x - xLimit(1))*posAxis(3)/diff(xLimit)); xFig2DatLinCurr = @(x)(xLimitCurr(1) + diff(xLimitCurr)*(x-posCurr(1))/posCurr(3)); xDat2FigLinCurr = @(x)(posCurr(1) + (x - xLimitCurr(1))*posCurr(3)/diff(xLimitCurr)); % Convert y point between figure and axis data coordinates on linear scale yFig2DatLinAxis = @(y)(yLimit(1) + diff(yLimit)*(y-posAxis(2))/posAxis(4)); yDat2FigLinAxis = @(y)(posAxis(2) + (y - yLimit(1))*posAxis(4)/diff(yLimit)); yFig2DatLinCurr = @(y)(yLimitCurr(1) + diff(yLimitCurr)*(y-posCurr(2))/posCurr(4)); yDat2FigLinCurr = @(y)(posCurr(2) + (y - yLimitCurr(1))*posCurr(4)/diff(yLimitCurr)); % Convert x point between figure and axis data coordinates on logarithmic scale xFig2DatLogAxis = @(x)(exp(log(xLimit(1)) + log(xLimit(2)/xLimit(1))*(x-posAxis(1))/posAxis(3))); xDat2FigLogAxis = @(x)(posAxis(1) + posAxis(3)*log(x/xLimit(1))/log(xLimit(2)/xLimit(1))); xFig2DatLogCurr = @(x)(exp(log(xLimitCurr(1)) + log(xLimitCurr(2)/xLimitCurr(1))*(x-posCurr(1))/posCurr(3))); xDat2FigLogCurr = @(x)(posCurr(1) + posCurr(3)*log(x/xLimitCurr(1))/log(xLimitCurr(2)/xLimitCurr(1))); % Convert y point between figure and axis data coordinates on logarithmic scale yFig2DatLogAxis = @(y)(exp(log(yLimit(1)) + log(yLimit(2)/yLimit(1))*(y-posAxis(2))/posAxis(4))); yDat2FigLogAxis = @(y)(posAxis(2) + posAxis(4)*log(y/yLimit(1))/log(yLimit(2)/yLimit(1))); yFig2DatLogCurr = @(y)(exp(log(yLimitCurr(1)) + log(yLimitCurr(2)/yLimitCurr(1))*(y-posCurr(2))/posCurr(4))); yDat2FigLogCurr = @(y)(posCurr(2) + posCurr(4)*log(y/yLimitCurr(1))/log(yLimitCurr(2)/yLimitCurr(1))); % Convert x point between figure and axis [0,1] coordinates xFig2Ax = @(x)((x - posAxis(1))/posAxis(3)); xAx2Fig = @(x)(posAxis(1) + x*posAxis(3)); % Convert y point between figure and axis [0,1] coordinates yFig2Ax = @(y)((y - posAxis(2))/posAxis(4)); yAx2Fig = @(y)(posAxis(2) + x*posAxis(4)); switch xScale case 'linear' xFig2DatAxis = xFig2DatLinAxis; xDat2FigAxis = xDat2FigLinAxis; case 'log' xFig2DatAxis = xFig2DatLogAxis; xDat2FigAxis = xDat2FigLogAxis; end switch yScale case 'linear' yFig2DatAxis = yFig2DatLinAxis; yDat2FigAxis = yDat2FigLinAxis; case 'log' yFig2DatAxis = yFig2DatLogAxis; yDat2FigAxis = yDat2FigLogAxis; end switch xScaleCurr case 'linear' xFig2DatCurr = xFig2DatLinCurr; xDat2FigCurr = xDat2FigLinCurr; case 'log' xFig2DatCurr = xFig2DatLogCurr; xDat2FigCurr = xDat2FigLogCurr; end switch yScaleCurr case 'linear' yFig2DatCurr = yFig2DatLinCurr; yDat2FigCurr = yDat2FigLinCurr; case 'log' yFig2DatCurr = yFig2DatLogCurr; yDat2FigCurr = yDat2FigLogCurr; end if ~isempty(xTickLabel) % Set the X Axis xTickIndex = find((xTick >= xLimit(1)) & (xTick <= xLimit(2))); xTickVisible = xTick((xTick >= xLimit(1)) & (xTick <= xLimit(2))); xLabel = cell(length(xTickVisible),1); switch xTickLabelMode case 'auto' assert(length(xTickVisible) <= size(xTickLabel,1)); switch xScale case 'linear' % Determine where there should be an exponent xExp = max(abs(xLimit)); if xExp > 0 xExpLog = ceil(log10(xExp)); if(xExpLog > 0) xExpLog = xExpLog - 1; end if (xExpLog > -3) && (xExpLog <= 3) xExpLog = 0; end else xExpLog = 0; end xExp = 10^xExpLog; for i=1:length(xTickVisible) value = xTickVisible(i)/xExp; if abs(value) <= eps value = 0; end xLabel{i} = ['$' num2str(value) '$']; end if (abs(xExpLog) > eps) && (abs(xExpLog) < 1/eps) switch xAxisLocation case 'bottom' hText = text(... xFig2DatCurr(xDat2FigAxis(xLimit(2))),... yFig2DatCurr(yDat2FigAxis(yLimit(1))-0.06),... ['$\times 10^{' num2str(xExpLog) '}$'],... 'HorizontalAlignment','Right',... 'Interpreter','latex',... 'FontSize', fontSize); case 'top' hText = text(... xFig2DatCurr(xDat2FigAxis(xLimit(2))),... yFig2DatCurr(yDat2FigAxis(yLimit(2))+0.06),... ['$\times 10^{' num2str(xExpLog) '}$'],... 'HorizontalAlignment','Right',... 'Interpreter','latex',... 'FontSize', fontSize); end set(hText,'HitTest','off'); end case 'log' for i=1:length(xTickVisible) sgn = sign(xTickVisible(i)); xExp = log10(abs(xTickVisible(i))); if abs(xExp) <= eps xExp = 0; end xLabel{i} = ['$' num2str(10*sgn) '^{' num2str(xExp) '}$']; end end case 'manual' if iscell(xTickLabel) for i=1:length(xTickVisible) xLabel{i} = xTickLabel{1+mod(xTickIndex(i)-1,length(xTickLabel))}; end else for i=1:length(xTickVisible) xLabel{i} = xTickLabel(1+mod(xTickIndex(i)-1,size(xTickLabel,1)),:); end end end switch xAxisLocation case 'bottom' for i = 1:length(xTickVisible) hText = text(... xFig2DatCurr(xDat2FigAxis(xTickVisible(i))),... yFig2DatCurr(yDat2FigAxis(yLimit(1))-0.025),... strtrim(xLabel{i}),... 'HorizontalAlignment','Center',... 'Interpreter','latex',... 'FontSize', fontSize); set(hText,'HitTest','off'); end case 'top' for i = 1:length(xTickVisible) hText = text(... xFig2DatCurr(xDat2FigAxis(xTickVisible(i))),... yFig2DatCurr(yDat2FigAxis(yLimit(2))+0.025),... strtrim(xLabel{i}),... 'HorizontalAlignment','Center',... 'Interpreter','latex',... 'FontSize', fontSize); set(hText,'HitTest','off'); end end xLabel = get(hAxis,'XLabel'); xLabelPos = get(xLabel,'Position'); set(xLabel,'Position',[xLabelPos(1) yFig2DatCurr(yDat2FigAxis(yLimit(1))-0.07+xLabelDy) xLabelPos(3)]); xlim(hAxis, xLimit); end if ~isempty(yTickLabel) % Set the Y axis yTickIndex = find((yTick >= yLimit(1)) & (yTick <= yLimit(2))); yTickVisible = yTick((yTick >= yLimit(1)) & (yTick <= yLimit(2))); yLabel = cell(length(yTickVisible),1); switch yTickLabelMode case 'auto' assert(length(yTickVisible) <= size(yTickLabel,1)); switch yScale case 'linear' % Determine where there should be an exponent yExp = max(abs(yLimit)); if yExp > 0 yExpLog = ceil(log10(yExp))-1; if(yExpLog > 0) yExpLog = yExpLog - 1; end if (yExpLog > -3) && (yExpLog <= 3) yExpLog = 0; end else yExpLog = 0; end yExp = 10^yExpLog; for i=1:length(yTickVisible) value = yTickVisible(i)/yExp; if abs(value) <= eps value = 0; end yLabel{i} = ['$' num2str(value) '$']; end if (abs(yExpLog) > eps) && (abs(yExpLog) < 1/eps) switch yAxisLocation case 'left' hText = text(... xFig2DatCurr(xDat2FigAxis(xLimit(1))),... yFig2DatCurr(yDat2FigAxis(yLimit(2)) + 0.03),... ['$\times 10^{' num2str(yExpLog) '}$'],... 'Interpreter','latex',... 'FontSize', fontSize); case 'right' hText = text(... xFig2DatCurr(xDat2FigAxis(xLimit(2))),... yFig2DatCurr(yDat2FigAxis(yLimit(2)) + 0.03),... ['$\times 10^{' num2str(yExpLog) '}$'],... 'HorizontalAlignment','Right',... 'Interpreter','latex',... 'FontSize', fontSize); end set(hText,'HitTest','off'); end case 'log' for i=1:length(yTickVisible) sgn = sign(yTickVisible(i)); yExp = log10(yTickVisible(i)); if abs(yExp) <= eps yExp = 0; end yLabel{i} = ['$' num2str(10*sgn) '^{' num2str(yExp) '}$']; end end case 'manual' if iscell(yTickLabel) for i=1:length(yTickVisible) yLabel{i} = yTickLabel{1+mod(yTickIndex(i)-1,length(yTickLabel))}; end else for i=1:length(yTickVisible) yLabel{i} = yTickLabel(1+mod(yTickIndex(i)-1,size(yTickLabel,1)),:); end end end xMin = bitmax; switch yAxisLocation case 'left' for i = 1:length(yTickVisible) hText = text(... xFig2DatCurr(xDat2FigAxis(xLimit(1))-0.01),... yFig2DatCurr(yDat2FigAxis(yTickVisible(i))),... strtrim(yLabel{i}),... 'HorizontalAlignment','Right',... 'Interpreter','latex',... 'FontSize', fontSize); set(hText,'HitTest','off'); set(hText,'Units','normalized'); xExt = get(hText,'Extent'); set(hText,'Units','data'); xMin = min(xMin, xExt(1)); end case 'right' for i = 1:length(yTickVisible) hText = text(... xFig2DatCurr(xDat2FigAxis(xLimit(2))+0.01),... yFig2DatCurr(yDat2FigAxis(yTickVisible(i))),... strtrim(yLabel{i}),... 'HorizontalAlignment','Left',... 'Interpreter','latex',... 'FontSize', fontSize); set(hText,'HitTest','off'); set(hText,'Units','normalized'); xExt = get(hText,'Extent'); set(hText,'Units','data'); xMin = min(xMin, xExt(1)); end end yLabel = get(hAxis,'YLabel'); yLabelPos = get(yLabel,'Position'); set(yLabel,'Position',[xFig2DatCurr(xAx2Fig(xMin) - 0.002 + yLabelDx) yLabelPos(2) yLabelPos(3)]); ylim(hAxis, yLimit); end end
Published: August 31, 2011
Last updated: December 13, 2011