I am using pcolor to plot matrix X, which has dimensions (286,64) and values ranging from 0 to 20. How do I set specific colors to specific ranges, ie 0-0.5, white; 0.5-1.0, red; 1.0-2.0, orange, ... 15-20, blue? Every time I try to do that using contours and pcolor, the color bar ranges do not align with the tick marks, and the tick marks change from plot to plot, even though I hardwire them in the code.
Thanks?
To specify colors to ranges that are not equally distant, you can either edit the colormap manually, or convert your matrix to an index of range matrix, then define you own colormap. Here is a simple example:
X = randi([0 20],28,64);
C = zeros(size(X)); % the ranges matrix
color_shift = [0 5 11 12]; % the values where the color changes
for k = 1:numel(color_shift)
C(X>color_shift(k)) = k;
end
% your colormap
cmap = [0.8 0.2 0 % 0 - 5
1 0.5 0 % 5 - 11
0.5 0 0.5 % 11 - 12
0.3 0.3 1]; % 12 - 20
pcolor(C)
colormap(cmap)
ch = colorbar;
% setting the ticks on the colorbar:
ch.Ticks = 0:numel(color_shift);
ch.TickLabels = [color_shift max(X(:))];
and you will get somthing like this:
I am trying to use either the contourf or colormap functions to plot filled ellipses with colors according to their arcsin(b/a) value (a=major axis, b=minor axis).
clearvars -except data colheaders
close all
clc
data(:,9)=data(:,9)*pi/180; % Convers Column 9 (angle of rotation) in rad
data(:,6)=1196-data(:,6); % Reset the Y coordinate axis to bottom left
theta = 0 : 0.01 : 2*pi; % Converts phi in rad
imax=29;
% Define colors
cvalues=asin(data(1:imax,8)./data(1:imax,7))./asin(1);
cm = colormap; % returns the current color map
% Sort and get their index to access the color array
[~,idx] = sort(cvalues);
% Create colormap
%ColorMap=jet;
for i=1:imax
x = data(i,7)/2 * cos(theta) * cos(data(i,9)) - data(i,8)/2 * sin(theta) * sin(data(i,9)) + data(i,5);
y = data(i,8)/2 * sin(theta) * cos(data(i,9)) + data(i,7)/2 * cos(theta) * sin(data(i,9)) + data(i,6);
colorID = max(1, sum(cvalues(i) > [0:1/length(cm(:,1)):1]));
ColorMap(i,:) = cm(colorID, :); % returns your color
hold on
% Columns (5,6) are the centre (x,y) of the ellipse
% Columns (7,8) are the major and minor axes (a,b)
% Column 9 is the rotation angle with the x axis
%% TRYING A FASTER WAY OF PLOTTING
%A(:,i)=x';
%B(:,i)=y';
%%
fill(x,y,ColorMap(i,:),'EdgeColor', 'None')
text(data(i,5),data(i,6),[num2str(asin(1)*180*cvalues(i)/pi)]) % Assigns number to each ellipse
end
%%
%fill(A,B,ColorMap(1:200,3)','EdgeColor', 'None')
%%
% Adds colorbar to plot
colorbar('SouthOutside')
caxis([0 90])
axis equal;
%xlim([0 7649]);
%ylim([0 15927]);
grid on;
I get a picture that looks like this which I think works well:
Instead of adding numbers in the ellipses, I have added the angle I obtained (90 for circles, 0 for very long ellipse). Now is my real experiment i will have to plot several thousands ellipses, and we found out that it takes quite alot of time to plot them, you'll see we tried another method to basically record the data and plot all in one go. But we haven't succeeded so far if you have any advice :)
Here is a way using built-in colormaps in Matlab (look here for a complete list).
The trick is to create a n x 3 array where n is the number of colors you wish to represent. Here it's the number of ellipses.
You can create a colormap like so:
MyColorMap = jet(n)); %// jet or anything listed in the link above. You can also create your own colormap.
So that's what we're going to do in the following code. In order to get the order right, we need to sort the values of asin(b/a) and fetch each index for the right ellipse. The code is commented so it's quite easy to follow. I added 4 ellipses in the plot to see the difference in color better:
clear
clc
close all
%// Define dummy data
data = zeros(8,9);
data(:,5) = [3;5;12;8;2;7;4;6]; % Centre location X
data(:,6) = [1; -5 ;-2; 4;2;-3;9;5]; % Centre location Y
data(:,7) = [6 ;7;8;6;1;4;2;5]; % Major Axis a
data(:,8) = [2;5;4;2;2;5;3;7]; % Minor axis b
data(:,9) = [10;40;45;90;35;70;85;110]; % Angle of rotation phi
data(:,9)=data(:,9)*pi/180; % Converts phi in rads
theta = 0 : 0.01 : 2*pi;
%// Define colors here
cvalues = asin(data(:,8)./data(:,7));
%// Sort and get their index to access the color array
[~,idx] = sort(cvalues);
%// Create colormap with the "jet" colors
ColorMap = jet(numel(cvalues));
This is the array containing the "colors". It looks like this:
ColorMap =
0 0 1
0 0.5 1
0 1 1
0.5 1 0.5
1 1 0
1 0.5 0
1 0 0
0.5 0 0
So each row represents a combination of red, blue and green (RGB) and there are as many rows as there are ellipses to plot. Now filling the ellipses:
hold all
for i=1:numel(idx)
k = idx(i);
x = data(k,8)/2 * cos(theta) * cos(data(k,9)) - data(k,7)/2 * sin(theta) * sin(data(k,9)) + data(k,5);
y = data(k,7)/2 * sin(theta) * cos(data(k,9)) + data(k,8)/2 * cos(theta) * sin(data(k,9)) + data(k,6);
fill(x,y,ColorMap(i,:))
plot(x, y, 'LineWidth', 1);
% Label each ellipse with a number
text(data(i,5),data(i,6),num2str(i),'Color','k','FontSize',12)
end
axis equal;
grid on;
Output with the jet colormap: blue is the first ellipse plotted and red is the last. You can add a colorbar if you want (add colorbar)
Using another colormap, the bone colormap, gives the following:
Hope that helps!
I would like to draw a 3D histogram (with gnuplot or octave) in order to represent my data.
lets say that I have a data file in the following form:
2 3 4
8 4 10
5 6 7
I'd like to draw nine colored bars (the size of the matrix), in the set [1,3]x[1,3], such that the bar's color is proportional to the bar's height. How can I do this?
Below is a function I implemented that acts as a bar3 replacement (partially).
In my version, the bars are rendered by creating a patch graphics object: we build a matrix of vertex coordinates and a list of faces connecting those vertices.
The idea is to first build a single "3d cube" as a template, then replicate it for as many bars as we have. Each bar is shifted and scaled according to its position and height.
The vertices/faces matrices are constructed in a vectorized manner (look ma, no loops!), and the result is a single patch object drawn for all bars, as opposed to multiple patches one per bar (this is more efficient in terms of graphics performance).
The function could have been implemented by specifying coordinates of connected vertices that form polygons, by using the XData, YData, ZData and CData properties instead of the Vertices and Faces properties. In fact this is what bar3 internally does. Such approach usually requires larger data to define the patches (because we cant have shared points across patch faces, although I didn't care much about that in my implementation). Here is a related post where I tried to explain the structure of the data constructed by bar3.
my_bar3.m
function pp = my_bar3(M, width)
% MY_BAR3 3D bar graph.
%
% M - 2D matrix
% width - bar width (1 means no separation between bars)
%
% See also: bar3, hist3
%% construct patch
if nargin < 2, width = 0.8; end
assert(ismatrix(M), 'Matrix expected.')
% size of matrix
[ny,nx] = size(M);
% first we build a "template" column-bar (8 vertices and 6 faces)
% (bar is initially centered at position (1,1) with width=? and height=1)
hw = width / 2; % half width
[X,Y,Z] = ndgrid([1-hw 1+hw], [1-hw 1+hw], [0 1]);
v = [X(:) Y(:) Z(:)];
f = [
1 2 4 3 ; % bottom
5 6 8 7 ; % top
1 2 6 5 ; % front
3 4 8 7 ; % back
1 5 7 3 ; % left
2 6 8 4 % right
];
% replicate vertices of "template" to form nx*ny bars
[offsetX,offsetY] = meshgrid(0:nx-1,0:ny-1);
offset = [offsetX(:) offsetY(:)]; offset(:,3) = 0;
v = bsxfun(#plus, v, permute(offset,[3 2 1]));
v = reshape(permute(v,[2 1 3]), 3,[]).';
% adjust bar heights to be equal to matrix values
v(:,3) = v(:,3) .* kron(M(:), ones(8,1));
% replicate faces of "template" to form nx*ny bars
increments = 0:8:8*(nx*ny-1);
f = bsxfun(#plus, f, permute(increments,[1 3 2]));
f = reshape(permute(f,[2 1 3]), 4,[]).';
%% plot
% prepare plot
if exist('OCTAVE_VERSION','builtin') > 0
% If running Octave, select OpenGL backend, gnuplot wont work
graphics_toolkit('fltk');
hax = gca;
else
hax = newplot();
set(ancestor(hax,'figure'), 'Renderer','opengl')
end
% draw patch specified by faces/vertices
% (we use a solid color for all faces)
p = patch('Faces',f, 'Vertices',v, ...
'FaceColor',[0.75 0.85 0.95], 'EdgeColor','k', 'Parent',hax);
view(hax,3); grid(hax,'on');
set(hax, 'XTick',1:nx, 'YTick',1:ny, 'Box','off', 'YDir','reverse', ...
'PlotBoxAspectRatio',[1 1 (sqrt(5)-1)/2]) % 1/GR (GR: golden ratio)
% return handle to patch object if requested
if nargout > 0
pp = p;
end
end
Here is an example to compare it against the builtin bar3 function in MATLAB:
subplot(121), bar3(magic(7)), axis tight
subplot(122), my_bar3(magic(7)), axis tight
Note that I chose to color all the bars in a single solid color (similar to the output of the hist3 function), while MATLAB emphasizes the columns of the matrix with matching colors.
It is easy to customize the patch though; Here is an example to match bar3 coloring mode by using indexed color mapping (scaled):
M = membrane(1); M = M(1:3:end,1:3:end);
h = my_bar3(M, 1.0);
% 6 faces per bar
fvcd = kron((1:numel(M))', ones(6,1));
set(h, 'FaceVertexCData',fvcd, 'FaceColor','flat', 'CDataMapping','scaled')
colormap hsv; axis tight; view(50,25)
set(h, 'FaceAlpha',0.85) % semi-transparent bars
Or say you wanted to color the bars using gradient according to their heights:
M = 9^2 - spiral(9);
h = my_bar3(M, 0.8);
% use Z-coordinates as vertex colors (indexed color mapping)
v = get(h, 'Vertices');
fvcd = v(:,3);
set(h, 'FaceVertexCData',fvcd, 'FaceColor','interp')
axis tight vis3d; daspect([1 1 10]); view(-40,20)
set(h, 'EdgeColor','k', 'EdgeAlpha',0.1)
Note that in the last example, the "Renderer" property of the figure will affect the appearance of the gradients. In MATLAB, the 'OpenGL' renderer will interpolate colors along the RGB colorspace, whereas the other two renderers ('Painters' and 'ZBuffer') will interpolate across the colors of the current colormap used (so the histogram bars would look like mini colorbars going through the jet palette, as opposed to a gradient from blue at the base to whatever the color is at the defined height as shown above). See this post for more details.
I've tested the function in Octave 3.6.4 and 3.8.1 both running on Windows, and it worked fine. If you run the examples I showed above, you'll find that some of the advanced 3D features are not yet implemented correctly in Octave (this includes transparency, lighting, and such..). Also I've used functions not available in Octave like membrane and spiral to build sample matrices, but those are not essential to the code, just replace them with your own data :)
Solution using only functions available in OCTAVE, tested with octave-online
This solution generates a surface in a similar way to the internals of Matlabs hist3d function.
In brief:
creates a surface with 4 points with the "height" of each
value, which are plotted at each bin edge.
Each is surrounded by zeros, which are also plotted at each bin edge.
The colour is set to be based on the bin values and is applied to
the 4 points and the surrounding zeros. (so that the edges and tops of the 'bars' are coloured to match the "height".)
For data given as a matrix containing bin heights (bin_values in the code):
Code
bin_values=rand(5,4); %some random data
bin_edges_x=[0:size(bin_values,2)];
x=kron(bin_edges_x,ones(1,5));
x=x(4:end-2);
bin_edges_y=[0:size(bin_values,1)];
y=kron(bin_edges_y,ones(1,5));
y=y(4:end-2);
mask_z=[0,0,0,0,0;0,1,1,0,0;0,1,1,0,0;0,0,0,0,0;0,0,0,0,0];
mask_c=ones(5);
z=kron(bin_values,mask_z);
c=kron(bin_values,mask_c);
surf(x,y,z,c)
Output
I don't have access to Octave, butI believe this should do the trick:
Z = [2 3 4
8 4 10
5 6 7];
[H W] = size(Z);
h = zeros( 1, numel(Z) );
ih = 1;
for ix = 1:W
fx = ix-.45;
tx = ix+.45;
for iy = 1:W
fy = iy-.45;
ty = iy+.45;
vert = [ fx fy 0;...
fx ty 0;...
tx fy 0;...
tx ty 0;...
fx fy Z(iy,ix);...
fx ty Z(iy,ix);...
tx fy Z(iy,ix);...
tx ty Z(iy,ix)];
faces = [ 1 3 5;...
5 3 7;...
7 3 4;...
7 8 4;...
5 6 7;...
6 7 8;...
1 2 5;...
5 6 2;...
2 4 8;...
2 6 8];
h(ih) = patch( 'faces', faces, 'vertices', vert, 'FaceVertexCData', Z(iy,ix),...
'FaceColor', 'flat', 'EdgeColor','none' );
ih = ih+1;
end
end
view( 60, 45 );
colorbar;
I think the following should do the trick. I didn't use anything more sophisticated than colormap, surf and patch, which to my knowledge should all work as-is in Octave.
The code:
%# Your data
Z = [2 3 4
8 4 10
5 6 7];
%# the "nominal" bar (adjusted from cylinder())
n = 4;
r = [0.5; 0.5];
m = length(r);
theta = (0:n)/n*2*pi + pi/4;
sintheta = sin(theta); sintheta(end) = sqrt(2)/2;
x0 = r * cos(theta);
y0 = r * sintheta;
z0 = (0:m-1)'/(m-1) * ones(1,n+1);
%# get data for current colormap
map = colormap;
Mz = max(Z(:));
mz = min(Z(:));
% Each "bar" is 1 surf and 1 patch
for ii = 1:size(Z,1)
for jj = 1:size(Z,2)
% Get color (linear interpolation through current colormap)
cI = (Z(ii,jj)-mz)*(size(map,1)-1)/(Mz-mz) + 1;
fC = floor(cI);
cC = ceil(cI);
color = map(fC,:) + (map(cC,:) - map(fC,:)) * (cI-fC);
% Translate and rescale the nominal bar
x = x0+ii;
y = y0+jj;
z = z0*Z(ii,jj);
% Draw the bar
surf(x,y,z, 'Facecolor', color)
patch(x(end,:), y(end,:), z(end,:), color)
end
end
Result:
How I generate the "nominal bar" is based on code from MATLAB's cylinder(). One cool thing about that is you can very easily make much more funky-looking bars:
This was generated by changing
n = 4;
r = [0.5; 0.5];
into
n = 8;
r = [0.5; 0.45; 0.2; 0.1; 0.2; 0.45; 0.5];
Have you looked at this tutorial on bar3?
Adapting it slightly:
Z=[2 3 4
8 4 10
5 6 7]; % input data
figure;
h = bar3(Z); % get handle to graphics
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( Z(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
set(h(k),'CData', nz); % set the new colors
end
colorbar;
And here's what you get at the end:
I am newbie in matlab.
I want to draw something like below pic in 3-D axes and move it mouse move.
i do not have problem with second part(move objects on mouse move) ,
i do not know how to create this circle in 3-D axes
elevation = linspace(0,2*pi,100);
r = ones(1,100);
azimuth = .75 * pi *ones(1,100);
while 1
axis([-10 10 -10 10 -10 10])
view([20 20 5])
[newx newy] = ginput(1);
[x,y,z] = sph2cart(azimuth,elevation,r);
x = x + newx;
y = y + newy;
patch(x,y,z,[1 0 0],'EdgeColor','r');
axis([-10 10 -10 10 -10 10])
end
You can change the radius by r like r = .5 * ones(1,100);
But the coordinates of click doesn't seem to be right.
I think you have solved that problem in your previous question.
Note
Coordinates returned by ginput are scaled to the XLim and YLim bounds of the axes you click (data units).
The figure CurrentPoint property, by contrast, is always returned in figure Units, irrespective of axes Units or limits`
I had to plot this in matlab :
so I wrote the following code:
x=[0.9 1 0.9 -0.9 0.7 0.7 -0.9 0.9];
y=[-1 0 1 -0.5 -0.8 0.8 -0.4 -1];
plot(x,y);
but this gives me:
Is this method insufficient to draw the first figure....Is there some other short method for this...
You can do better positioning your data points
nPoints = 7;
th = linspace(-2*pi, 2*pi, 2*nPoints+1);%// extra point to close the curve
r = 1;
x = r*cos(th);
y = r*sin(th);
scatter( x, y, 'ro' );
hold on;
plot( x(1:2:end), y(1:2:end), 'b-' );
axis equal;
Resulting with:
BTW, this code works for any odd nPoints - just try ;)
It seems to me that you want to construct a star polygon, which has the property that all points are equidistant to its neighboring points, and all points lie on the same circle.
First, we generate the desired angles a (measured from the x-axis to a line that connects the origin with the desired point, see wikipedia). Based on the polygon, we rearrage the angles in such a way that a desired number of points is skipped (in the code below, this is done by using among others repmat - but many alternatives exist).
To convert the angles to actual points in the plane, we take sine and cosine values, and then we can plot the dots and lines. Putting this together results in the following code, which results in the dersired figure
n = 7;
a = linspace(0,2*pi,n+1);
skip = 1;
b = [repmat(a(1:end-1),1,skip+1) a(end)];
a = b(1:skip+1:end);
figure;
clf;
hold on;
plot(cos(a),sin(a),'b-');
plot(cos(a(1:end-1)),sin(a(1:end-1)),'ro');
axis([-1 1 -1 1])
axis equal
A little less involved would be to compute the vector a like this:
a = mod(linspace(0,(skip+1)*2*pi,n+1),(skip+1)*2*pi);
I tried manually:
x = [-0.4 0.6 1 0.6 -0.4 -0.8 -0.8];
y = [-0.9 -0.7 0 0.7 0.9 0.4 -0.4];
x_ = [x,x];
y_ = [y,y];
figure;
hold on;
for ii=1:numel(x),
scatter(x(ii),y(ii),'ro');
plot([x_(ii),x_(ii+1+1)],[y_(ii),y_(ii+1+1)],'b-');
end
axis([-1 1 -1 1]);
And I get his: