MATLAB Answers

How do I use multiple colormaps in a single figure?

I have a figure in which I wish to use multiple colormaps. I would also like to know where the colormaps are stored and what are some of its properties. Examples will be useful.

2 Answers

Answer by MathWorks Support Team on 10 Nov 2015
 Accepted Answer

1. Background

2. Useful Properties

3. Example 1: Using Two Colormaps in a Single Axes

4. Example 2: Use a Different Colormap in Two Separate Axes

5. Example 3: Use Three Colormaps in a Single Axes

6. Example 4: Use Multiple Colormaps in a Single Figure

7. Example 5: Overlay Multiple Axes with Differing Colormaps in a Single Figure

Background

Each figure has its own colormap, stored in the Colormap property. To view it, you can use the command:

 

ColorMap = get(gcf,'Colormap')

All the objects which are children of a figure refer to the parent figure's colormap if they need to access one. If you want two or more different objects to use varying colors, however, it is possible to construct a colormap that contains several smaller colormaps concatenated together and force each object to use a different section of the larger colormap corresponding to the small colormap. For example, you can build a colormap that consists of the cool and gray colormaps by doing the following:

 

cmap = [cool(32); gray(32)];

The first 32 rows of cmap are from the cool colormap, and the last 32 rows are from the gray colormap.

Useful Properties

Three properties that are used to determine the range of colors used to color an object are CData, CLim, and CDataMapping. They are defined below, or you can refer to the Handle Graphics Online Documentation for more in-depth information:

  • CData: The CData property contains a matrix that defines the colors at every point in the ZData (YData for 2-D patches). By default, Patch and Surface objects scale their CData into the colormap. The minimum value of the CData is mapped to the first row of the colormap, and the maximum value is mapped to the last row of the colormap. The remaining elements are mapped proportionally to rows in the colormap using the following equation:

 

m = size(colormap,1);  % Number of colors in the current
                       % colormap
CData = get(H,'CData') % Where H is a handle to a surface or
                       % patch object
cmin = min(CData(:));  % Minimum color value
cmax = max(CData(:));  % Maximum color value
idx = min(m,round((m-1)*(CData-cmin)/(cmax-cmin))+1);

idx contains integer values that range from 1 to the length of the colormap. The values are the actual row numbers of the colors used in the surface plot.

The CData for an image object defines the rows in the colormap used to color the corresponding pixel (or bin). If the CData is logical, than a value of 0 corresponds to the first row, and a value of 1 to the second row. In this case to use multiple colormaps the CData should be converted to direct indexing; this is demonstrated in Example 2.

  • CDataMapping: The CDataMapping property of Patch and Surface objects determines whether the objects scale their CData into the colormap (which is the default behavior) or whether the CData is a direct index into the colormap and should not be scaled.
  • CLim: CLim is a property of Axes objects. It is a two-element vector that defines the color range. Usually, the CLim property contains the minimum and maximum values of the CData. You can use the caxis command to change the axes CLim property.

By manipulating these three properties, you can force different objects to use different portions of the colormap. First, scale the CData properties of the individual objects so that they have nonoverlapping, contiguous values and the same range. If the CData values do overlap, then the plots will share some of the same colors. After scaling, set the CLim property so that it contains the minimum and maximum values of all the CData matrices. The following examples illustrate how to use multiple colormaps in single axes and multiple axes.

Example 1: Using Two Colormaps in a Single Axes

 

% Define a colormap that uses the cool colormap and 
% the gray colormap and assign it as the Figure's colormap.
colormap([cool(64);gray(64)])
% Generate some surface data.
[X,Y,Z] = peaks(30);
% Produce the two surface plots.
h(1) = surf(X,Y,Z);
hold on
h(2) = pcolor(X,Y,Z);
hold off
% Move the pcolor to Z = -10.
% The 0*Z is in the statement below to insure that the size
% of the ZData does not change.
set(h(2),'ZData',-10 + 0*Z)
set(h(2),'FaceColor','interp','EdgeColor','interp')
view(3)
% Scale the CData (Color Data) of each plot so that the 
% plots have contiguous, nonoverlapping values.  The range 
% of each CData should be equal. Here the CDatas are mapped 
% to integer values so that they are easier to manage; 
% however, this is not necessary.
% Initially, both CDatas are equal to Z.
m = 64;  % 64-elements is each colormap
cmin = min(Z(:));
cmax = max(Z(:));
% CData for surface
C1 = min(m,round((m-1)*(Z-cmin)/(cmax-cmin))+1); 
% CData for pcolor
C2 = 64+C1;
% Update the CDatas for each object.
set(h(1),'CData',C1);
set(h(2),'CData',C2);
% Change the CLim property of axes so that it spans the 
% CDatas of both objects.
caxis([min(C1(:)) max(C2(:))])

In this example, the CData properties of each object are mapped to integer values. The surface CData, C1, ranges from 1 to 64. 64 was chosen because it uses the first 64 rows of the colormap. Since the pcolor plot used the second half of the colormap, simply add 64 to C1 and the new CData matrix, C2, ranges from 65 to 128. As you can see, both C1 and C2 have the same range, 64. They are contiguous and do not overlap.

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)​

If you are using a MATLAB R2014a and earlier, the following example with show how you can get different colormaps for two separate axes. 

 

% Load some image data.
load clown
% Define a colormap that consists of two separate colormaps.
% The object in the left axes will use the first half of the
% colormap, and the object in the right axes will use the
% second half.
cmap1 = map;
cmap2 = gray(size(map,1));
cmap = [cmap1;cmap2];
colormap(cmap)
% Generate the first image.
subplot(121)
image(X)
% Generate the second image.  In this axes, the image data 
% is scaled to start at 1+<the maximum value of other 
% image>.  This is the equivalent of setting the CData 
% for each image so that they have contiguous, nonoverlapping 
% values.
subplot(122)
X2 = X + max(X(:));
image(X2)

Note that if surface or patch plots were used instead of images, you would also have to set the CLim properties of each axis to [min(X(:)) max(X2(:))]. The following code fragment illustrates how to do this using the SET function rather than CAXIS:

 

ax = findobj(gcf,'Type','axes');
set(ax,'CLim', [min(X(:)) max(X2(:))])

Note that we can set the CLim property of both axes simultaneously with SET; CAXIS will only affect one axis.

If the CData is logical, it should be converted to direct indexing in order to use more than the first 2 rows of the colormap. For example, following the same process as above, but with a binary image:

 

load clown;
%Create logical CData 
X = X>mean(X(:));
subplot(121)
h(1) = image(X);
subplot(122)
h(2) = image(X);
cmap1 = summer(2);
cmap2 = copper(2);
cmap = [cmap1;cmap2];
colormap(cmap)
%CData for h(1) and h(2), should be converted from logical 
%indexing to direct indexing in order to make use of more than 2 colors  
%"1" is of type double by default, so adding to logical CData causes 
%the result to be converted to double due to class precedence
h1CData = get(h(1),'CData');
%This converts from logical to direct indexing
h1CData = h1CData + 1;
set(h(1),'CData', h1CData );
h2CData = get(h(2),'CData');
%First convert from logical to direct indexing
%Conversion from logical can also be done directly using DOUBLE:
h2CData = double(h2CData);
%Convert to direct index starting at 1 instead of 0
h2CData = h2CData + 1;
%Then set to different part of colormap than first image
h2CData = h2CData + max(h1CData(:));
set(h(2),'CData', h2CData );

Example 3: Use Three Colormaps in a Single Axes

 

% Create some polar data to work with.
theta = linspace(0,2*pi,40);
rho = [5:.5:10]';
[rho,theta] = meshgrid(rho,theta);
% Map the polar coordinates to Cartesian coordinates.
[X,Y] = pol2cart(theta,rho);
Z = (sin(X)./X) + .05*sin(3*Y);
% Generate a black wire mesh plot.
hm = mesh(X,Y,Z);
set(hm,'FaceColor','none','EdgeColor','k')
hold on
ax = axis;
axis(ax)
% Project Data to the different planes.
h(1) = surf(X,Y,ax(5)+0*Z,Z); % X-Y Plane Projection
h(2) = surf(X,ax(4)+0*Y,Z);   % X-Z Plane Projection
h(3) = surf(ax(2)+0*X,Y,Z);   % Y-Z Plane Projection
set(h,'FaceColor','interp','EdgeColor','interp')
% Build a colormap that consists of three separate
% colormaps.
cmapX = bone(32);
cmapY = cool(32);
cmapZ = jet(32);
cmap = [cmapX;cmapY;cmapZ];
colormap(cmap)
% Map the CData of each surface plot to a contiguous, 
% nonoverlapping set of data.  Each CData must have
% the same range.
zmin = min(Z(:));
zmax = max(Z(:));
% CDX ranges from 1 to 32.
cdx = min(32,round(31*(Z-zmin)/(zmax-zmin))+1);
% CDY ranges from 33 to 64.
cdy = cdx+32;
% CDZ ranges from 65 to 96.
cdz = cdy+32;
% Update the CDatas.
set(h(1),'CData',cdx)
set(h(3),'CData',cdy)
set(h(2),'CData',cdz)
% Change CLim (Color Limits) so that it spans all the CDatas
caxis([min(cdx(:)) max(cdz(:))])

This example operates in much the same way Example 1 does. However, instead of partitioning the colormap into two pieces it partitions the colormap into three sections.

Example 4: Use Multiple Colormaps in a Single Figure

If you have the Image Processing Toolbox, you can use SUBIMAGE in conjunction with subplot to create figures with multiple images, even if the images have different colormaps. SUBIMAGE works by converting images to truecolor for display purposes, thus avoiding colormap conflicts.

More information on this can be found in the Displaying Multiple Images section of the documentation for the Image Processing Toolbox, in particular the documentation for SUBIMAGE:

http://www.mathworks.com/help/images/ref/subimage.html

Example 5: Overlay Multiple Axes with Differing Colormaps in a Single Figure

This example shows how to overlay two axes in a figure and link them. One axes contains a contourm plot of a peaks function. The other axes contains a pcolor plot of the 2nd derivative of the peaks function.

Since there is no CData property in contour plots, we can not manually assign it a portion of the colormap from the axes like Example 1 does. The contour plots automatically use the whole colormap of the axes. Instead, we can give the contour plot and pcolor plot each its own axes (with differing colormaps) and then overlay the two.

The first axes is created, set with a gray colormap, and is filled with the pcolor plot. The second axes is then created, set to be invisible with a cool colormap, and then filled with the contourm plot. Each axes also gets its own colorbar on each side of the figure with correct values. Finally, the two axes are linked so that they always mimic each others bounds. Without this, panning and zooming would only affect the last created axes which is on top of the rest.

 

%create data
[X,Y,Z] = peaks(30);
Zprime = del2(Z);
contourmin = min(Z(:));
contourmax = max(Z(:));
pcolormin = min(Zprime(:));
pcolormax = max(Zprime(:));
%create figure and store handle
hF = figure;
%create axes for pcolor and store handle
hAxesP = axes;
%set colormap for pcolor axes
colormap(hAxesP,gray);
%plot pcolor for gradient
pcolorPlot = pcolor(X,Y,Zprime);
set(pcolorPlot,'FaceColor','interp','EdgeColor','interp');
%create color bar and set range for color
cbP = colorbar(hAxesP,'Location','west');
caxis(hAxesP,[pcolormin pcolormax]);
%create axes for the countourm axes
hAxesCM = axes;
%set visibility for axes to 'off' so it appears transparent
axis(hAxesCM,'off')
%set colormap for contourm axes
colormap(hAxesCM,cool);
%plot contourm
contourmPlot = contourm(X,Y,Z,20);
%create color bar and set range for color
cbCM = colorbar(hAxesCM,'Location','east');
caxis(hAxesCM,[contourmin contourmax]);
%link the two overlaying axes so they match at all times to remain accurate
linkaxes([hAxesP,hAxesCM]);

  3 Comments

Thanks for this hint, it almost solved my problem. The remaining issue in my case is that with the procedure described above (multiple objects in same axis using different ranges of the colormap), I cannot plot a colorbar anymore. What I need is a colorbar for just one of the objects (i.e. for a certain subrange of the colormap), with proper labelling of the corresponding Z-Values next to the colorbar. With the procedure you describe, the colorbar will show all colormaps and the values labelled next to it have nothing to do with the Z-Data of my plot

Is it possible to use subimage within a GUI? It doesn't seem to accept a handle to the figure. Same problem with subplot.

@Nico: With R2014b, this can be done easily. Conidering example 3 from above, you could add a colorbar only for the h(1) surface with the original values via

cb = colorbar; cb.Limits=[1 32]; ticks=str2double(cb.TickLabels)/32; tl = zmin+ticks*(zmax-zmin); cb.TickLabels=num2cell(tl);

@Jason: Both subimage and subplot do NOT take figure handles as input, please consult their corresponding doc pages. Please open another thread and describe your problem as this is not really related to colormaps anymore.

Log in to comment.


Answer by sanjeet
on 8 Jun 2015
Edited by sanjeet
on 9 Jun 2015

I wannt to overlap three images to get single image showing all three color corresponding to the property of original image in the final image. . I started using the standard approach of using 1 image a s background and second imaged as transparent set using AlphaData and repmat to give fading form. But it will not be clear for 3 or four images. If i need to assign the colorbar for both subplot as per thier image (even say I make one as 'cool') and the color bar for the result be as per the result image

I tried the above method for indexig based on separate colormap.. but nothing I am geting ..Can you suggest the correct approach for overlaying three image to one

  2 Comments

Gaurav Pathak commented "I have exactly the same problem still looking for the solution."

Sanjeet,

You can contact MathWorks Technical Support for help on this issue.

Nalini

Log in to comment.


Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

MATLAB Academy

New to MATLAB?

Learn MATLAB today!