Q: Special formatting of tickmarks?

Tickmarks are the only labels in Matlab that do not accept formatting: it is impossible to include special symbols, vary orientation, color, etc. The workaround is to replace them with TEXT objects. Unfortunately, some extra not-so-trivial measures have to be taken to ensure the labels stay in place if the figure is resized or axes are moved. XTICKS function (below) is an attempt to do so.

This plot has been produced by the following commands:

xl=[12 8 6 4 3 2];
xs=strcat('^{\pi}/_{',cellstr(num2str(xl(:))),'}'); % fills the labels using TeX noation 
cl=num2cell(interp1((0:.1:1)'*.5,jet(11),1./xl),2); % create pretty colors
xticks(pi./xl,xs,{'color'},cl);

function h=xticks(varargin)
%XTICKS  enables rich formatting of tickmarks
%  XTICKS(X,LABEL) creates tickmarks at positions X
%  X should be a vector, 
%  LABEL may be a cell array of the same size, or char matrix with lenght(X) rows
%  any TeX notation can be used.
% 
%  XTICKS(X) creates labels automaticly
%
%  XTICKS(...,'Property',Value,...) passes TEXT properties
%	
%  H=XTICKS(...) returns handles of TEXT objects
% 	 
%   Note: 
%  Tickmarks created this way are sensitive to YLIM: if it is changed, tickmarks 
%  may move. Calling XTICKS without any arguments after changing YLIM restores them.
%
%   Example:
%  XTICKS([0 pi 2*pi],{'Zero','\pi','2\pi'},'rotation',45,'fontsize',14) 

% 6/4/01 ashcherbina@ucsd.edu

fig = gcbo;	%if executed as a callback
if isempty(fig), fig=gcf;end

u = findobj(fig, 'Tag','SpecialXTick');
if ~isempty(u)
   axs = get(u,'parent');
   axs=cat(1,axs{:});
else
   axs=[];
end

% if moving, just update all ticks
if (isempty(varargin) & ~isempty(u))
   if length(u)==0 set(gcbo,'ResizeFcn',[]);return; end;
   for ax=unique(axs)'
      tm=u(axs==ax); %ticks belonging to this axis
      tm=sort(tm);
      pos=get_positions(ax);
      set(tm,{'position'},pos);
   end
   return;
end
% get ticks and labels
ax=gca;
xpos=get(ax,'Xtick');
str=cellstr(get(ax,'XtickLabel'));
if ~isempty(varargin) & ~isstr(varargin{1}), 
   xpos=varargin{1};
   set(ax,'Xtick',xpos);
   str=cellstr(get(ax,'XtickLabel'));
   if length(varargin)>1 & length(varargin{2})>1,
      str=varargin{2};
      if ~iscell(str),  str=cellstr(str);end;
      varargin={varargin{3:end}};
   else 
      varargin={varargin{2:end}};
   end
   xpos=xpos(:);
   str={str{:}}';
   visible=(xpos>=min(xlim) & xpos<=max(xlim));
   xpos=xpos(visible);
   str={str{visible}}';
   set(ax,'Xtick',xpos);

end

if ~isempty(axs)
   tm=u(axs==ax); %ticks belonging to the current axis
   if ~isempty(tm)
      % ticks exist - delete them
      delete(tm);  
   end
end

% fix limits & tickmarks
ylim(ylim);
xlim(xlim);

set(ax,'XtickMode','MANUAL','XtickLabelMode','MANUAL','Xticklabel',[]);

pos=get_positions(ax);
N=length(pos);

%create text objects
hh=text(zeros(N,1),zeros(N,1),str);
hh=sort(hh);
set(hh,{'position'},pos,...
   {'string'},str,...
	'horizontalalignment','center',...
   'clipping','off',...
   'Tag','SpecialXTick',...
   varargin{:});
set(gcf,'ResizeFcn','xticks');	% establish figure callback
if nargout>0, h=hh;end;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function pos=get_positions(ax)
YSPACE=10;	 %spacing between the axis and the labels, points
unit=get(ax,'units');
set(ax,'units','points');
rect=actual_pos(ax);
set(ax,'units',unit);

xpos=get(ax,'Xtick');
yl=get(ax,'Ylim');
y=yl(1)-YSPACE/rect(4)*diff(yl);
ypos=repmat(y,1,length(xpos));
zpos=0*ypos;
pos=num2cell([xpos(:),ypos(:),zpos(:)],2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function rr=actual_pos(ax)
% ACTUAL_POS - get the *actual* axis position
%	r=ACTUAL_POS(AX) returns the actual axis rectangle, which may be
%	different from get(AX,'Position') if data aspect is set manually.
%  If called without arguments, gca assumed

% ashcherbina@ucsd.edu, 2000

if nargin==0 ax=gca;end;
r=get(ax,'position');
rr=r;
if strcmp(get(ax,'DataAspectRatioMode'),'manual')
   dar=get(ax,'DataAspectRatio');
   units = get(ax,'units');
   set(ax,'units','pixels');
   r=get(ax,'position');
   set(ax,'units',units)
   xl=diff(xlim)./dar(1);
   yl=diff(ylim)./dar(2);
   p_r=yl/xl;	 %plot ratio
   b_r=r(4)/r(3);% box ratio
   if (p_r>b_r) %vertical positions are correct
      % actual width
      ax=r(4)/p_r;
      %extra width
      ex=(r(3)-ax)/2;
      rr(1)=rr(1)+ex/r(3)*rr(3);
      rr(3)=ax/r(3)*rr(3);
   else % horizontal positions are correct
     % actual height
      ax=r(3)*p_r;
      %extra height
      ex=(r(4)-ax)/2;
      rr(2)=rr(2)+ex/r(4)*rr(4);
      rr(4)=ax/r(4)*rr(4);
   end
end