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

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:

Related

Equally spaced x-value for values that are not equally spaced

I'm trying to display a discrete plot with values on the x-axis that are not equally space but I want them to appear equally spaced. I would like a stem plot with the first stick not on the y-axis, and I'd also like to have an horizontal dashed line at y=1.
So far here is what I tried.
x = [10 50 150 3000];
y = [.6 .754 .853 .954];
xv = [1 2 3 4];
stem(xv,y);
set(gca,'XTickLabel',x);
Unfortunately, this is not what I expected. The value on the x-axis are not right and the sticks start on the y-axis and end on the figure edge.
How can I fix this?
EDIT: I initially forgot the horizontal dashed line. Added this.
You just need two tiny additions:
x = [10 50 150 3000];
y = [.6 .754 .853 .954];
xv = [1 2 3 4];
stem(xv, y);
xlim([min(xv)-1 max(xv)+1]); % <--
set(gca, 'xtick', xv); % <--
set(gca, 'xticklabel', x);
You (also) need to explicitly set the xtick option, so that only these ticks are drawn, and no other.
With xlim, you can manipulate the x-axis limits. (Left and right limit might be modified to your needs.)
To add the horizontal dashed line, just add the following at the end:
hold on;
plot([min(xv)-1 max(xv)+1], [1 1], 'k--');
hold off;
(Start and end points of the line might be modified to your needs.)
From Matlab R2018b on, you could also use yline.
The output then looks like this:
When you have a sequence of values that you want to plot equally spaced without any special treatment to what each value actually is, you're essentially defining a set of categories.
MATLAB is good at handling these nicely without any extra trickery to lay them out uniformly on your axes if you declare the values explicitly as categorical.
All you need, therefore, is:
x = [10 50 150 3000];
y = [.6 .754 .853 .954];
stem(categorical(x),y);
yline(1,'--');
ylim([0 1.5]) % Make some space on the y-axis so the horizontal line doesn't sit on the top edge

How to insert two X axis in a Matlab a plot

I would like create a Matlab figure with a double X axis (m/s and km/h) with the same plot.
I have found plotyy and - in Matlab reposity - plotyyy, but I am looking for:
A double X axis.
Together below the plot.
My code is very simple:
stem(M(:, 1) .* 3.6, M(:, 3));
grid on
xlabel('Speed (km/h)');
ylabel('Samples');
M(:, 1) is the speed (in m/s), and M(:, 3) is the data.
I would like only a second line, in the bottom, with the speeds in m/s.
You can do something like the following. In comparison to the solution of #Benoit_11 I do use the normal Matlab labels and refer to both axes with handles so the assignments are explicit.
The following code creates an empty x-axis b with the units m/s with a negligible height. After this, the actual plot is drawn in a second axes a located a bit above the other axes and with units km/h. To plot on a specific axes, insert the axes-handle as the first argument of stem. The conversion from m/s to km/h is directly written in the call to stem. Finally, it's needed to set the xlim-property of the both axes to the same values.
% experimental data
M(:,1) = [ 0, 1, 2, 3, 4, 5];
M(:,3) = [12, 10, 15, 12, 11, 13];
% get bounds
xmaxa = max(M(:,1))*3.6; % km/h
xmaxb = max(M(:,1)); % m/s
figure;
% axis for m/s
b=axes('Position',[.1 .1 .8 1e-12]);
set(b,'Units','normalized');
set(b,'Color','none');
% axis for km/h with stem-plot
a=axes('Position',[.1 .2 .8 .7]);
set(a,'Units','normalized');
stem(a,M(:,1).*3.6, M(:,3));
% set limits and labels
set(a,'xlim',[0 xmaxa]);
set(b,'xlim',[0 xmaxb]);
xlabel(a,'Speed (km/h)')
xlabel(b,'Speed (m/s)')
ylabel(a,'Samples');
title(a,'Double x-axis plot');
As a very simple alternative you could also create a 2nd axis (transparent) and put it below the first one so that you only see the x axis.
Example:
clear
clc
close all
x = 1:10;
x2 = x/3.6;
y = rand(size(x));
hP1 = plot(x,y);
a1Pos = get(gca,'Position');
%// Place axis 2 below the 1st.
ax2 = axes('Position',[a1Pos(1) a1Pos(2)-.05 a1Pos(3) a1Pos(4)],'Color','none','YTick',[],'YTickLabel',[]);
%// Adjust limits
xlim([min(x2(:)) max(x2(:))])
text(2.85,0 ,'m/s','FontSize',14,'Color','r')
text(2.85,.05 ,'km/h','FontSize',14,'Color','r')
Output:
Then you can manually add the x labels for each unit, in different color for example.
The best way i can think to do it is to use 2 plots, for example, you can split the plot into a large and small section by doing something like this:
subplot(100, 1, 1:99) // plot your graph as you normally would
plot(...
subplot(100, 1, 100) // Plot a really small plot to get the axis
plot(...)
b = axis()
axis([b(1:2), 0, 0]) // set the y axis to really small
This is untested, you might need to fiddle around a little but it should hopefully put you on the right track.

Xtick marks and Xtick labels on heatmap in Matlab

Environment: Windows 7 64 bit, Matlab 2014a
Objective:
To draw a heatmap of errors for two parameters to be optimized.
To put proper tick marks and tick values
Draw the grid lines in the correct place
Problem: Arranging the X and Y tick positions and values. When the last ("end") value of the vectors in x and y axes are the same, the code I use puts the ticks and values properly. However, when the end values are different it does not, and produces something really weird.
Below I have included the code which I have modified so that you can run it without the need of adding anything. Of course in my case the error vector are the error values, not random numbers. To see the problem of "end value" use the second b vector.
fontsize = 20
k = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^9, 2^11, 2^13, 2^15]
b = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^8, 2^9, 2^10, 2^11, 2^13, 2^15]
% b = [2^-5, 2^-3, 2^-1, 2^0, 2^1, 2^3, 2^5, 2^7, 2^8, 2^9, 2^10, 2^11, 2^13, 2^19]
errorVector = randi(20, 1, length(b)*length(k))'
figure
% Create a matrix from error vector (size of error vector is [length(k)*length(b),1])
B = reshape(errorVector, [length(b), length(k)])
B = flipud(B)
% imagesc(x,y,C)
imagesc(b, k, B)
title('Heatmap Parameters Percent Error', 'FontSize', fontsize);
% Set colorbar limits
caxis([0 15])
colorbar;
ax1 = gca;
xTickLabel = (k)'
xTick = linspace(k(1), k(end), numel(xTickLabel))';
set(ax1, 'XTick', xTick, 'XTickLabel', xTickLabel)
xlabel('k parameter', 'FontSize', fontsize)
yTickLabel = (b)'
yTick = linspace(b(1), b(end), numel(yTickLabel))';
set(ax1, 'YTick', yTick, 'YTickLabel', flipud(yTickLabel(:)))
ylabel('b parameter', 'FontSize', fontsize)
set(ax1,'FontSize', fontsize)
Here, change any of the end values of b or k vectors, and the program will output a graph where the X and Y ticks are totally wrong.
Also, I would like to draw grid lines. When I use "grid on" it draws grid lines right on the tick marks which is not correct in the case of heatmap. Because tick marks will be in the center of the columns -or rows- but the grid lines should be at the boundaries between the columns -or rows.
By the way if you know a better way to plot a heatmap in Matlab, please do tell.
Please help me solve this problem. Any help is appreciated,
Ilyas
First of all - you don't need to flipud the B matrix - by default imagesc plots the y-data inversed, but you can fix this with the following statement:
set(gca,'ydir','normal');
This also means you don't have to mess around with flipping the tick-labels. You can get the labels right by doing the following:
% replace the imagesc call with:
imagesc(B);
set(gca,'ydir','normal');
% formatting stuff
...
% replace the set commands with:
set(ax1, 'XTick', 1:length(k), 'XTickLabel', k)
set(ax1, 'YTick', 1:length(b), 'YTickLabel', b)
By default, if you don't provide x and y data to the imagesc command, it will number them linearly (1,2,3...). Basically what we've done here is make sure that it has ticks for each of the elements of b and k, and then set the labels to the values of the respective vectors.
Unfortunately, I'm not sure if there is a way to get the grid spacing right with imagesc or not. You could try using pcolor instead, which has it's own set of issues, but allows you to get grid lines (of sorts) between the elements. It also allows you to use an interpolated shading mode, which will make your plot look more like a typical heat map.
To use pcolor instead, you just have to replace imagesc:
% imagesc(B);
% set(gca,'ydir','normal');
pcolor(B);
% this uses a smoother shading method, for a more 'heatmap' like output
% shading interp
Everything else should work as intended, I believe.

Use multiple colorbars in one figure [duplicate]

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.

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.