I have the following figure, where I plotted two surfaces and I wanted to indicate the intersection of both of them. To do that, I did the following:
zdiff = z1-z2;
C = contours(x,y,zdiff,[0 0]);
xL = C(1, 2:end);
yL = C(2, 2:end);
zL = interp2(x, y, z1, xL, yL);
line(xL, yL, zL, 'Color', 'k', 'LineWidth', 2,'Linestyle','--'); hold on;
line(xL, yL, zeros(size(zL)), 'Color', 'k', 'LineWidth', 2); hold off;
Now, I want to plot the vertical surface between the actual intersection (dash line) and its projection over XY (solid line), but I cannot figure out how to do that. Any ideas?
Another really simple option:
dist = (diff(xL).^2+diff(yL).^2).^0.5; %distance between x,y
cdist = [0, cumsum(dist)]; %cumsum of the distance
area = trapz(cdist,zL); %The area
Why not calculating it manually?
Something like (untested):
Area = 0
for i=1:numel(xL)-1
base = sqrt( (xL(i)-xL(i+1))^2 + (yL(i)-yL(i+1))^2);
Area =Area + base * (zL(i) + zL(i+1))/2;
end;
maybe not pretty but its a oneliner it might do the trick. maybe you have to adjust the format as this code is for (1,N) vectors
xL=(1:100); %size 1 100
yL=(1:100) ;%size 1 100
zL=rand(1,100);%size 1 100
line(xL,yL,zL)
line(xL,yL,zeros(size(zL)))
hold on
surf(repmat(xL,100,1),repmat(yL,100,1),cell2mat(arrayfun(#(x,y) linspace(x,y,100)',zL,zeros(size(zL)),'UniformOutput',false)))
xL=sin((1:30)/10); % Data generation for test only. Use your data
yL=cos((1:30)/10); % Data generation for test only. Use your data
zL=2+xL.*yL; % Data generation for test only. Use your data
surf([xL;xL],[yL;yL],[zeros(size(zL));zL]); % plot the surface
I have 4 sets of values: y1, y2, y3, y4 and one set x. The y values are of different ranges, and I need to plot them as separate curves with separate sets of values on the y-axis.
To put it simple, I need 3 y-axes with different values (scales) for plotting on the same figure.
Any help appreciated, or tips on where to look.
This is a great chance to introduce you to the File Exchange. Though the organization of late has suffered from some very unfortunately interface design choices, it is still a great resource for pre-packaged solutions to common problems. Though many here have given you the gory details of how to achieve this (#prm!), I had a similar need a few years ago and found that addaxis worked very well. (It was a File Exchange pick of the week at one point!) It has inspired later, probably better mods. Here is some example output:
(source: mathworks.com)
I just searched for "plotyy" at File Exchange.
Though understanding what's going on in important, sometimes you just need to get things done, not do them yourself. Matlab Central is great for that.
One possibility you can try is to create 3 axes stacked one on top of the other with the 'Color' properties of the top two set to 'none' so that all the plots are visible. You would have to adjust the axes width, position, and x-axis limits so that the 3 y axes are side-by-side instead of on top of one another. You would also want to remove the x-axis tick marks and labels from 2 of the axes since they will lie on top of one another.
Here's a general implementation that computes the proper positions for the axes and offsets for the x-axis limits to keep the plots lined up properly:
%# Some sample data:
x = 0:20;
N = numel(x);
y1 = rand(1,N);
y2 = 5.*rand(1,N)+5;
y3 = 50.*rand(1,N)-50;
%# Some initial computations:
axesPosition = [110 40 200 200]; %# Axes position, in pixels
yWidth = 30; %# y axes spacing, in pixels
xLimit = [min(x) max(x)]; %# Range of x values
xOffset = -yWidth*diff(xLimit)/axesPosition(3);
%# Create the figure and axes:
figure('Units','pixels','Position',[200 200 330 260]);
h1 = axes('Units','pixels','Position',axesPosition,...
'Color','w','XColor','k','YColor','r',...
'XLim',xLimit,'YLim',[0 1],'NextPlot','add');
h2 = axes('Units','pixels','Position',axesPosition+yWidth.*[-1 0 1 0],...
'Color','none','XColor','k','YColor','m',...
'XLim',xLimit+[xOffset 0],'YLim',[0 10],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
h3 = axes('Units','pixels','Position',axesPosition+yWidth.*[-2 0 2 0],...
'Color','none','XColor','k','YColor','b',...
'XLim',xLimit+[2*xOffset 0],'YLim',[-50 50],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
xlabel(h1,'time');
ylabel(h3,'values');
%# Plot the data:
plot(h1,x,y1,'r');
plot(h2,x,y2,'m');
plot(h3,x,y3,'b');
and here's the resulting figure:
I know of plotyy that allows you to have two y-axes, but no "plotyyy"!
Perhaps you can normalize the y values to have the same scale (min/max normalization, zscore standardization, etc..), then you can just easily plot them using normal plot, hold sequence.
Here's an example:
%# random data
x=1:20;
y = [randn(20,1)*1 + 0 , randn(20,1)*5 + 10 , randn(20,1)*0.3 + 50];
%# plotyy
plotyy(x,y(:,1), x,y(:,3))
%# orginial
figure
subplot(221), plot(x,y(:,1), x,y(:,2), x,y(:,3))
title('original'), legend({'y1' 'y2' 'y3'})
%# normalize: (y-min)/(max-min) ==> [0,1]
yy = bsxfun(#times, bsxfun(#minus,y,min(y)), 1./range(y));
subplot(222), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('minmax')
%# standarize: (y - mean) / std ==> N(0,1)
yy = zscore(y);
subplot(223), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('zscore')
%# softmax normalization with logistic sigmoid ==> [0,1]
yy = 1 ./ ( 1 + exp( -zscore(y) ) );
subplot(224), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('softmax')
Multi-scale plots are rare to find beyond two axes... Luckily in Matlab it is possible, but you have to fully overlap axes and play with tickmarks so as not to hide info.
Below is a nice working sample. I hope this is what you are looking for (although colors could be much nicer)!
close all
clear all
display('Generating data');
x = 0:10;
y1 = rand(1,11);
y2 = 10.*rand(1,11);
y3 = 100.*rand(1,11);
y4 = 100.*rand(1,11);
display('Plotting');
figure;
ax1 = gca;
get(ax1,'Position')
set(ax1,'XColor','k',...
'YColor','b',...
'YLim',[0,1],...
'YTick',[0, 0.2, 0.4, 0.6, 0.8, 1.0]);
line(x, y1, 'Color', 'b', 'LineStyle', '-', 'Marker', '.', 'Parent', ax1)
ax2 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','left',...
'Color','none',...
'XColor','k',...
'YColor','r',...
'YLim',[0,10],...
'YTick',[1, 3, 5, 7, 9],...
'XTick',[],'XTickLabel',[]);
line(x, y2, 'Color', 'r', 'LineStyle', '-', 'Marker', '.', 'Parent', ax2)
ax3 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k',...
'YColor','g',...
'YLim',[0,100],...
'YTick',[0, 20, 40, 60, 80, 100],...
'XTick',[],'XTickLabel',[]);
line(x, y3, 'Color', 'g', 'LineStyle', '-', 'Marker', '.', 'Parent', ax3)
ax4 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k',...
'YColor','c',...
'YLim',[0,100],...
'YTick',[10, 30, 50, 70, 90],...
'XTick',[],'XTickLabel',[]);
line(x, y4, 'Color', 'c', 'LineStyle', '-', 'Marker', '.', 'Parent', ax4)
(source: pablorodriguez.info)
PLOTYY allows two different y-axes. Or you might look into LayerPlot from the File Exchange. I guess I should ask if you've considered using HOLD or just rescaling the data and using regular old plot?
OLD, not what the OP was looking for:
SUBPLOT allows you to break a figure window into multiple axes. Then if you want to have only one x-axis showing, or some other customization, you can manipulate each axis independently.
In your case there are 3 extra y axis (4 in total) and the best code that could be used to achieve what you want and deal with other cases is illustrated above:
clear
clc
x = linspace(0,1,10);
N = numel(x);
y = rand(1,N);
y_extra_1 = 5.*rand(1,N)+5;
y_extra_2 = 50.*rand(1,N)+20;
Y = [y;y_extra_1;y_extra_2];
xLimit = [min(x) max(x)];
xWidth = xLimit(2)-xLimit(1);
numberOfExtraPlots = 2;
a = 0.05;
N_ = numberOfExtraPlots+1;
for i=1:N_
L=1-(numberOfExtraPlots*a)-0.2;
axesPosition = [(0.1+(numberOfExtraPlots*a)) 0.1 L 0.8];
if(i==1)
color = [rand(1),rand(1),rand(1)];
figure('Units','pixels','Position',[200 200 1200 600])
axes('Units','normalized','Position',axesPosition,...
'Color','w','XColor','k','YColor',color,...
'XLim',xLimit,'YLim',[min(Y(i,:)) max(Y(i,:))],...
'NextPlot','add');
plot(x,Y(i,:),'Color',color);
xlabel('Time (s)');
ylab = strcat('Values of dataset 0',num2str(i));
ylabel(ylab)
numberOfExtraPlots = numberOfExtraPlots - 1;
else
color = [rand(1),rand(1),rand(1)];
axes('Units','normalized','Position',axesPosition,...
'Color','none','XColor','k','YColor',color,...
'XLim',xLimit,'YLim',[min(Y(i,:)) max(Y(i,:))],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
V = (xWidth*a*(i-1))/L;
b=xLimit+[V 0];
x_=linspace(b(1),b(2),10);
plot(x_,Y(i,:),'Color',color);
ylab = strcat('Values of dataset 0',num2str(i));
ylabel(ylab)
numberOfExtraPlots = numberOfExtraPlots - 1;
end
end
The code above will produce something like this:
In a while loop, I need to plot the positions (x,y) of two entities. That is, all I need to do is generate a plot with two points on it. I need to scale the plot to a specific maximum x and y value. An additional requirement is the fact that one of the points needs to have three concentric rings placed around it, each with a given radius. Additionally, this all is to happen in a loop, thus I'm hoping that only a single plot window opens and that I don't get a whole slew of windows opening (one for each loop iteration).
Basically here's the pseudo-code I'm trying (and failing!) to implement:
-> Open new plot window, with a given x and y axis
while (running) {
-> Clear the plot, so figure is nice and clean
-> Plot the two points
-> Plot the three circles around point A
}
I found several items in MATLAB's documentation, but no single plotting functions seems to do what I want, or there are instances where I inadvertently create multiple plots with only some of the data (i.e., one plot has the points and another has the circles).
here's a sample code you can use in your while loop
x0=1; y0=4;
x1=2; y1=3; % the x-y points
r=[1 2 3]; % 3 radii of concentrating rings
ang=0:0.01:2*pi;
xc=cos(ang)'*r;
yc=sin(ang)'*r;
plot(x0,y0,'.',x1,y1,'.'); % plot the point A
hold on
plot(x1+xc,y1+yc); % plot the 3 circles
% set the limits of the plots (though Matlab does it for you already)
xlim([min([x0 x1])-max(r) max([x0 x1])+max(r)]);
ylim([min([y0 y1])-max(r) max([y0 y1])+max(r)]);
hold off
you can make this work in a loop quite easily, read matlab's documentation on how to do that.
Try something like this:
r = [0.25 0.125 0.0625];
d = (1:360) / 180 * pi;
xy_circle = [cos(d)' sin(d)'];
xy_circle_1 = r(1) * xy_circle;
xy_circle_2 = r(2) * xy_circle;
xy_circle_3 = r(3) * xy_circle;
h_plot = plot(0, 0, '.k');
hold on
h_circle_1 = plot(xy_circle_1(:, 1), xy_circle_1(:, 2), '-b');
h_circle_2 = plot(xy_circle_2(:, 1), xy_circle_2(:, 2), '-r');
h_circle_3 = plot(xy_circle_3(:, 1), xy_circle_3(:, 2), '-g');
axis equal
for hh = 1:100
xy = rand(2, 2) / 4 + 0.375;
xlim = [0 1];
ylim = [0 1];
set(h_plot, 'XData', xy(:, 1));
set(h_plot, 'YData', xy(:, 2));
set(gca, 'XLim', xlim)
set(gca, 'YLim', ylim)
set(h_circle_1, 'XData', xy_circle_1(:, 1) + xy(1, 1));
set(h_circle_1, 'YData', xy_circle_1(:, 2) + xy(1, 2));
set(h_circle_2, 'XData', xy_circle_2(:, 1) + xy(1, 1));
set(h_circle_2, 'YData', xy_circle_2(:, 2) + xy(1, 2));
set(h_circle_3, 'XData', xy_circle_3(:, 1) + xy(1, 1));
set(h_circle_3, 'YData', xy_circle_3(:, 2) + xy(1, 2));
pause(1)
end
You can change the parameters as you wish.
You can use the following functions
figure; %creates a figure
hold on; %overlays points and circles
clf; %clear the figure
and use two types of markers (. and o) of various sizes for the points and circles
plot(x,y, 'b.', 'MarkerSize', 4);
plot(x,y, 'ro', 'MarkerSize', 10);
plot(x,y, 'go', 'MarkerSize', 14);
plot(x,y, 'bo', 'MarkerSize', 18);
I have the following code to generate me a 2D plot or 2 normal distributions:
res = zeros(2, 320);
index = 1:320;
% assign some data to the res array and then approximate:
PD = fitdist(index','normal', 'frequency', res(1,:)')
pdfNormal = normpdf(index',PD.mu,PD.sigma);
plot(index', pdfNormal, 'Color', 'r', 'LineWidth', 2);
hold on;
PD = fitdist(index','normal', 'frequency', res(2,:)')
pdfNormal = normpdf(index',PD.mu,PD.sigma);
plot(index', pdfNormal, 'Color', 'b', 'LineWidth', 2);
This code generates me then the following picture:
Now I am wondering how I could add a third dimension to this plot? Essentially,
I would like to plot another 2 normal distributions, but this time in the Z-axis,
ie., in the third dimension.
Anyone an idea how I could do that easily?
Thanks so much!
If I understood correctly, you can simply give the plots different z-values. Example:
%# some random data
x = 1:300;
y = zeros(5,300);
for i=1:5
y(i,:) = normpdf(x,100+i*20,10);
end
%# plot
hold on
clr = lines(5);
h = zeros(5,1);
for i=1:5
h(i) = plot(x, y(i,:), 'Color',clr(i,:), 'LineWidth',2);
set(h(i), 'ZData',ones(size(x))*i)
end
zlim([0 6]), box on, grid on
view(3)
hold off