Numbers on the middle of colorbar in MATLAB

How to create a colorbar in MATLAB like this in which the numebrs comes exactly on the colorbar cell.

Answers (3)

I understand you need to create a “colorbar” in MATLAB with text inside the “colorbar” cell.
This can be achieved using “annotation” objects (for example textbox)
Here’s the code for the same:
figure
hcb = colorbar;
hcb.Position(3)=0.1;
hcb.Position(4)=0.5;
hcb.TickLabels = [];
tix = reshape([hcb.Ticks; repmat(" ", 1, numel(hcb.Ticks))],[],1);
pos = hcb.Position;
t=annotation('textbox',pos,'String',flip(tix), 'LineStyle','none', 'FontWeight','bold')
t =
TextBox ( , 1, , 0.8, , 0.6, , 0.4, , 0.2, , 0) with properties: String: {12x1 cell} FontName: 'Helvetica' FontSize: 10 FontWeight: 'bold' Color: [0 0 0] BackgroundColor: 'none' EdgeColor: [0 0 0] LineStyle: 'none' LineWidth: 0.5000 Position: [0.8295 0.1098 0.1000 0.5000] Units: 'normalized' Use GET to show all properties
t.HorizontalAlignment="right";
t.VerticalAlignment = "middle";
size(hcb.TickLabels);
sz=size(tix);
You can read more about “annotation” function and its properties here: https://www.mathworks.com/help/matlab/ref/annotation.html
Hope this helps!

4 Comments

Not working. The labels leave the cell.
Ayush
Ayush on 1 Oct 2024
Edited: Ayush on 1 Oct 2024
The labels leave the cell because textbox and texts follow relative positioning.
So, resizing the colorbar can affect the positions of labels and thus the labels are leaving the cell.
you can use callback function to track the "resize" operation on the colorbar and adjust the position of labels accordingly.
Here's a script using this approach:
matrix = magic(3);
imagesc(matrix)
% Define levels and number of ticks (customizable)
levels = 9; % Change this to adjust the number of ticks
tick_vals = linspace(min(matrix(:)), max(matrix(:)), levels);
% Setting up the figure and color settings
current_figure = gcf;
colormap_tones = jet(numel(tick_vals)); % Using jet colormap for a different approach
colormap(colormap_tones)
color_scale = colorbar('Ticks', tick_vals);
% Adjusting the color axis limits based on the range of ticks
color_limits = [min(tick_vals)-0.5, max(tick_vals)+0.5];
caxis(color_limits);
% Convert the tick positions to figure space
colorbar_pos = color_scale.Position;
tick_positions = rescale_range(tick_vals, color_limits, colorbar_pos(2) + [0 colorbar_pos(4)]);
% Generating custom tick labels
for i = 1:numel(tick_vals)
gray_intensity = double(rgb2gray(1 - colormap_tones(i,:)) > 0.5);
annotation('textbox', [colorbar_pos(1), tick_positions(i), 0.05, 0.05], ...
'String', num2str(round(tick_vals(i),2)), 'VerticalAlignment', 'middle', ...
'Color', gray_intensity, 'LineStyle', 'none', 'FontWeight', 'bold');
end
% Hide default tick labels on the colorbar
color_scale.TickLabels = [];
% Adding dynamic resizing behavior for figure
set(current_figure, 'ResizeFcn', @(~,~) adjust_on_resize(color_scale, tick_vals));
% Rescaling the function to update tick positions during figure resize
function adjust_on_resize(color_scale, tick_vals)
colorbar_pos = color_scale.Position;
new_tick_positions = rescale_range(tick_vals, [min(tick_vals)-0.5, max(tick_vals)+0.5], colorbar_pos(2) + [0 colorbar_pos(4)]);
for i = 1:numel(tick_vals)
annotation('textbox', [colorbar_pos(1), new_tick_positions(i), 0.05, 0.05], ...
'String', num2str(round(tick_vals(i),2)), 'LineStyle', 'none');
end
end
% Helper function to rescale values to a new range
function output_vals = rescale_range(input_vals, input_range, output_range)
output_vals = rescale(input_vals, output_range(1), output_range(2), 'InputMin', input_range(1), 'InputMax', input_range(2));
end
Note:I
f the labels extend beyond the boundaries of the colorbar, consider defining custom positions for the labels by adjusting their placement according to the required width of the colorbar.
Hope this helps!
DGM
DGM on 1 Oct 2024
Edited: DGM on 1 Oct 2024
I see what you did there. I also see what you didn't do.

Sign in to comment.

Assuming a discrete colorbar,
% the setup
z = magic(3);
imagesc(z)
% the values associated with each discrete level
ticks = 1:9;
% set the colormap and colorbar
nticks = numel(ticks);
CT = parula(nticks);
colormap(CT)
hcb = colorbar;
hcb.Ticks = ticks;
% set clim so that our ticks are centered on their respective subinterval
% if your ticks are not uniformly-spaced integers, then this needs adjusting
cbrange = imrange(ticks) + [-0.5 0.5];
clim(cbrange);
% rescale tick position from data space to figure space
pos = hcb.Position;
tposy = pos(2) + [0 pos(4)];
tposy = rescalefix(ticks,cbrange,tposy);
% create new ticks
for k = 1:nticks
thislabel = sprintf('%d',ticks(k));
thispos = [pos(1)+pos(3)/2 tposy(k) 0 0];
thiscolor = double(rgb2gray(1-CT(k,:))>0.5);
annotation('textbox',thispos,'string',thislabel, ...
'horizontalalignment','center','verticalalignment','middle', ...
'color',thiscolor,'linestyle','none', 'fontweight','bold');
end
% hide the old ticks once you're sure the new ones are okay
hcb.TickLabels = [];
EDIT: That should help make the labels more readable.

3 Comments

Not working. It is comming like this.
It looks like you're resizing the figure. If you do that, the relative positions change. You need to update the annotation positions.
% the setup
z = magic(3);
imagesc(z)
% the values associated with each discrete level
ticks = 1:9;
% we need the figure handle later
hfig = gcf;
% set the colormap and colorbar
nticks = numel(ticks);
CT = parula(nticks);
colormap(CT)
hcb = colorbar;
hcb.Ticks = ticks;
% set clim so that our ticks are centered on their respective subinterval
% if your ticks are not uniformly-spaced integers, then this needs adjusting
cbrange = imrange(ticks) + [-0.5 0.5];
clim(cbrange);
% rescale tick position from data space to figure space
pos = hcb.Position;
tposy = pos(2) + [0 pos(4)];
tposy = rescalefix(ticks,cbrange,tposy);
% create new ticks
han = gobjects(nticks,1);
for k = 1:nticks
thislabel = sprintf('%d',ticks(k));
thispos = [pos(1)+pos(3)/2 tposy(k) 0 0];
thiscolor = double(rgb2gray(1-CT(k,:))>0.5);
han(k) = annotation('textbox',thispos,'string',thislabel, ...
'horizontalalignment','center','verticalalignment','middle', ...
'color',thiscolor,'linestyle','none', 'fontweight','bold');
end
% hide the old ticks once you're sure the new ones are okay
hcb.TickLabels = [];
% set up a callback that fires when the figure is resized
hfig = gcf; % or use whatever the relevant figure handle is
set(hfig,'resizefcn',{@onresize,ticks,cbrange,hcb,han})
% function to do the size update
function onresize(~,~,ticks,cbrange,hcb,han)
% rescale tick position from data space to figure space
pos = hcb.Position;
tposy = pos(2) + [0 pos(4)];
tposy = rescalefix(ticks,cbrange,tposy);
% adjust ticks
for k = 1:numel(ticks)
thispos = [pos(1)+pos(3)/2 tposy(k) 0 0];
han(k).Position = thispos;
end
end
I don't know what the motivation for this layout actually is, but it should be clear that managing annotations and trying to do direct manipulation of the colorbar costs extra effort and complexity for whatever benefit it has.
On the downside, I think it reduces the readability of both the color patches and the tick labels.
Also note that moving the tick labels into the colorbar doesn't save any space. We never moved the colorbar (and axes) to take advantage of the empty space left by removing the original labels. Doing that would take yet more work to complicate the layout.
Likewise, larger ticklabels would require the colorbar (and the axes) to be resized and repositioned so that the colorbar can be wide enough to accomodate the labels.

Sign in to comment.

It can be done using annotation objects (specifically textbox) however it is definitely a challenge.
Try something like this —
figure
surf(peaks)
hcb = colorbar;
% get(hcb)
hcb.TickLabels = [];
tix = reshape([hcb.Ticks; repmat(" ", 1, numel(hcb.Ticks))],[],1);
pos = hcb.Position;
annotation('textbox',pos,'String',flip(tix), 'LineStyle','none', 'FontWeight','bold')
.

6 Comments

Not working. The labels leave the cell.
Please provide your code and all tthe data files needed to run it.
Here is my sample code:
% Sample code
subplot(1,2,1)
color2=[0 0 1];
color6=[0 1 1];
plot(1,0.5, '.', 'markersize', 2, 'color', color2)
plot(0.1,0.5, '.', 'markersize', 2, 'color', color6)
hold on
c=colorbar('eastoutside', 'Ticks', '', 'Color', [0 0 0], 'Limits', [0 1]);
cmap=[color2; color6;];
numTicks=size(cmap,1);
tickValues=linspace(0, 1, numTicks+1);
midTickvalues=tickValues(1:end-1)+diff(tickValues)/2;
c.Ticks=midTickvalues;
c.TickLabels={'2', '6'};
c.Label.FontSize=1;
c.TickLength=0;
colormap(cmap)
% Sample code
subplot(1,2,1)
color2=[0 0 1];
color6=[0 1 1];
plot(1,0.5, '.', 'markersize', 2, 'color', color2)
plot(0.1,0.5, '.', 'markersize', 2, 'color', color6)
hold on
c=colorbar('eastoutside', 'Ticks', '', 'Color', [0 0 0], 'Limits', [0 1]);
cmap=[color2; color6;];
numTicks=size(cmap,1);
tickValues=linspace(0, 1, numTicks+1);
midTickvalues=tickValues(1:end-1)+diff(tickValues)/2;
c.Ticks=midTickvalues;
c.TickLabels={'2', '6'};
c.Label.FontSize=1;
c.TickLength=0;
colormap(cmap)
% get(c)
TL = c.TickLabels;
pos = c.Position;
tickposv = c.Ticks*pos(4) + pos(2)*0.4;
tickposh = pos(1)*0.975;
annotation('textbox',[tickposh tickposv(1) 0.1 0.1],'String',TL{1}, 'LineStyle','none', 'FontWeight','bold', 'FontSize',12, 'Color','m')
annotation('textbox',[tickposh tickposv(2) 0.1 0.1],'String',TL{2}, 'LineStyle','none', 'FontWeight','bold', 'FontSize',12, 'Color','m')
c.TickLabels = [];
My apologies for the delay. This is the best I can do with this, and it unfortunately requires a bit of ‘kludging’ to get this far. I increased the font size and changed the colour so I could read the repositioned tick labels easily. It should be straightforward to change them to whatever you want in the annotation calls. I am not certain how fragile this code is or how easily it could be extended to to more tick labels. I am reasonably certain that it is not as robust as I would like it to be.
(I am having serious problems with Windows 11 Pro, since it makes the Firefox and DuckDuckGo browsers virtually impossible to use. I could not use Firefox — I could not type anything into any of its text boxes — and DuckDuckGo would freeze for about a minute randomly. It originally worked quite well, and does on another computer. Micro$oft should not just be broken up, it should be shattered! As soon as AMD releases its next high-performance multicore Zen CPU, I intend to buy a new desktop and install only Ubuntu on it. Windows used to be a useful OS. Now it is unstable, loaded with bloatware, and completely unreliable. My apologies for the rant — I am really frustrated with Windows 11 Pro tonight.)
.
Thank you all for your support.

Sign in to comment.

Categories

Find more on Graphics Object Properties in Help Center and File Exchange

Asked:

on 30 Sep 2024

Commented:

on 12 Oct 2024

Community Treasure Hunt

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

Start Hunting!