Use multiple colorbars in one figure [duplicate] - matlab

I am fairly new to Matlab and have a few questions.
I got two surfaces and a plane in the same figure.
I want to use different colormap and colorbar for b and another colormap and colorbar for c. s is fixed color so it's not a problem.
Let me try to explain what I am trying to achieve:
cmap1=colormap(topobathy) -->cmap1 is 64x3 double as expected
cmap2=colormap(redwhitegreen)
create cdata1 using cmap1 (this is the first part I cannot figure out, how to scale z data using cmap1, by default CData contains the z values)
b=surf(x,y,z,cdata1)
colorbar for b using z values
c=pcolor(x,y,(z-z0)) - I want to use cmap2 for this one.
colorbar for c using (z-z0) values
Here is what I have so far and the problems I encounter
b=surf(x,y,z);
colormap(topobathy);
cbar1=colorbar;
set(get(cbar1,'ylabel'),'String', 'Elevation (m)', 'Rotation', 90)
hold on;
s=surf(x,y,z1,'FaceColor',[0.278 0.788 0.788])
hold on;
change=z-z0;
c=pcolor(x,y,change)
set(c,'ZData',100 + 0*change); %plotting it above the other surfaces
colormap(redwhitegreen)`
at this point colormap is set to redwhitegreen for b, colorbar of b
I can't get the second colorbar with its own clim etc.
I used the freezeColors and cbfreeze explained in this link:
http://blogs.mathworks.com/pick/2009/07/24/using-multiple-colormaps-in-a-single-figure/
but one thing works while messing another thing (probably all my fault). I want to learn how to have complete control over my objects without using external m files anyway.
Any help is appreciated.

The basic idea is that you concatenate the colormaps, and then shift/scale the color data (CData) of the different plot handles to line up with the desired portions of the colormap. So, without knowing what your custom functions or specific data are, you could do something like colormap(topobathy(64); redwhitegreen(64)) and then scale the CData of b into the range [1,64] and the CData of c into the range [65,128].
There is an excellent guide on the MathWorks website that explains all this (even uses surf() and pcolor() like your example):
http://www.mathworks.com/support/tech-notes/1200/1215.html#Example_1
For the colorbar, you can just fake out the ticks and labels in a similar manner. Here is rough shot at making a color bar for the above example:
h = colorbar;
ticks = [1 16:16:64 64:16:128];
ticks(5:6) = [62 66];
set(h, 'YTick', ticks);
labels = num2str(repmat(linspace(min(Z(:)), max(Z(:)), 5), 1, 2)', 2);
set(h, 'YTickLabel', labels)

I had the same problem as you, and the best (and only) solution I found was the next:
Concatenate both colormaps I wanted:
cmap1 = jet(64); cmap2 = copper(64); color_map = [cmap1 ; cmap2];
So, the first colormap (cmap1) will be used for Axes1, and the second colormap (cmap2) for Axes2. I guess that Axes1 and Axes2 are in the same figure.
Normalize data, giving a scale from 0 to 1 for data of Axes1, and from 1 to 2 for data of Axes2. So, Axes1 in [0, 1] and Axes2 in [1 2].
data1 = data1 - lower_limit1;
data1 = double(data1./(upper_limit1 - lower_limit1));
For data set of Axes 2:
data2 = data2 - lower_limit;
data2 = double(data2./(upper_limit2 - lower_limit2)) + 1;
When representing them:
Axes1:
pcolor(handle_axes1, x_axis, y_axis, data1); shading(handle_axes1,'FLAT');
caxis(handle_axes1, [0 2]);
% Colorbar
h_colorbar = colorbar('peer', handle_axes1);
set(h_colorbar, 'YLim', [0 1]);
labels = num2str(linspace(lower_limit1, upper_limit1, 6)', 2);
set(h_colorbar, 'YTick', linspace(0, 1, 6));
set(h_colorbar, 'YTickLabel', labels);
Axes2:
pcolor(handle_axes2, x_axis, y_axis, data2); shading(handle_axes2,'FLAT');
caxis(handle_axes2, [0 2]);
% Colorbar
h_colorbar2 = colorbar('peer', handle_axes2);
set(h_colorbar2, 'YLim', [1 2]);
labels = num2str(linspace(lower_limit2, upper_limit2, 6)', 2);
set(h_colorbar2, 'YTick', linspace(1, 2, 6));
set(h_colorbar2, 'YTickLabel', labels);
Use pcolor or surf, depending on your needs.
Hope it helps!

Matlab has provided code for a function newclim which solves this problem cleanly by concatenating the colormaps into one colormap. I could only find this documentation on the 2012b Help, but not online.
Note that the axes used to update the CLim as the last step could be axes to surf plots, which is how I applied this code.
Calculating Color Limits
The key to this example is calculating values for CLim that cause each surface to use the section of the colormap containing the appropriate colors.
To calculate the new values for CLim, you need to know
The total length of the colormap (CmLength)
The beginning colormap slot to use for each axes (BeginSlot)
The ending colormap slot to use for each axes (EndSlot)
The minimum and maximum CData values of the graphic objects contained
in the axes. That is, the values of the axes CLim property determined
by MATLAB when CLimMode is auto (CDmin and CDmax).
First, define subplot regions and plot the surfaces.
im1 = load('cape.mat');
im2 = load('flujet.mat');
ax1 = subplot(1,2,1);
imagesc(im1.X)
axis(ax1,'image')
ax2 = subplot(1,2,2);
imagesc(im2.X)
axis(ax2,'image')
Concatenate two colormaps and install the new colormap.
colormap([im1.map;im2.map])
Obtain the data you need to calculate new values for CLim.
CmLength = length(colormap); % Colormap length
BeginSlot1 = 1; % Beginning slot
EndSlot1 = length(im1.map); % Ending slot
BeginSlot2 = EndSlot1 + 1;
EndSlot2 = CmLength;
CLim1 = get(ax1,'CLim'); % CLim values for each axis
CLim2 = get(ax2,'CLim');
Defining a Function to Calculate CLim Values
Computing new values for CLim involves determining the portion of the colormap you want each axes to use relative to the total colormap size and scaling its Clim range accordingly. You can define a MATLAB function to do this.
function CLim = newclim(BeginSlot,EndSlot,CDmin,CDmax,CmLength)
% Convert slot number and range
% to percent of colormap
PBeginSlot = (BeginSlot - 1) / (CmLength - 1);
PEndSlot = (EndSlot - 1) / (CmLength - 1);
PCmRange = PEndSlot - PBeginSlot;
% Determine range and min and max
% of new CLim values
DataRange = CDmax - CDmin;
ClimRange = DataRange / PCmRange;
NewCmin = CDmin - (PBeginSlot * ClimRange);
NewCmax = CDmax + (1 - PEndSlot) * ClimRange;
CLim = [NewCmin,NewCmax];
end
The input arguments are identified in the bulleted list above. The function first computes the percentage of the total colormap you want to use for a particular axes (PCmRange) and then computes the CLim range required to use that portion of the colormap given the CData range in the axes. Finally, it determines the minimum and maximum values required for the calculated CLim range and returns these values. These values are the color limits for the given axes.
Using the Function
Use the newclim function to set the CLim values of each axes. The statement
set(ax1,'CLim',newclim(BeginSlot1,EndSlot1,CLim1(1),...
CLim1(2),CmLength))
sets the CLim values for the first axes so the surface uses color slots 65 to 120. The lit surface uses the lower 64 slots. You need to reset its CLim values as well.
set(ax2,'CLim',newclim(BeginSlot2,EndSlot2,CLim2(1),...
CLim2(2),CmLength))
How the Function Works
MATLAB enables you to specify any values for the axes CLim property, even if these values do not correspond to the CData of the graphics objects displayed in the axes. The minimum CLim value is always mapped to the first color in the colormap and the maximum CLim value is always mapped to the last color in the colormap, whether or not there are really any CData values corresponding to these colors. Therefore, if you specify values for CLim that extend beyond the object's actual CData minimum or maximum, MATLAB colors the object with only a subset of the colormap.
The newclim function computes values for CLim that map the graphics object's actual CData values to the beginning and ending colormap slots that you specify. It does this by defining a "virtual" graphics object having the computed CLim values.

Related

MATLAB: Specify a fixed color for zero in imagesc [duplicate]

I have a wide range of values and while plotting as a scatter(x,y,z), the colorbar showing the z axis shows a wide range of values, now I am not interested in the lower range values. Is there any method to change the range in color bar.
I have the following part of my code to plot, I also intend to plot the log plot. For eg. I want to set the range in my log plot to 14 to the maximum value.
I want some values not to be displayed at all. so that the color bar has a limited range, say from 14 to maximum. At present it is showing from 9 to maximum in the log plot.
scatter(x(1:end-1), y(1:end-1), 5, gnd);
title('G plot (m^-^2)');
colorbar('eastoutside');
xlabel(' X-axis (microns)');
ylabel('Y-axis (microns)');
figure;
log_g=log10(gnd);
scatter(x(1:end-1), y(1:end-1), 5,log_g);
colorbar('eastoutside');
xlabel(' X-axis (microns)');
ylabel('Y-axis (microns)');
title('G Density, log plot (m^-^2)');
I believe that caxis is the command you're looking for. Usage:
caxis([minValue maxValue])
Using caxis like this, all values outside the range [minValue maxValue] will be coloured with the lowest or highest value in the colormap, respectively.
Since colorbar and friends use colormap, you'll have to adjust the current colormap if you want to adjust the number of colors used. Do this like so:
%# get current colormap
map = colormap;
%# adjust for number of colors you want
rows = uint16(linspace(1, size(map,1), NUM_COLORS)) ;
map = map(rows, :);
%# and apply the new colormap
colormap(map);
Of course, combining this with caxis is the most powerful.
If you don't want to show some values outside of range, that's not a job for colorbar or caxis, that's up to you -- you'll have to adjust the data that's plotted so that all values you don't want plotted are NaN. Doing so will make Matlab understand that you don't want to plot these data:
data( indices_to_data_not_to_plot ) = NaN;
surf(x,y,data); %# or whatever you're using
How about this?
% don’t know why, but apparently your x and y are one value too long?
x = x(1:end-1); y = y(1:end-1);
% only plot values of 14 or higher
scatter(x(gnd>=14), y(gnd>=14), 5, gnd(gnd>=14);
Try this:
cmap = colormap; % get current colormap
cmap=cmap([min max],:); % set your range here
colormap(cmap); % apply new colormap
colorbar();

How do you rescale the height of a histogram?

I am having trouble plotting a histogram of the x-values of my data points together with a line showing the relationship between x and y, mainly because the scale in the y direction of the histogram is not of the same magnitude as the scale in the line plot. For example:
% generate data
rng(1, 'twister')
x = randn(10000,1);
y = x.^2
% plot line, histogram, then histogram and line.
subplot(3,1,1)
scatter(x, y, 1, 'filled')
ax = gca;
maxlim = max(ax.XLim); % store maximum y-value to rescale histogram to this value
subplot(3,1,2)
h = histogram(x, 'FaceAlpha', 0.2)
subplot(3,1,3)
scatter(x, y, 1, 'filled')
hold on
h = histogram(x, 'FaceAlpha', 0.2)
Produces the following:
where the line chart is completely obscured by the histogram.
Now, one might naively try to rescale the histogram using:
h.Values = h.Values/max(h.Values) * maxlim;
which gives
You cannot set the read-only property 'Values' of Histogram.
Alternatively one can get the bin counts using histcounts, but as far as I can tell, the bar function does not allow one to set the face alpha or have other configurability as per the call to histogram.
As discussed in the comments there are several solutions that depend on the version of Matlab you are using. To restate the problem, the histogram function allows you to control many graphics properties like transparency, but only gives you a limited number of options to change the height of the bars. With histcounts you can get the bar heights and rescale them however you want, but you must plot the bars yourself.
First option: use histogram
As you cannot rescale the histogram heights, you must plot them on separate axis.
From release 2016a and onwards, you can use yyaxis left for the scatter plot and yyaxis right for the histogram, see Matlab documentation:
Prior to this one must manually create and set separate y-axis. Although I have not found a good simple example of this, this is perhaps the most relevant answer here: plot two histograms (using the same y-axis) and a line plot (using a different y-axis) on the same figure
Using histcounts and manually creating a bar chart
Using my example, we can get counts as follows:
[Values, Edges] = histcounts(x);
And rescaling:
Values = Values / max(Values) * maxlim;
and finding centres of bars:
bar_centres = 0.5*(Edges(1:end-1) + Edges(2:end));
Up to release 2014a, bar charts had a 'children' property for the patches that allows transparency to be controlled, e.g.:
% plot histogram
b1 = bar(bar_centres,Values);
% change transparency
set(get(b1,'Children'),'FaceAlpha',0.3)
After 2014a bar charts no longer have this property, and to get around it I plot the patches myself using the code from this mathworks q&a, replicated here:
function ptchs = createPatches(x,y,offset,c,FaceAlpha)
%createPatches.m
% This file will create a bar plot with the option for changing the
% FaceAlpha property. It is meant to be able to recreate the functionality
% of bar plots in versions prior to 2014b. It will create the rectangular
% patches with a base centered at the locations in x with a bar width of
% 2*offset and a height of y.
% Ensure x and y are numeric vectors
validateattributes(x,{'numeric'},{'vector'});
validateattributes(y,{'numeric'},{'vector'});
validateattributes(c,{'char'},{'scalar'});
%#TODO Allow use of vector c
% Check size(x) is same as size(y)
assert(all(size(x) == size(y)),'x and y must be same size');
% Default FaceAlpha = 1
if nargin < 5
FaceAlpha = 1;
end
if FaceAlpha > 1 || FaceAlpha <= 0
warning('FaceAlpha has been set to 1, valid range is (0,1]');
FaceAlpha = 1;
end
ptchs = cell(size(x)); % For storing the patch objects
for k = 1:length(x)
leftX = x(k) - offset; % Left Boundary of x
rightX = x(k) + offset; % Right Boundary of x
ptchs{k} = patch([leftX rightX rightX leftX],...
[0 0 y(k) y(k)],c,'FaceAlpha',FaceAlpha, ...
'EdgeColor', 'none');
end
end
I made one change: that is, imposed the no edge condition. Then, it is perfectly fine to use:
createPatches(bin_centres, Values, 1,'k', 0.2)
to create the bars.

Change Colorbar Scheme

I read in an image in MATLAB and display it using imagesc. I then set the colormap to grey.
On top of this image, I plot points with the jet colour scheme. How do I then display the jet colorbar, to correspond to the colours of the points plotted on top of the original image? I tried redefining the colorbar after all of the plots, but this changes the original grey scale image back to colours, which isn't desired.
Code:
%Create Figure with handle.
h5=figure('units','normalized','outerposition',[0 0 1 1]);
whitebg(h5,[0 0 0]);
subplot(2,5,1);
k=1;
for i=16:25
subplot(2,5,k);
imagesc(squeeze(ana(:,:,i)));
title(['Z=',num2str(i)]);
colormap gray
axis equal
k=k+1;
colorbar
end
%Adapt colour values so that they are between 0 and 1. We want to scale
%both data sets equally, so we find the smallest value across Ix and Iy. We
%also find what will be the new largest value across Ix and Iy, after we
%add the magnitude of the smallest value to make all numbers greater than
%or equal to 0.
absolutemin=min(min(Ix(:,1)),min(Iy(:,1)));
absolutemax=max(abs(absolutemin)+(max(Ix(:,1))),abs(absolutemin)+max(Iy(:,1)));
%Add the smallest value, and divide by the largest maximum value for both Ix
%and Iy.
ixcolours=uint8(((Ix(:,1)+abs(absolutemin))/absolutemax).*255)+1;
iycolours=uint8(((Iy(:,1)+abs(absolutemin))/absolutemax).*255)+1;
mycolours=jet(256);
o=1;
for k=16:25; %For all 3D slices
for i=1:471; %and for all x and y seed slices
if k==seed_locs(i,3);
subplot(2,5,o);
hold all%go to the corresponding z subplot
plot(seed_locs(i,1),seed_locs(i,2),'MarkerFaceColor',mycolours(ixcolours(i),:),'MarkerEdgeColor',mycolours(ixcolours(i),:),'MarkerSize',10,'Marker','s') %plot the x and y seedlocs
%hold on
end
end
for i=1:486;
if k==test_locs(i,3);
subplot(2,5,o);
hold all
plot(test_locs(i,1),test_locs(i,2),'MarkerFaceColor',mycolours(iycolours(i),:),'MarkerEdgeColor',mycolours(iycolours(i),:),'MarkerSize',10,'Marker','s') %plot the x and y seedlocs
% hold on
end
end
o=o+1; %go to the next z subplot
end
colormap jet
colorbar
I think the following example can help you to improve your code. You firstly need to define two colormaps:
colormap([cool(64);gray(64)]);
Then let's say we have two different sets of datapoints to plot:
[X,Y,Z] = peaks(25);
h(1) = surf(X,Y,Z);hold on
h(2) = pcolor(X,Y,Z);
So the data is defined with two different handles. Now we need to make the CData using the minimum and maximum values.
cmin = min(Z(:));
cmax = max(Z(:));
C1 = min(64,round((64-1)*(Z-cmin)/(cmax-cmin))+1); % CData for the first datapoints
C2 = 64+C1; % CData for the second datapoints
Now we update the CDatas for each object.
set(h(1),'CData',C1);
set(h(2),'CData',C2);
Now you can set the CLim property of axes:
caxis([min(C1(:)) max(C2(:))])
colorbar;

MATLAB: how to customize non linear X axis (for example ticks at 1,2,3,4,5,20,100,'string')

I'm using the MATLAB plot feature to compare two vectors. I would like my X axis to represent 1 through 7, and then 14, 21, and then a category at the end for points with undetermined X values..(I'm also not sure how to represent these numberless point (they have Y values, just no X values) I could assign a large number outside any of my X values (1000) to these points, do the 1-7,14,21,1000 and then change the 1000 label to my 'string for un-numbered points'. ??
Here is a way to do it based on the example by The Mathworks here.
The trick is to create 2 x axis with different ranges and make one of them transparent. You can then play around with its properties. I modified a bit their code but kept most of their comments because they explain well the steps.
For the demo I used scatter to represent the points and colored the "good" points in red and the other point (here only 1) in green. You can customize all this of course. For instance I used a value of 100 and not 1000 for the x value of the 2nd axes, but I'll let you figure out how to modify it all to change the output as you wish.
clear
clc
close all
%// Create axes 1 and get its position
hAxes1 = axes;
axes_position = get(hAxes1, 'Position');
%// Create axes 2 and place it at the same position than axes 1
hAxes2 = axes('Position', axes_position);
%// Your data go here.
x = [1 7 14 21 100];
y = rand(1, length(x));
%// Plot the two sections of data on different axes objects
hPlot1 = scatter(hAxes1, x(1:4), y(1:4),40,'r','filled');
hold on
hPlot2 = scatter(hAxes2, x(end), y(end),40,'g','filled');
%// Link the y axis limits and fontsize property of the axes objects
linkaxes([hAxes1 hAxes2], 'y');
linkprop([hAxes1 hAxes2], 'FontSize');
%// Set the x range limits and tick mark positions of the first axes object
set(hAxes1, 'XLim', [1 25], ...
'XTick', [1 7 14 21])
%// Set the x range limits and tick mark positions for the second axes object.
%// Also set the background color to 'none', which makes the background
%// transparent.Add the label for the "super points".
set(hAxes2, 'Color', 'none', ...
'YTickLabel', [], ...
'XLim', [95 100], ...
'XTick', 100,'XTickLabel',{'Super Points'})
And the output:
EDIT
If you wish to add a fit line, I suggest adding a 3rd axes at the same position than the other 2, make it transparent and remove its X- and Y-ticks.
i.e. Add something like this:
hAxes3 = axes('Position', axes_position,'Color','none','YTick',[],'XTick',[]);
And in the call to polyfit/polyval, in my example you want to get only the first 4 elements (i.e. the red ones).
Hence:
p = polyfit(x(1:4),y(1:4),1);
y_poly = polyval(p,x(1:4));
And then plot the line on hAxes3:
hPlot3 = plot(x(1:4),y_poly)
Output:

Matlab: How to assign different colormaps/colorbars to different surfaces in the same Figure

I am fairly new to Matlab and have a few questions.
I got two surfaces and a plane in the same figure.
I want to use different colormap and colorbar for b and another colormap and colorbar for c. s is fixed color so it's not a problem.
Let me try to explain what I am trying to achieve:
cmap1=colormap(topobathy) -->cmap1 is 64x3 double as expected
cmap2=colormap(redwhitegreen)
create cdata1 using cmap1 (this is the first part I cannot figure out, how to scale z data using cmap1, by default CData contains the z values)
b=surf(x,y,z,cdata1)
colorbar for b using z values
c=pcolor(x,y,(z-z0)) - I want to use cmap2 for this one.
colorbar for c using (z-z0) values
Here is what I have so far and the problems I encounter
b=surf(x,y,z);
colormap(topobathy);
cbar1=colorbar;
set(get(cbar1,'ylabel'),'String', 'Elevation (m)', 'Rotation', 90)
hold on;
s=surf(x,y,z1,'FaceColor',[0.278 0.788 0.788])
hold on;
change=z-z0;
c=pcolor(x,y,change)
set(c,'ZData',100 + 0*change); %plotting it above the other surfaces
colormap(redwhitegreen)`
at this point colormap is set to redwhitegreen for b, colorbar of b
I can't get the second colorbar with its own clim etc.
I used the freezeColors and cbfreeze explained in this link:
http://blogs.mathworks.com/pick/2009/07/24/using-multiple-colormaps-in-a-single-figure/
but one thing works while messing another thing (probably all my fault). I want to learn how to have complete control over my objects without using external m files anyway.
Any help is appreciated.
The basic idea is that you concatenate the colormaps, and then shift/scale the color data (CData) of the different plot handles to line up with the desired portions of the colormap. So, without knowing what your custom functions or specific data are, you could do something like colormap(topobathy(64); redwhitegreen(64)) and then scale the CData of b into the range [1,64] and the CData of c into the range [65,128].
There is an excellent guide on the MathWorks website that explains all this (even uses surf() and pcolor() like your example):
http://www.mathworks.com/support/tech-notes/1200/1215.html#Example_1
For the colorbar, you can just fake out the ticks and labels in a similar manner. Here is rough shot at making a color bar for the above example:
h = colorbar;
ticks = [1 16:16:64 64:16:128];
ticks(5:6) = [62 66];
set(h, 'YTick', ticks);
labels = num2str(repmat(linspace(min(Z(:)), max(Z(:)), 5), 1, 2)', 2);
set(h, 'YTickLabel', labels)
I had the same problem as you, and the best (and only) solution I found was the next:
Concatenate both colormaps I wanted:
cmap1 = jet(64); cmap2 = copper(64); color_map = [cmap1 ; cmap2];
So, the first colormap (cmap1) will be used for Axes1, and the second colormap (cmap2) for Axes2. I guess that Axes1 and Axes2 are in the same figure.
Normalize data, giving a scale from 0 to 1 for data of Axes1, and from 1 to 2 for data of Axes2. So, Axes1 in [0, 1] and Axes2 in [1 2].
data1 = data1 - lower_limit1;
data1 = double(data1./(upper_limit1 - lower_limit1));
For data set of Axes 2:
data2 = data2 - lower_limit;
data2 = double(data2./(upper_limit2 - lower_limit2)) + 1;
When representing them:
Axes1:
pcolor(handle_axes1, x_axis, y_axis, data1); shading(handle_axes1,'FLAT');
caxis(handle_axes1, [0 2]);
% Colorbar
h_colorbar = colorbar('peer', handle_axes1);
set(h_colorbar, 'YLim', [0 1]);
labels = num2str(linspace(lower_limit1, upper_limit1, 6)', 2);
set(h_colorbar, 'YTick', linspace(0, 1, 6));
set(h_colorbar, 'YTickLabel', labels);
Axes2:
pcolor(handle_axes2, x_axis, y_axis, data2); shading(handle_axes2,'FLAT');
caxis(handle_axes2, [0 2]);
% Colorbar
h_colorbar2 = colorbar('peer', handle_axes2);
set(h_colorbar2, 'YLim', [1 2]);
labels = num2str(linspace(lower_limit2, upper_limit2, 6)', 2);
set(h_colorbar2, 'YTick', linspace(1, 2, 6));
set(h_colorbar2, 'YTickLabel', labels);
Use pcolor or surf, depending on your needs.
Hope it helps!
Matlab has provided code for a function newclim which solves this problem cleanly by concatenating the colormaps into one colormap. I could only find this documentation on the 2012b Help, but not online.
Note that the axes used to update the CLim as the last step could be axes to surf plots, which is how I applied this code.
Calculating Color Limits
The key to this example is calculating values for CLim that cause each surface to use the section of the colormap containing the appropriate colors.
To calculate the new values for CLim, you need to know
The total length of the colormap (CmLength)
The beginning colormap slot to use for each axes (BeginSlot)
The ending colormap slot to use for each axes (EndSlot)
The minimum and maximum CData values of the graphic objects contained
in the axes. That is, the values of the axes CLim property determined
by MATLAB when CLimMode is auto (CDmin and CDmax).
First, define subplot regions and plot the surfaces.
im1 = load('cape.mat');
im2 = load('flujet.mat');
ax1 = subplot(1,2,1);
imagesc(im1.X)
axis(ax1,'image')
ax2 = subplot(1,2,2);
imagesc(im2.X)
axis(ax2,'image')
Concatenate two colormaps and install the new colormap.
colormap([im1.map;im2.map])
Obtain the data you need to calculate new values for CLim.
CmLength = length(colormap); % Colormap length
BeginSlot1 = 1; % Beginning slot
EndSlot1 = length(im1.map); % Ending slot
BeginSlot2 = EndSlot1 + 1;
EndSlot2 = CmLength;
CLim1 = get(ax1,'CLim'); % CLim values for each axis
CLim2 = get(ax2,'CLim');
Defining a Function to Calculate CLim Values
Computing new values for CLim involves determining the portion of the colormap you want each axes to use relative to the total colormap size and scaling its Clim range accordingly. You can define a MATLAB function to do this.
function CLim = newclim(BeginSlot,EndSlot,CDmin,CDmax,CmLength)
% Convert slot number and range
% to percent of colormap
PBeginSlot = (BeginSlot - 1) / (CmLength - 1);
PEndSlot = (EndSlot - 1) / (CmLength - 1);
PCmRange = PEndSlot - PBeginSlot;
% Determine range and min and max
% of new CLim values
DataRange = CDmax - CDmin;
ClimRange = DataRange / PCmRange;
NewCmin = CDmin - (PBeginSlot * ClimRange);
NewCmax = CDmax + (1 - PEndSlot) * ClimRange;
CLim = [NewCmin,NewCmax];
end
The input arguments are identified in the bulleted list above. The function first computes the percentage of the total colormap you want to use for a particular axes (PCmRange) and then computes the CLim range required to use that portion of the colormap given the CData range in the axes. Finally, it determines the minimum and maximum values required for the calculated CLim range and returns these values. These values are the color limits for the given axes.
Using the Function
Use the newclim function to set the CLim values of each axes. The statement
set(ax1,'CLim',newclim(BeginSlot1,EndSlot1,CLim1(1),...
CLim1(2),CmLength))
sets the CLim values for the first axes so the surface uses color slots 65 to 120. The lit surface uses the lower 64 slots. You need to reset its CLim values as well.
set(ax2,'CLim',newclim(BeginSlot2,EndSlot2,CLim2(1),...
CLim2(2),CmLength))
How the Function Works
MATLAB enables you to specify any values for the axes CLim property, even if these values do not correspond to the CData of the graphics objects displayed in the axes. The minimum CLim value is always mapped to the first color in the colormap and the maximum CLim value is always mapped to the last color in the colormap, whether or not there are really any CData values corresponding to these colors. Therefore, if you specify values for CLim that extend beyond the object's actual CData minimum or maximum, MATLAB colors the object with only a subset of the colormap.
The newclim function computes values for CLim that map the graphics object's actual CData values to the beginning and ending colormap slots that you specify. It does this by defining a "virtual" graphics object having the computed CLim values.