Code covered by the BSD License  

Highlights from
Rotate X-axis tick labels

4.57143

4.6 | 22 ratings Rate this file 456 Downloads (last 30 days) File Size: 4.9 KB File ID: #27812
image thumbnail

Rotate X-axis tick labels

by

 

01 Jun 2010 (Updated )

Rotate x-tick labels to any angle, preserving font settings and coping with resize, zoom, pan etc

| Watch this File

File Information
Description

This function rotates the x-tick labels on a plot. An arbitrary angle can be specified for the text and the label justification adjusts appropriately to ensure the labels lie below the ticks. The axes font properties are preserved in the labels, which will update in response to font changes. Changes to the axes limits are also handled.

Main features:
* Arbitrary angle of rotation
* Justification adjusts appropriately for the specified angle
* Axes font property changes are reflected
* Labels move correctly when zooming and panning

As with other functions that achieve the same result, this works by replacing the xtick labels with text objects. Handles to the created text objects are returned for you to tinker with.

Acknowledgements

Rotate X Tick Labels For Multi Axes inspired this file.

This file inspired Shaded Correlation Table, Machine Learning With Matlab, and X Yrotalabel Rotate X Axis And Y Axis Labels.

MATLAB release MATLAB 7.10 (R2010a)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (49)
27 Jan 2014 Art

Having problems with this. consider
figure;plot(1:10);
set(gca,'xlimmode','manual','xlim',[0,11]);
rotateXlabels(gca,90);
set(gca, 'xlim', [0,15]);

The labels do not update correctly. 13,14,&15 don't show. Adding 'xtick',[0:15] to the set command didn't help.
Using matlab 7.12.0 on an xp box.

17 Oct 2013 Amit

Nice function.

Follow-on to the discussion about imagesc
Had some trouble (position of labels) using this with imagesc. Solved it modifying the following

line 139: y = ylim(1);
line 141: y = ylim(2);
line 357: pos = [0 ylim(2)];
line 359: pos = [0 ylim(1)];

Still a remaining problem. If colorbar is visible the figure sizing is not correct.
Not sure how to fix this part.

24 Sep 2013 Patrick Cloke

Very useful! Some errors when saving a figure and reopening them (it looks like the old axes is trying to be modified).

19 Sep 2013 Adam Finnefrock  
19 Aug 2013 Forest

things are not right if one set the axis reverse as:
set(gca,'YDir','reverse')

18 Aug 2013 Forest

Pretty good and handy tool to display long strings as X tick label!

06 Aug 2013 Jaroslaw Tuszynski

Idea is great and it works for some plots. I had issues with plots being incorrectly resized that required code changes. I also had some blots for which this function placed tick labels inside the plot area. So it needs more debugging and possibly a tutorial page with examples.

04 Jul 2013 Dinesh Jayaraman  
11 Jun 2013 Gadi

I've pinpointed the issue with the "Index exceeds matrix dimensions." error and it's a bug somewhere else.

It has to do with "hold on" somehow adding 2 new tick marks to the figure.

Here is how to reproduce it on 2012a:

dat = 1:5;
fh = figure;
hold all;
bar(dat);
set(gca,'XTickLabel', dat);
rotateXLabels(gca,10);

If you would remove "hold on", no error.

06 May 2013 Muthu Annamalai

Thanks for sharing! Do you have any ideas on applying this to the Y-axis ?

26 Apr 2013 Jorge  
18 Mar 2013 Andrea  
19 Feb 2013 M H

Very nice function!!

the imagesc() workaround would be to create a copy of the function e.g. 'rotateXLabelsIMGSC()' and change

'y = ylim(2);' to 'y = ylim(1);' in line 124
and
'y = ylim(1);' to 'y = ylim(2);' in line 126

..would be nicer to catch the imagesc()-case by an 'if' but I am not sure if there is a handle/handle-combination to do it...
cheers

08 Feb 2013 Ben Tordoff

Hi Fernando & Martin, could one of you post (or email me) an example? When I try the obvious:

imagesc
rotateXLabels(gca, 45)

it all looks fine. Also, which MATLAB version, just in case it matters?

08 Feb 2013 Ben Tordoff

Thanks Matt, that's an interesting bug you've found.

I think we can do something slightly better and remove everything to do with rotated labels when the axes are cleared. I'll post an update that does this for you to try. Hopefully it won't break any existing functionality.

07 Feb 2013 Matt Jardin

Hey Ben. Very useful function indeed! I may have found an odd issue that occurs if you run cla on the axis that contains rotated x-axis labels. In that case, the next time you trigger one of the listeners that your function sets up, an error is thrown because all of the properties it expects to find have been cleared. I hacked a quick fix by checking inside of each of the listener callbacks to check if the particular axis property is empty. If so, I remove the listeners. Perhaps you have a better suggestion? Thanks again for the function.

05 Oct 2012 Jingmin

Thanks!! Just what I needed.

05 Oct 2012 none

great! eg rotateXLabels(gca, 40);

17 Sep 2012 Fernando

I have the same problem of Martin

08 Aug 2012 Edward  
08 Jul 2012 Martin

Love the function, but have one problem: when I use it with imagesc() the labels end up on the top of the graph and inside the face of the graph. How can I move them to be outside?

22 Jun 2012 Sam

Thanks for the sweet function. However, I'm also getting an "Index exceeds matrix dimensions" error with R2012a, and I isolated what's causing the problem for me at least (although I have no idea why). The code below simulates the scenario I'm working on. When I set 'YGrid' to 'on', I get the error that follows the code. No error when I leave out a 'YGrid' specification. (Note that the code seems to execute just fine despite the error, so it's not a huge deal.)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

% Create fake data
%%% 14 groups of 4 percentages, each group adding to 100
data = zeros(14,4) ;
data(:,1) = randi(100,14,1) ;
for y = 2:3
for x = 1:14
if sum(data(x,:)) == 100
continue
end
data(x,y) = randi(100-sum(data(x,:)),1,1) ;
end
end
for x = 1:14
data(x,4) = 100 - sum(data(x,:)) ;
end

% Make grouped bar graph
bar(data,'grouped') ;
xlabels = char('Grp01','Grp02','Grp03','Grp04','Grp05','Grp06','Grp07','Grp08','Grp09','Grp10','Grp11','Grp12','Grp13','Grp14') ;
set(gca,'XTickLabel',xlabels,'YLim',[0 100],'YGrid','on')
rotateXLabels(gca,45)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Here's the error message:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Index exceeds matrix dimensions.

Error in rotateXLabels/getLabelHeight (line 226)
oldUnits = get( textLabels(1), 'Units' );

Error in rotateXLabels/repositionXLabel (line 204)
labelHeight = getLabelHeight(ax);

Error in rotateXLabels/onAxesLimitsChanged (line 353)
repositionXLabel( ax );

Warning: Error occurred while evaluating listener callback.
> In graphics/private/clo at 83
In cla at 29
In newplot>ObserveAxesNextPlot at 125
In newplot at 74
In bar at 76

11 Jun 2012 Ben Tordoff

Hi Vaibhav, any chance you could post a version of the code that doesn't require a data-file? You can use RAND etc to generate some fake data. The important thing is that the range of the data (both in x and y) is similar to the data that you are having trouble with.

10 Jun 2012 Vaibhav Jain

Hi Ben,

Thank you for your function. It works absolutely perfect but I am facing a problem when converting the x ticks to mm/dd hh:mm format using datetick command. The eroor message arises specifically when I increase the number of x ticks beyond a certain limit (more than 8 in this case) using linspace command.

Please look at the following code. I have tried to explain its steps in the commented lines. In the end I am pasting the error message I get on running. I would like to know your views on it. Thanks again!

file=importdata('HourlyTemperature.csv');
DateTime=file.textdata(2:end,1);
% textdata is a <168x1 double> array with values in 'dd/mm hh:mm:ss' format

DateTime=datenum(DateTime);
% Converts mm/dd hh:mm to numeric values

Temperature=file.data(:,1);
% data is a <168x1 double> array with numeric format

plot(DateTime,Temperature);
datetick('x','dd/mm HH:MM:SS','keepticks');
xData=linspace(735105.0416666666,735112,8);
% linspace('first value of DateTime array', 'last value of DateTime array',
% 'number of XTicks in between')

set(gca,'XTick',xData)

rotateXLabels(gca, 90)

Error message:
??? Index exceeds matrix dimensions.

Error in ==> rotateXLabels>createNewLabels at 132
textLabels(ll) = text( ...

Error in ==> rotateXLabels at 35
h = createNewLabels( ax, vals, labels, angle );

Error in ==> HourlyTempPlot at 29
rotateXLabels(gca, 90)

- Vaibhav Jain

10 Jun 2012 Vaibhav Jain  
29 Feb 2012 Jacques Pecreaux

Worked perfectly in 2 minutes.
A great and user-friendly file.
Some warnings about latex markups while using no interpreter but it's harmless so far
Thanks for sharing!

21 Feb 2012 Ben Tordoff

OK, I've submitted an update that will hopefully fix the printing issues. Please keep a backup of the old version in case this change breaks something else (it passes all my tests, but they probably don't cover all uses). The update should appear here in the next few days. When it does, let me know if it helped.

Cheers.
Ben

21 Feb 2012 Ben Tordoff

Hi Johan, I can see the problem. I am using "normalized" coordinates for the text used as the labels. It seems that with the units set to normalized they don't print, but if I set them to something else they do. I have no idea why this would be.

I will see if I can re-arrange the code to use something other than normalized units without breaking something else (zooming, panning, titles, etc).

:-(

Ben

07 Feb 2012 Johan Carlson

Hi,
On screen everything looks fine. However, when I try to print, the tick labels disappear, same as for Wolfgang. I'm running MATLAB 2011b (7.13.0.564) on Windows 7 (x64 version). All plot settings are at the default.

Other than that, great function!
/Johan

Here's the test script that used:

%------------------
clear all
close all
clc

x = 1:0.2:2.8;
y = x.^2;
plot(x,y);
xlab = get(gca,'XTickLabel');
xlab = num2str(xlab);
set(gca,'XTickLabel',xlab);
xlabel('X axis label');
ylabel('Y axis label');
title('Plot title');
rotateXLabels(gca, 45)
set(gcf, 'PaperPositionMode', 'auto');
print('-dpng','plot.png');

27 Jan 2012 Pablo  
13 Oct 2011 Chris Sparrow

yes I am using an old version of Matlab - thanks for the suggestion. Great script btw!

13 Oct 2011 Ben Tordoff

Hi Chris, are you by any chance using a version of MATLAB older than R2010a?

If so, you may still be able to get it to work by replacing the '~' with a real variable name, but bear in mind this hasn't been developed or tested on older releases.

Cheers. Ben

12 Oct 2011 Chris Sparrow

I get the following error:
>> rotateXLabels( gca(), 22 )
??? Error: File: rotateXLabels.m Line: 310 Column: 33
Unexpected MATLAB operator.

line 310 is function onAxesFontChanged( ~, ~ )

it will work if I commnet out the functions having ( ~, ~ )
any thoughts why I have this error?

thanks

12 Oct 2011 Ben Tordoff

Hi Wolfgang, I've just tried this using the example in the help and printing using the lines you provided and the labels appear OK. Could you provide a more detailed example that shows the problem? There may be some setting of your figure that makes a difference.

Cheers. Ben

12 Oct 2011 Wolfgang

Hi Ben,

This works fine with me, but the x-Axis labels are not printed into a png-file via
set(gcf, 'PaperPositionMode', 'auto');
print('-dpng','-r90','bild.png');

Can you reproduce this, and do you have a solution.

04 Aug 2011 Thijs

First rotate script I came across that works without issues (yet ;) ) on subplots.

Thank you!

29 Mar 2011 Denzel Li

Hi Ben and Miranda:
The program is cool, especially comparing to other rotation programs which may not adjust the text object position well. Also the code style is clear.
For my previous request of setting the axis to the top, I just manually set the y to a proper value in creatNewLabels(...) and it works.

14 Feb 2011 Miranda

Hi Ben,
Thank you for this nice program. One disadvantage is that the labels are very close to the x-axes, especially if I choose an angle of -90 or 90. I thought of including an extra space in the labels:
if 0 <= angle && angle < 180
labels = cellfun(@(x) horzcat(x,' '),labels,'UniformOutput', false);
else
labels = cellfun(@(x) horzcat(' ',x),labels,'UniformOutput', false);
end
Maybe an extra if-expression is needed for the labels on XAxisLocation top...
Miranda

11 Feb 2011 Ben Tordoff

Hi Denzel, my first attempt at getting this to work is on its way through the approval process now. You should see it arrive on here in the next day or two.

08 Feb 2011 Denzel Li

Hi Ben:
Thanks for your quick reply. Having xticklabels on top and yticklabels on right are especially useful when displaying heatmap with labels. Please keep me updated. Thanks.

01 Feb 2011 Ben Tordoff

Hi Denzel,
this hack works by replacing the tick labels with text objects and removing the existing tick labels. This means that setting properties of the tick labels (fonts, position etc) will no longer have any effect. I'll have a look and see if I can make them honour the "XAxisLocation" property, but I suspect that even then you will need to set it before rotating the labels. Watch this space...

Ben

31 Jan 2011 Denzel Li

Hi Ben:
Thanks for the great tool. However it only produces xticklabels which is at the bottom and not on the top. That is, even with the function call:
set(gca, 'XAxisLocation', 'top');
the xticklabels are still at the bottom. Please note that get(gca,XAxisLocation') returns 'top'.
Please let me know if anyone has any suggestion. Thanks.

Best,
Denzel

06 Oct 2010 Dan Glaser

Thanks, the positioning now works great.

06 Oct 2010 Ben Tordoff

Hi Dan. I'm hoping this latest update will have fixed your problem. Please let me know if it doesn't.

Cheers. Ben

01 Oct 2010 Dan Glaser

Thanks Ben,
I appreciate you looking into this!
-Dan

30 Sep 2010 Ben Tordoff

Hi Dan. Having done some testing, it looks like text object positions are only stored to the nearest pixel. This means that when you call rotateXLabels, any labels that are drawn at the same pixel location will store their position as the same value. This seems to be a limitation of MATLAB's normalised position units or at least a restriction imposed when you switch to them. I will see if it's possible to achieve the same label behavior without using normalised coordinates as this may fix your problem. Watch this space...

Cheers. Ben

29 Sep 2010 Dan Glaser

This works beautifully, but when it is used with a plot that has a very large number of x tick labels (1000 for example) it does not position them correctly.

Initially of course in this case, they labels are all overlapping, but after zooming it can be seen that they do not position equally and some are directly on top of each other.

Does anyone have any suggestions?

29 Sep 2010 Dan Glaser  
27 Sep 2010 Suresh Joel

Some function arguments missing? (line 256 col 33)

Updates
30 Sep 2010

Switch to using normalized units for labels to prevent loss of accuracy with hundreds/thousands of labels.

07 Feb 2011

Should now honour the "XAxisLocation" property of the axes.

21 Feb 2012

Switch to using data coordinates internally to allow printing to work. Please keep the old version in case this breaks something else!

28 Mar 2013

Improve behavior when "cla" is called on the axes.

Contact us