**- Undocumented Matlab - https://undocumentedmatlab.com -**

Setting axes tick labels format

Posted By Yair Altman On April 18, 2012 | __18 Comments__

Have you ever tried to customize the way in which tick labels appear in Matlab plot axes?

For example, setting the numerical precision of the labels, or adding some short descriptive text (for example, the units)? If you have, then I bet that you have encountered the following dilemma: Once we modify the tick labels (for discussion sake, let’s assume the Y axis, so this is done by updating the **YTickLabel** property), then the corresponding **YTickLabelMode** property changes from ‘auto’ to ‘manual’ and loses its relationship to the tick values (**YTick**). So, if we now zoom or pan the plot, our new labels remain unchanged although the tick values have changed, causing much panic and frustration… If we also set the tick values manually, this solves *that* problem but leaves us with another: now, when we zoom or pan, we no longer see any ticks or tick labels at all!

Of course, we can always trap the zoom and pan callback functions to update the tick labels dynamically while keeping the tick values automatically. This will work for these cases, but we need to do it separately for zoom and pan. Also, if we modify the axes limits explicitly (via the corresponding

A better way to solve this problem is to simply trap changes to the displayed tick values, and whenever these occur to call our dedicated function to update the labels according to the new tick values. This can be done by using UDD, or more precisely the ability to trap update events on any property ^{[1]} (in our case, **YTick**). Such a mechanism was already demonstrated here ^{[2]} in 2010, as one way to achieve continuous slider feedback. The idea is to use the built-in * handle.listener* function with the PropertyPostSet event, as follows:

```
hhAxes = handle(hAxes); % hAxes is the Matlab handle of our axes
hProp = findprop(hhAxes,'YTick'); % a schema.prop object
hListener = handle.listener(hhAxes, hProp, 'PropertyPostSet', @myCallbackFunction);
setappdata(hAxes, 'YTickListener', hListener);
```

Note that we have used * setappdata* to store the

`hListener`

handle in the axes. This ensures that the listener exists for exactly as long as the axes does. If we had not stored this listener handle somewhere, then Matlab would have immediately deleted the listener hook and our callback function would not have been called upon tick value updates. Forgetting to store listener handles is a common pitfall when using them. If you take a look at the That’s all there is to it: Whenever

```
function myCallbackFunction(hProp,eventData) %#ok - hProp is unused
hAxes = eventData.AffectedObject;
tickValues = get(hAxes,'YTick');
newLabels = arrayfun(@(value)(sprintf('%.1fV',value)), tickValues, 'UniformOutput',false);
set(hAxes, 'YTickLabel', newLabels);
end % myCallbackFunction
```

Of course, ‘%.1fV’ may not be a good format when we zoom in to such a degree that the values differ by less than 0.1 – in this case all the labels will be the same. So let’s modify our callback function to add extra decimals until the labels become distinct:

```
function myCallbackFunction(hProp,eventData) %#ok - hProp is unused
hAxes = eventData.AffectedObject;
tickValues = get(hAxes,'YTick');
%newLabels = arrayfun(@(value)(sprintf('%.1fV',value)), tickValues, 'UniformOutput',false);
digits = 0;
labelsOverlap = true;
while labelsOverlap
% Add another decimal digit to the format until the labels become distinct
digits = digits + 1;
format = sprintf('%%.%dfV',digits);
newLabels = arrayfun(@(value)(sprintf(format,value)), tickValues, 'UniformOutput',false);
labelsOverlap = (length(newLabels) > length(unique(newLabels)));
% prevent endless loop if the tick values themselves are non-unique
if labelsOverlap && max(diff(tickValues))< 16*eps
break;
end
end
set(hAxes, 'YTickLabel', newLabels);
end % myCallbackFunction
```

Based on a file that I received from an anonymous reader a few years ago, I have prepared a utility called * ticklabelformat* that automates much of the set-up above. Feel free to download

```
ticklabelformat(gca,'y','%.6g V') % sets y axis on current axes to display 6 significant digits
ticklabelformat(gca,'xy','%.2f') % sets x & y axes on current axes to display 2 decimal digits
ticklabelformat(gca,'z',@myCbFcn) % sets a function to update the Z tick labels on current axes
ticklabelformat(gca,'z',{@myCbFcn,extraData}) % sets an update function as above, with extra data
```

As I’ve indicated in my comment response ^{[5]} below, in HG2 (R2014b or newer) we need to listen to the HG object’s `MarkedClean`

event ^{[6]}, rather than to a property change event.

I’ve updated my ticklabelformat utility accordingly, so that it works with both HG1 (pre-R2014a) and HG2 (R2014b+). Use this utility as-is, and/or look within its source code for the implementation details.

Categories: Handle graphics, Listeners, Medium risk of breaking in future versions, Undocumented function

18 Comments (Open | Close)

Article printed from Undocumented Matlab: **https://undocumentedmatlab.com**

URL to article: **https://undocumentedmatlab.com/articles/setting-axes-tick-labels-format**

URLs in this post:

[1] ability to trap update events on any property: **http://undocumentedmatlab.com/blog/udd-events-and-listeners/**

[2] demonstrated here: **http://undocumentedmatlab.com/blog/continuous-slider-callback/#Property_Listener**

[3] HG2: **http://undocumentedmatlab.com/blog/matlab-hg2/**

[4] download: **http://www.mathworks.com/matlabcentral/fileexchange/36254-ticklabelformat**

[5] my comment response: **http://undocumentedmatlab.com/blog/setting-axes-tick-labels-format#comment-339729**

[6] HG object’s `MarkedClean`

event: **http://undocumentedmatlab.com/blog/undocumented-hg2-graphics-events**

[7] Customizing axes tick labels : **https://undocumentedmatlab.com/articles/customizing-axes-tick-labels**

[8] Customizing axes part 5 – origin crossover and labels : **https://undocumentedmatlab.com/articles/customizing-axes-part-5-origin-crossover-and-labels**

[9] Axes LooseInset property : **https://undocumentedmatlab.com/articles/axes-looseinset-property**

[10] Customizing axes rulers : **https://undocumentedmatlab.com/articles/customizing-axes-rulers**

[11] Undocumented HG2 graphics events : **https://undocumentedmatlab.com/articles/undocumented-hg2-graphics-events**

[12] FIG files format : **https://undocumentedmatlab.com/articles/fig-files-format**

[13] : **http://stackoverflow.com/questions/13326894/force-exponential-format-of-ticks-like-matlab-does-it-automatically**

[14] : **https://undocumentedmatlab.com/blog/matlab-hg2/**

[15] : **https://undocumentedmatlab.com/blog/hg2-update/**

[16] : **https://undocumentedmatlab.com/blog/undocumented-hg2-graphics-events**

Click here to print.

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.

18 Comments To "Setting axes tick labels format"

#1 CommentByEdOn April 25, 2012 @ 06:56This is fantastic! I had long since given up hope of finding a solution to this problem. Thanks very much.

#2 CommentByLubos SmolikOn January 9, 2013 @ 02:40Brilliant!

Very useful in 3D rotordynamics graphs when

gives ugly results. Thank you very much 😉

#3 CommentByYuriOn April 30, 2013 @ 12:12Yair,

Have you looked at how MATLAB works with scientific notation format of tick labels putting the exponent only into one place on the axes? The XTickLabels are only what one can see there without exponent. Where MATLAB hides the exponent? Is there a way to change it? to enforce this format? I know only way with manually changing the ticks and adding exponent as a text object. As in this question, for example:

^{[13]}Any undocumented staff?

#4 CommentByYair AltmanOn April 30, 2013 @ 12:52@Yuri – I do not know of a way to do this with the current HG system. HG axes have some related hidden properties (

ExpFontAngle, ExpFontName, ExpFontSize, ExpFontStrikeThrough, ExpFontUnderline, ExpFontUnits, ExpFontWeight) but they don’t appear to have any effect as far as I can tell (maybe someone could find out).I believe that I saw some configurable exponent properties in the

^{[14]}. I haven’t tested HG2 on the latest releases lately, so try it (using the -hgVersion2 startup switch as mentioned in the article) and let us know what you discover.p.s. – wow, has it been 2 full years already? – it’s about time HG2 got released…#5 CommentByYair AltmanOn May 28, 2013 @ 16:55@Yuri – as followup, customizing the exponent is indeed possible in HG2, as I have

^{[15]}.#6 CommentByNicoOn May 13, 2013 @ 05:09Just found this post yesterday and really liked it. Using this method, you can avoid the stupid identical labels that appear when you zoom in real close in a large plot. Also, the

function from matlabcentral can be modified quite easily to scale the tick values, which can be extremely helpful. Thanks, Yair.ticklabelformat#7 CommentBydamayiOn December 2, 2014 @ 23:38I always use this method for MATLAB 2013B, it works fine.

However, it does not work for 2014b, the latest released version.

#8 CommentByYair AltmanOn December 4, 2014 @ 14:35@Damayi – This is a known issue that is due to the changes in property listeners that were done for the new HG2 graphics engine in R2014b.

#9 CommentBydamayiOn December 27, 2014 @ 01:23Do you have a resolution for this problem?

#10 CommentByYair AltmanOn January 5, 2015 @ 07:28@Damayi – Yes, in HG2 we need to listen to the HG object’s

`MarkedClean`

event, rather than to a property change event.I’ve updated my

^{[4]}accordingly, so that it works with both HG1 (pre-R2014a) and HG2 (R2014b+). Use this utility as-is, and/or look within its source code for the implementation details.#11 CommentByRobertOn January 25, 2015 @ 08:41Yair,

thanks for providing this kind of input and the ticklabelformat. I’m also thankful for the comments as I had no idea why the callbacks for axis properties do not work anymore with HG2. Already in HG1 some things are confusing, since somehow the event argument is of different type, depending on…well I don’t really know. But in HG2 addlistener does somehow not work on those properties.

Would it be possible to provide a fully working example callback function for HG2 (maybe in the docstring of the ticklabelformat function)?. The one given above apparently does not work (only tested with HG2). The second argument has only two properties: .Source and something else. I tried to access the ticks via – I think it was – .Source.Tick, but it did not work properly and even crashed MATLAB. All my old callbacks do not work anymore with the new HG2. Sad, that TWM does not supply easy instructions on updating customized tick labels as this is quite a substantial thing, when examining data using a plot and the pan/zoom functionality. Thanks.

#12 CommentBySandor TothOn August 3, 2015 @ 07:01Dear Yair,

do you know a way to change the XTickLabel vertical position, a.k.a its distance from the x-axis line? The generally suggested solution is to recreate the labels using the text() command, but there should be a simpler way to do it!

Do you have any suggestion?

Thanks,

Sandor

#13 CommentByfulvio settiOn April 28, 2016 @ 15:23YEEEESSSS !!! It’s many time that i searched this way to have MORE digit in the graphs !!!! THAAANK YOU !!!!

#14 CommentByJim HokansonOn November 29, 2017 @ 21:18Yair,

Would it be possible to add an “update” section by the blurb on the listener to describe the change with HG2? I’m specifically thinking something that references MarkedClean and YRuler. I’m fine but it might be nice for others …

Thanks,

Jim

#15 CommentByYair AltmanOn December 6, 2017 @ 16:29@Jim – done 🙂

#16 CommentByRon DekelOn June 20, 2018 @ 15:43I wonder – is it possible to use images as axis tick labels?

Ron

#17 CommentByYair AltmanOn June 21, 2018 @ 16:14@Ron – Tick labels are strings. If you want to use images, then set the ticklabels to empty (i.e., do not show any ticks) and programmatically add images at the relevant [negative] axes locations based on the computed tick positions. You will need to update the images and their location whenever the axes resizes or zooms or pans or changes its ticks in whichever way (

^{[16]}). To be honest, I’m not sure that it’s worth all this effort…#18 CommentByAntonius ArmaniousOn August 7, 2019 @ 12:51Do you know of a way to change the position of one of the tick labels so that it does not overlap with the tick labels from the neighbouring axes?

Thanks