Custom colorbar labeling centered on colors

I have a figure for which I want to create custom colorbar labeling. Below is the sample code:
figure;
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(gcf,'units','pixel','position',[70,70,600,600],'papersize',[600,600],'color','w');
ax=gca;
colormap(flipud(jet(11)));
caxis([0 11]);
hcb=colorbar('SouthOutside');
axPos = ax.Position;
colorbarpos=hcb.Position;
hcb.Ruler.TickLabelRotation=0;
set(hcb,'YTick',[0:1:11],'TickLength',colorbarpos(4)/colorbarpos(3));
This gives a standard southoutside, reverse jet colorbar like below:
Instead, I'd like to create custom labels centered on each color...something like below:
Any ideas on how or if this can be done?

 Accepted Answer

f = figure;
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(f,'units','pixel','position',[70,70,600,600],'papersize',[600,600],'color','w');
colormap(flipud(jet(11)));
caxis([0 11]);
hcb=colorbar('SouthOutside','YTick',[]);
colorbarpos=hcb.Position;
ax = axes( ...
'Parent',f, ...
'Units','normalized', ...
'Position',[colorbarpos(1) 0 colorbarpos([3 2])], ...
'Visible','off', ...
'XLim',[0 1], ...
'YLim',[0 1.1]);
text( ...
'Parent',ax, ...
'Position',[0 1], ...
'String',{'Record','Warmest'}, ...
'HorizontalAlignment','left', ...
'VerticalAlignment','top')
text( ...
'Parent',ax, ...
'Position',[1 1], ...
'String',{'Record','Coldest'}, ...
'HorizontalAlignment','right', ...
'VerticalAlignment','top')
patch( ...
'Parent',ax, ...
'XData',[0.15 0.17 0.165 0.17 0.15 0.85 0.83 0.835 0.83 0.85], ...
'YData',[0.8 0.85 0.8 0.75 0.8 0.8 0.85 0.8 0.75 0.8], ...
'EdgeColor','k', ...
'FaceColor','k')
text( ...
'Parent',ax, ...
'Position',[0.2 0.8], ...
'String','Top 5 Warmest', ...
'HorizontalAlignment','left', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
text( ...
'Parent',ax, ...
'Position',[0.8 0.8], ...
'String','Top 5 Coldest', ...
'HorizontalAlignment','right', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')

8 Comments

Amazing! I would not think this code! Very cool
You may want to update the position of that new invisible axes (which contains the arrows and texts) whenever the figure's size changes, in order to avoid the texts overlapping the colorbar. One way to do that is to give the figure a SizeChangedFcn.
One such SizeChangedFcn is attached to this comment. Assign it to be the figure's SizeChangedFcn by adding the following line at the end of the code in my answer.
f.SizeChangedFcn = {@scf_fig,hcb,ax};
The function is very simple and just sets the invisible axes to be directly underneath the colorbar:
function scf_fig(~,~,hcb,ax)
colorbarpos = hcb.Position;
ax.Position = [colorbarpos(1) 0 colorbarpos([3 2])];
Voss
Voss on 18 May 2024
Edited: Voss on 18 May 2024
"Amazing! I would not think this code! Very cool"
This is really good.
I'm attempting to bring this code into a projected map (geographic lat/long coordinate system), but I'm running into issues with the axes when I draw the latitude longitude grid.
Below is a sample using the m_map mapping package (https://www.eoas.ubc.ca/~rich/map.html). Everything works as anticipated before the final m_grid line...
f=figure;
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(f,'units','pixel','position',[70,70,600,600],'papersize',[600,600],'color','w');
m_proj('Miller Cylindrical','lon',[-170 -100],'lat',[20 80]);
colormap(flipud(jet(11)));
caxis([0 11]);
hcb=colorbar('SouthOutside','YTick',[]);
colorbarpos=hcb.Position;
ax = axes( ...
'Parent',f, ...
'Units','normalized', ...
'Position',[colorbarpos(1) 0 colorbarpos([3 2])], ...
'Visible','off', ...
'XLim',[0 1], ...
'YLim',[0 1.1]);
text( ...
'Parent',ax, ...
'Position',[0 1], ...
'String',{'Record','Warmest'}, ...
'HorizontalAlignment','left', ...
'VerticalAlignment','top')
text( ...
'Parent',ax, ...
'Position',[1 1], ...
'String',{'Record','Coldest'}, ...
'HorizontalAlignment','right', ...
'VerticalAlignment','top')
patch( ...
'Parent',ax, ...
'XData',[0.15 0.17 0.165 0.17 0.15 0.85 0.83 0.835 0.83 0.85], ...
'YData',[0.8 0.85 0.8 0.75 0.8 0.8 0.85 0.8 0.75 0.8], ...
'EdgeColor','k', ...
'FaceColor','k')
text( ...
'Parent',ax, ...
'Position',[0.2 0.8], ...
'String','Top 5 Warmest', ...
'HorizontalAlignment','left', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
text( ...
'Parent',ax, ...
'Position',[0.8 0.8], ...
'String','Top 5 Coldest', ...
'HorizontalAlignment','right', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
m_grid('fontsize',12,'xtick',[-180:20:180],'ytick',[-80:20:80],'linestyle',':','fontsize',10);
Any ideas on how to get this onto the projected grid?
The problem is that m_grid uses the figure's CurrentAxes, which, at the point in the code you are calling m_grid, is the invisible axes that contains the arrows and texts. One solution is to call m_grid earlier, say, right after you call m_proj, so that the the first axes created is still the figure's CurrentAxes.
f=figure;
set(gca,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(f,'units','pixel','position',[70,70,600,600],'papersize',[600,600],'color','w');
m_proj('Miller Cylindrical','lon',[-170 -100],'lat',[20 80]);
m_grid('fontsize',12,'xtick',-180:20:180,'ytick',-80:20:80,'linestyle',':','fontsize',10);
colormap(flipud(jet(11)));
caxis([0 11]);
hcb=colorbar('SouthOutside','YTick',[]);
colorbarpos=hcb.Position;
ax = axes( ...
'Parent',f, ...
'Units','normalized', ...
'Position',[colorbarpos(1) 0 colorbarpos([3 2])], ...
'Visible','off', ...
'XLim',[0 1], ...
'YLim',[0 1.1]);
text( ...
'Parent',ax, ...
'Position',[0 1], ...
'String',{'Record','Warmest'}, ...
'HorizontalAlignment','left', ...
'VerticalAlignment','top')
text( ...
'Parent',ax, ...
'Position',[1 1], ...
'String',{'Record','Coldest'}, ...
'HorizontalAlignment','right', ...
'VerticalAlignment','top')
patch( ...
'Parent',ax, ...
'XData',[0.15 0.17 0.165 0.17 0.15 0.85 0.83 0.835 0.83 0.85], ...
'YData',[0.8 0.85 0.8 0.75 0.8 0.8 0.85 0.8 0.75 0.8], ...
'EdgeColor','k', ...
'FaceColor','k')
text( ...
'Parent',ax, ...
'Position',[0.2 0.8], ...
'String','Top 5 Warmest', ...
'HorizontalAlignment','left', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
text( ...
'Parent',ax, ...
'Position',[0.8 0.8], ...
'String','Top 5 Coldest', ...
'HorizontalAlignment','right', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
f.SizeChangedFcn = {@scf_fig,hcb,ax};
Another solution would be to include the 'axes',ax_handle property/value pair in the call to m_grid, where ax_handle is the first axes created, i.e., the one you want m_grid to apply to.
f=figure;
ax_handle = gca();
set(ax_handle,'xtick',[],'xticklabel',[],'ytick',[],'yticklabel',[],'color','w');
set(f,'units','pixel','position',[70,70,600,600],'papersize',[600,600],'color','w');
m_proj('Miller Cylindrical','lon',[-170 -100],'lat',[20 80]);
colormap(flipud(jet(11)));
caxis([0 11]);
hcb=colorbar('SouthOutside','YTick',[]);
colorbarpos=hcb.Position;
ax = axes( ...
'Parent',f, ...
'Units','normalized', ...
'Position',[colorbarpos(1) 0 colorbarpos([3 2])], ...
'Visible','off', ...
'XLim',[0 1], ...
'YLim',[0 1.1]);
text( ...
'Parent',ax, ...
'Position',[0 1], ...
'String',{'Record','Warmest'}, ...
'HorizontalAlignment','left', ...
'VerticalAlignment','top')
text( ...
'Parent',ax, ...
'Position',[1 1], ...
'String',{'Record','Coldest'}, ...
'HorizontalAlignment','right', ...
'VerticalAlignment','top')
patch( ...
'Parent',ax, ...
'XData',[0.15 0.17 0.165 0.17 0.15 0.85 0.83 0.835 0.83 0.85], ...
'YData',[0.8 0.85 0.8 0.75 0.8 0.8 0.85 0.8 0.75 0.8], ...
'EdgeColor','k', ...
'FaceColor','k')
text( ...
'Parent',ax, ...
'Position',[0.2 0.8], ...
'String','Top 5 Warmest', ...
'HorizontalAlignment','left', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
text( ...
'Parent',ax, ...
'Position',[0.8 0.8], ...
'String','Top 5 Coldest', ...
'HorizontalAlignment','right', ...
'VerticalAlignment','middle', ...
'BackgroundColor','w')
m_grid('axes',ax_handle,'fontsize',12,'xtick',[-180:20:180],'ytick',[-80:20:80],'linestyle',':','fontsize',10);
f.SizeChangedFcn = {@scf_fig,hcb,ax};
scf_fig([],[],hcb,ax)
In both of those examples, I'm using the attached SizeChangedFcn for the figure, in order to position the invisible axes properly relative to the colorbar.
The problem I'm seeing now is that the colorbar overlaps the main axes xtick labels, so I guess the colorbar needs to be moved down slightly, which is the same problem (or the opposite problem, really) that you ran into before
which I'm not sure if you found an adequate solution for.
This is extremely elegant and a tremendous help. Thank you!
You're welcome!

Sign in to comment.

More Answers (1)

I tried the folowing code! It is similar with your second graph, but I could replicate the arrows correct. You can edit the code and create the result yoy want
% Create a figure
figure;
% Set the axis properties
set(gca, 'xtick', [], 'xticklabel', [], 'ytick', [], 'yticklabel', [], 'color', 'w');
% Set the figure properties
set(gcf, 'units', 'pixel', 'position', [70, 70, 600, 600], 'papersize', [600, 600], 'color', 'w');
% Get the current axis handle
ax = gca;
% Set the colormap and color limits
colormap(flipud(jet(11)));
caxis([0 11]);
% Create a colorbar
hcb = colorbar('SouthOutside');
% Get axis and colorbar positions
axPos = ax.Position;
colorbarpos = hcb.Position;
% Set tick label rotation
hcb.Ruler.TickLabelRotation = 0;
% Define custom ticks and labels
customTicks = 0:1:11;
customLabels = {'', '', '', '', '', '', '', '', '', '', '', ''};
% Apply custom ticks and labels to the colorbar
set(hcb, 'Ticks', customTicks, 'TickLabels', customLabels, 'TickLength', colorbarpos(4) / colorbarpos(3));
% Add custom annotations
text('Units', 'normalized', 'Position', [0.05, -0.2], 'String', 'Record Warmest', 'FontSize', 10, 'HorizontalAlignment', 'center');
text('Units', 'normalized', 'Position', [0.30, -0.2], 'String', 'Top 5 Warmest', 'FontSize', 10, 'HorizontalAlignment', 'center');
text('Units', 'normalized', 'Position', [0.70, -0.2], 'String', 'Top 5 Coldest', 'FontSize', 10, 'HorizontalAlignment', 'center');
text('Units', 'normalized', 'Position', [0.95, -0.2], 'String', 'Record Coldest', 'FontSize', 10, 'HorizontalAlignment', 'center');
% Add arrows
annotation('textarrow', [0.05 0.00], [0.02 0.02], 'String', '');
annotation('textarrow', [0.35 0.30], [0.02 0.02], 'String', '');
annotation('textarrow', [0.65 0.70], [0.02 0.02], 'String', '');
annotation('textarrow', [0.95 1.00], [0.02 0.02], 'String', '');

Categories

Products

Release

R2024a

Asked:

on 18 May 2024

Commented:

on 20 May 2024

Community Treasure Hunt

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

Start Hunting!