Product Support
1215 - Using Multiple Colormaps in a Single Figure
- Background
- Useful Properties
- Example 1: Using Two Colormaps in a Single Axes
- Example 2: Use a Different Colormap in Two Separate Axes
- Example 3: Use Three Colormaps in a Single Axes
- Example 4: Use Multiple 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).
- 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
% 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.
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.
Store