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?

 Akzeptierte Antwort

Voss
Voss am 18 Mai 2024
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 Kommentare

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])];
Thank you very much!
Voss
Voss am 18 Mai 2024
Bearbeitet: Voss am 18 Mai 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.
John Cruce
John Cruce am 20 Mai 2024
This is extremely elegant and a tremendous help. Thank you!
Voss
Voss am 20 Mai 2024
You're welcome!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Athanasios Paraskevopoulos
Bearbeitet: Athanasios Paraskevopoulos am 18 Mai 2024
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', '');

Kategorien

Mehr zu Color and Styling finden Sie in Hilfe-Center und File Exchange

Produkte

Version

R2024a

Gefragt:

am 18 Mai 2024

Kommentiert:

am 20 Mai 2024

Community Treasure Hunt

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

Start Hunting!

Translated by