function ticks = logticks(dataMin, dataMax, n)
% LOGTICKS(DATAMIN, DATAMAX, N) calculates locations for axes tick marks between the
% values DATAMIN and DATAMAX, with behaviour specified by N as follows:
% N=1 will produce tick marks at 10^j for integer j,
% N=2 gives tick marks k*10^j with k in {1, 5},
% N=3 gives tick marks k*10^j with k in {1, 2, 5}.
% The return value is a structure with two fields:
% VALUES is a vector containing the locations for the ticks.
% LABELS is a cell containing labels corresponding to each tick value.
%
% LOGTICKS(DATAMIN, DATAMAX) works as above, with a 'best guess' value of N as
% follows:
% If the ratio dataMax/dataMin is > 10000, N is set at 1.
% If 500 < ratio <= 10000, then N is set at 2.
% For ratio <= 500, N is set at 3.
%
% EXAMPLE:
%
% datamin = 0.07;
% datamax = 45;
% ticks = logticks(datamin, datamax);
% plot(datamin:datamax, sin(datamin:datamax))
% set(gca, 'XScale', 'log', ...
% 'XTick', ticks.values, ...
% 'XTickLabel', ticks.labels, ...
% 'XMinorTick', 'off')
%
% $ Author: Richie Cotton $ $ Date: 2006/06/26 $
%% Basic error checking
if nargin < 2
error('logticks:notEnoughInputs', 'This function requires at least two inputs.');
elseif ~isreal(dataMin) || ~isreal(dataMax) || ~isscalar(dataMin) || ~isscalar(dataMax)
error('logticks:badMinMaxValue', 'The minimum and maximum must be real scalars.');
end
%% Set default for n, if necessary
if nargin < 3 || isempty(n)
ratio = dataMax/dataMin;
if ratio > 10000
n = 1;
elseif ratio > 500
n = 2;
else
n = 3;
end
end
%% Set value for k
if n == 3
k = [1 2 5];
elseif n == 2
k = [1 5];
elseif n == 1
k = 1;
else
error('logticks:badNValue', 'n must take the value 1, 2, or 3.');
end
%% Find lowest exponent for ticks
tempMin = dataMin;
if dataMin >= 1
jmin = -1;
while tempMin >= 1
tempMin = tempMin/10;
jmin = jmin+1;
end
else
jmin = 0;
while tempMin < 1
tempMin = tempMin*10;
jmin = jmin - 1;
end
end
%% Find highest exponent for ticks
tempMax = dataMax;
if dataMax >= 1
jmax = -1;
while tempMax >= 1
tempMax = tempMax/10;
jmax = jmax+1;
end
else
jmax = 0;
while tempMax < 1
tempMax = tempMax*10;
jmax = jmax - 1;
end
end
% Valid exponents, with padding
exponents = (jmin-2):(jmax+2);
%% Calculate tick values
ticksMatrix = k'*10.^exponents;
ticks.values = reshape(ticksMatrix, 1, numel(ticksMatrix));
% Find values in range, then pad by a couple of values
rangeFilter = find(ticks.values >= dataMin & ticks.values <= dataMax);
rangeFilter = [min(rangeFilter)-(2:-1:1) rangeFilter max(rangeFilter)+(1:2)];
%% Generate labels for ticks
lk = length(k);
le = length(exponents);
for i = 1:le
for j = 1:lk
if sign(exponents(i)) >= 0; s = '+'; else s=''; end;
ticks.labels{(i-1)*lk+j} = sprintf('%de%c%d', k(j), s, exponents(i));
end
end
% Return values
ticks.values = ticks.values(rangeFilter)';
ticks.labels = ticks.labels(rangeFilter)';