How can I use (and display) two different colormaps on the same figure?

Hey all,
My issue is that I would like to present a contour style map utilising m_map functions (using m_pcolor with colormap 'jet') that is overlaid with some scattered data (using m_scatter with colormap 'cool'). These two colormaps would then be displayed either side of the plot for reference. To me this seems quite a simple task but I can't seem to get Matlab to do it.
Can anyone help me? I've searched through the online community answers and there seem to be some answers that sound like they are relevant but then turn out not to be.
Thanks, Nick

1 Comment

I have personally found it much easier to just append 2 colormaps to create a combined colormap then scale your data to utilise the different regions of the appended colormap.
Eg:
%Create the combined colormap!
x = 1:2:1000;
s=jet(1000);
p=cool(1000);
m = [s(x,:);p(x,:)];
%Get some points
[X,Y] = meshgrid([0:0.1:1],[0:0.1:1] );
figure
%use the combined map
colormap(m);
%plot from 0 to 1 using the cool map
imagesc([0:0.1:1],[0:0.1:1],Y,[-1 1])
hold on
%Scale the other data between 0 and 500
s= surf(X,Y,0.4*ones(11),X*500);
s.CDataMapping = 'direct';
campos([1 1 0.5]);

Sign in to comment.

 Accepted Answer

It depends. Are you trying to put the pcolor in the same axes or in different axes. Starting in R2014b, MATLAB has a separate colormap for each axes, so the second case becomes pretty easy.
If you've got the first case (where they're in the same axes) things aren't as simple. If you've got R2014b or R2015a, then you can create two axes and overlay them. It would look a bit like the following:
%%Create two axes
ax1 = axes;
[x,y,z] = peaks;
surf(ax1,x,y,z)
view(2)
ax2 = axes;
scatter(ax2,randn(1,120),randn(1,120),50,randn(1,120),'filled')
%%Link them together
linkaxes([ax1,ax2])
%%Hide the top axes
ax2.Visible = 'off';
ax2.XTick = [];
ax2.YTick = [];
%%Give each one its own colormap
colormap(ax1,'hot')
colormap(ax2,'cool')
%%Then add colorbars and get everything lined up
set([ax1,ax2],'Position',[.17 .11 .685 .815]);
cb1 = colorbar(ax1,'Position',[.05 .11 .0675 .815]);
cb2 = colorbar(ax2,'Position',[.88 .11 .0675 .815]);
As you can see, the messiest part of that is that you don't get automatic layout with two colorbars. That means that you need to position them yourself.
If you're using an earlier version of MATLAB, then things are a little harder. There are a couple of file exchange utilties for combining two colormaps and then offseting the CData of one of your objects. That's probably the approach you'd have to take.

16 Comments

Hi Mike,
thanks for taking the time to answer my question. I decided to bite the bullet and upgrade to 2014b and your code works perfectly. I had a few further little problems when trying to combine your technique with the m_map toolbox. Whenever m_grid is built onto a particular m_proj range it builds a patch of solid white colour, negating the effect of your "ax2.Visible = 'off';" So I've had to hack it slightly by refraining from using m_grid for my second axis and then separately defining the axes positions.
But I'm well on the way to a suitable plot!
Thanks for your help.
N
Don't you mean upgrade to R2015a??? You didn't "upgrade" to an old version did you?
I should have also mentioned the other obvious approach here. That's to just give up on colormapping for one of the objects and use RGB colors. You can convert using ind2rgb. That'd look something like this:
ax = axes;
[x,y,z] = peaks;
surf(ax,x,y,z)
view(2)
colormap(ax1,'hot')
c = randn(1,120);
cmap_len = 64;
cmap = cool(cmap_len);
cmap_index = ind2rgb(floor(cmap_len*(c-min(c))/(max(c)-min(c)));
rgb = squeeze(cmap_index,cmap));
hold on
ax.SortMethod = 'childorder';
scatter(ax,randn(1,120),randn(1,120),50,rgb,'filled')
You'd need to do a bunch of futzing around to create the extra colorbar, and it'd be a pain if the data was changing. But it might be simpler than dealing with two axes.
Does not work with axesm though...At the end both assume one colormap...IDK why...
Your code works so well with Matlab 2016a. Thank you so much!
@Jakub I also have run into the issue with axesm and colormaps being merged. Pretty annoying.
The code works for me mostly, however the pcolor and contour plot I create do not overlap in size. the position set for both axis is however the same.
Code used:
figure_width = 14;
figure_height = 10;
% --- setup plot windows
figuresVisible = 'on'; % 'off' for non displayed plots (will still be exported)
hfig = figure(1); clf;
set(hfig,'Visible', figuresVisible)
set(hfig, 'units', 'centimeters', 'pos', [5 5 figure_width figure_height])
set(hfig, 'PaperPositionMode', 'auto');
set(hfig, 'Renderer','opengl');
set(hfig, 'Color', [1 1 1]); % Sets figure background
set(gca, 'Color', [1 1 1]); % Sets axes background
% --- dimensions and position of plot
hsp = subplot(1,1,1, 'Parent', hfig);
set(hsp,'Position',[0.15 0.17 0.75 0.80]);
ax1 = axes;
%%plot
colorDepth = 1000;
hold on;
% 3D flat plot
caxis([0 100]);
cmap = fliplr(jet(colorDepth));
colormap(ax1, cmap(1:800,:));
hplot = pcolor(ax1, xAxis, yAxis, Data2D);
shading flat; % do not interpolate pixels
axis image
set(gca,'XLim',[xAxis(1) xAxis(end)]);
% colorbar
hcb = colorbar('location','EastOutside', ...
'FontSize' , FontSize , ...
'FontName' , FontName);
set(hcb, 'Ylim', [0 100]);
set(hcb, ...
'Box' , 'on' , ...
'TickDir' , 'in' , ...
'TickLength' , [.02 ] , ...
'LineWidth' , 0.6);
% contour plot
ax2 = axes;
colormap(ax2, flipud(gray(colorDepth)));
[C,hfigc] = contour(ax2, xAxis, yAxis, DataMean2D,zlevs);
%%Link them together
linkaxes([ax1,ax2])
%%Hide the top axes
ax2.Visible = 'off';
ax2.XTick = [];
ax2.YTick = [];
set(hfigc, 'LineWidth',1.0);
set(hfigc, ...
'ShowText','on', ...
'TextStep',get(hfigc,'LevelStep')*2 );
hcollab = clabel(C,hfigc,'LabelSpacing',350); %
set(hcollab, ...
'BackgroundColor',[.99 .99 .99], ...
'Edgecolor',[.1 .1 .1], ...
'FontSize',FontSize - 5, ...
'FontName', FontName, ...
'Color',[0 0 0], ...
'Rotation',0, ...
'HorizontalAlignment','center', ...
'Margin',2)
hold off;
setup axis plot properties
set([ax1, ax2], ...
'Box' , 'on' , ...
'TickDir' , 'in' , ...
'TickLength' , [.02 .02] , ...
'XMinorTick' , 'off' , ...
'YMinorTick' , 'off' , ...
'XGrid' , 'off' , ...
'YGrid' , 'off' , ...
'XColor' , [.0 .0 .0], ...
'YColor' , [.0 .0 .0], ...
'LineWidth' , 0.6 );
% bring axis on top again (fix matlab bug)
set([ax1,ax2],'Layer', 'top');
%%Then add colorbars and get everything lined up
set([ax1,ax2],'Position',[.17 .11 .685 .815]);
I also get this problem with different sizes. Did you find a solution to this problem?
The trick to getting them to line up is to extract the axis properties from the first axis. Here's an example.
P = get(ax1,'Position');
XLIM = get(ax1,'XLim');
YLIM = get(ax1,'YLim');
PA = get(ax1,'PlotBoxAspectRatio');
set(ax2,'Position',P,'XLim',XLIM,'YLim',YLIM,'PlotBoxAspectRatio',PA)
I got this working well, but am now I'm trying to repeat it with a series of subplots, is this possible? I've had no success.
See:
Example 2: Use a Different Colormap in Two Separate Axes
If you are using MATLAB R2014b or later release, the function "colormap" accepts the handle to axes as input and allows you to set different colormaps for each axes. For example the following code snippet will plot two subplots with different colormaps.
figure
ax1 = subplot(2,1,1);
surf(peaks)
colormap(ax1,spring)
ax2 = subplot(2,1,2);
surf(peaks)
colormap(ax2,winter)
Does this work for a 3D plot? Basically, I want to overlay these two 3D plots which have their own colormap. So after merging, it should have a look like in this answer but with a 3D view. Thanks!
Finally achieved by changing the linkaxes to linkprop, successfully combined a 3D scatter plot with its own colormap with a surf plot also has its own colormap. Talk is cheap, show me the code:
load([idDataDir,filesep,'Acond.mat']); % load skymap condition number
[x,y,z] = sphere(300); % generate a 300 faces unit sphere
% convert sources coord. to spherical
[id_x,id_y,id_z] = sph2cart(idRA,idDec,1);
[sim_x,sim_y,sim_z] = sph2cart(simRA_nm,simDec_nm,1);
[matched_x,matched_y,matched_z] = sph2cart(matched_alpha,matched_dec,1);
figure
ax1 = axes;
surf(ax1,x,y,z,Acond,'EdgeColor','Interp','FaceColor','Interp');
axis equal
ax2 = axes;
scatter3(ax2,id_x,id_y,id_z,40,idSNR,'filled');
hold on
scatter3(ax2,sim_x,sim_y,sim_z,'o','MarkerEdgeColor','#888E8F')
scatter3(ax2,matched_x,matched_y,matched_z,[],matched_snr,'s');
% connect identified sources with matched true sources with great circle on
% sphere
center = zeros(1,3); % center of sphere
for src = 1:length(idRA)
[v] = GreatCircle(center,[id_x(src),id_y(src),id_z(src)],[matched_x(src),matched_y(src),matched_z(src)],1);
plot3(ax2,v(1,:),v(2,:),v(3,:),'m')
% pause
end
axis equal
% Link two axes together
hLink = linkprop([ax1,ax2],{'XLim','YLim','ZLim','CameraUpVector','CameraPosition','CameraTarget'});
% Hide the top axes
ax2.Visible = 'off';
ax2.XTick = [];
ax2.YTick = [];
% Give each one its colormap
colormap(ax1)
colormap(ax2,'spring')
% get everthin lined up
cb1 = colorbar(ax1,'Position',[0.1 0.1 0.05 0.815]); % four-elements vector to specify Position [left bottom width height]
cb2 = colorbar(ax2,'Position',[0.81 0.1 0.05 0.815]);
cb1.Label.String = 'Condition Number';
cb2.Label.String = 'SNR';
cb1.Label.FontSize = 14;
cb2.Label.FontSize = 14;
legend({'Grid','Identified Sources','True Sources','Matched True Source','Matched & Identi.'},'Location','southeast')
setappdata(gcf,'StoreTheLink',hLink); % store the link so that they can rotate and zoom synchronically
Code above finally produces a combined, synchronized 3D view of surf and scatter3 plot.
It works with separate figure but it doesnt in gui. see my thread (https://www.mathworks.com/matlabcentral/answers/837288-overlay-two-images-in-gui). maybe somebody can help me.
I am having trouble getting two different colourmaps to work within subplots. That is each subplot has two colourmaps. I can get it to work for a figure containing one 3D plot with two surfaces using different colourmaps, but I can't get the same thing to work when making subplots (to compare two different simulations side by side). I tried exporting the figures as different types of png, tiffn etc with higher resolution then using imread to make subplots, but the resulting figure has extremely low resolution (the axis labels etc are very poorly reproduced), no matter what settings I used when exporting the figures.
I tried importing the figures, but both colorbars where not read.
Do you know how I can use the axes command to save two different axes which I can then set two different colorbars to, when making subplots?
Thank you in advance.
Sometimes using axes overlays is problematic. For example, plotting the two toroid surfaces below is not possible if they are in different axes. If it's not clear why, see this animation of the axes rotating.
Instead of using axes overlays, use the CData property to specify TrueColor arrays. For more info and a demo see my full answer in another thread or Voss' answer using a slightly different approach.

Sign in to comment.

More Answers (0)

Products

Asked:

on 26 Mar 2015

Commented:

on 6 May 2025

Community Treasure Hunt

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

Start Hunting!