Nonlinear colour axis on colorbar

27 views (last 30 days)
Selwyn
Selwyn on 17 Feb 2012
Answered: Constantino on 9 Nov 2018
Hi,
I am trying to make a nonlinear (not logarithmic though) axis on my colorbar. To explain - if I use the following code:
a = rand(20,20);
colormap(jet(5))
conts = [0:1/5:1];
contourf(a,conts,'k:')
cb = colorbar;
caxis([0 1])
set(cb,'YTick',conts)
It produces a correct contourf figure with contour values equally spaced through the colorbar.
However, if I wanted to contour different values, and the change the routine to
a = rand(20,20);
colormap(jet(5))
conts = [0 0.01 0.05 0.9 0.95 1];
contourf(a,conts,'k:')
cb = colorbar;
caxis([0 1])
set(cb,'YTick',conts)
I end up with the colorbar patches not matching the contours I specified and the contours themselves not equally spaced on the colorbar axis, but shown rather as they would be in relation to the distance from zero. My intention is to make the shaded patches match up with the contour intervals I specify, and then have those spaced out neatly along the colorbar regardless of their actual value. The reason I have this is because I have data where the contour values will be something like [-0.1 -0.5 0.5 0.75 0.8 1 10 50 80 85 90:2:100] with each contour chosen for a reason and I need to display it nicely.
Any suggestions?
  2 Comments
Jiro Doke
Jiro Doke on 19 Feb 2012
Do you want the ticks of the color bar to be equally spaced (even if the actual values aren't equally spaced)? Or instead, do you want the color patches to be non-equally spaced to match the actual tick marks? The latter would be more difficult, possibly requiring you to create your own colorbar.
Selwyn
Selwyn on 23 Feb 2012
Hi. I'd like the ticks on the color bar to be equally spaced, even though the actual values arent equally spaced.
The color patches would have to match the ticks too

Sign in to comment.

Answers (3)

Selwyn
Selwyn on 24 Feb 2012
I solved this problem. To outline the solution:
1) First set your colormap and contour levels so that the number of contours matches the number of colours. (eg: 15 colours & 16 contours)
2) Make a pseudo contour level from 1:length(contours)
3) Scale your data according to the pseudo contour levels (I just found that in Matlab, its easier to scale data than to scale a graphics object like contourf or pcolor.
4) rather use pcolor with 'shading interp' as opposed to contourf (the shading command still gives you a limited number of colours and pcolor works nicely for sparse data)
5) Relabel the yticklabels on the colorbar with your original contour levels.
The exact code is very messy but works - its far better to understand the points above though.
  1 Comment
Milena
Milena on 28 Sep 2013
Hi Selwyn,
I am having the same problem and would like to try your solution. Could you please explain more points 2) and 3)? What do you mean by 'making a pseudo contour level'? And how do you scale your data?
Many thanks, Milena

Sign in to comment.


Stephen Licata
Stephen Licata on 13 Mar 2018
One way of handling this challenge - which I think is what the first answer suggested - is to create a set of colors and treat each color as a separate bin. You would then "translate" data from different value ranges into a sixed, fixed bin number.
For example, you could have a color bar with five colors, as follows: new colors = zeros(5,3);
[041 009 216] scaled to 255 => new colors(1,1:3) = [0.1608 0.0353 0.8471] % dark blue [170 248 255] scaled to 255 => new_colors(2,1:3) = [0.6667 0.9725 1.0000] % light blue [255 255 191] scaled to 255 => new_colors(3,1:3) = [1.0000 1.0000 0.7490] % yellow [248,109,094] scaled to 255 => new_colors(4,1:3) = [0.9725 0.4275 0.3686] % orange [165 000 033] scaled to 255 => new_colors(5,1:3) = [0.6471 0.0000 0.1294] % dark red
Then assign a bin number range of 1 to 5
Then, if you have data that varies from, say, -10 (or less) to + 10.0 (or more), examine each data point and assign it a bin number that corresponds to any non-linear set of ranges.
For example, for data array float X(1000) and corresponding bin assignment integer B(1000)...
if X(n) < -10.0 and X(n) <=-3.0, then B(n) = 1; % dark blue if X(n) >-3.0 and X(n) <-0.50, then B(n) = 2; % light blue if X(n) >=-0.5 and X(n) <= 0.50, then B(n) = 3; % yellow if X(n) > 0.50 and X(n) < 3.0, then B(n) = 4; % orange if X(n) >= 3.0 and X(n) <= 10.0, then B(n) = 5; % dark red
You would then simply plot the B array (not X). When you create your color bar, just scale it from 1 to 5 but add the "real data value" labels of '-10', '-3', '-0.5', '0.5', '3.0', '10';

Constantino
Constantino on 9 Nov 2018
I have the same difficulty, but solved it another way. In short, I plotted with contourf, with the non evenly spaced contours given by a vector. Then, I plotted an empty axis, and made a discrete colorbar (for example jet(4)). The I just changed the colors and the labels of the colorbar ticks. Here is the result. I will read your strategy in detail to see if it is better. To add the second (empty) plot I just put hold on, fakeax=axes, and turned the visible propertie off. The colorbar of the fake invisible axes covers the wrong previous axes.

Categories

Find more on Colormaps in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!