Let me start by saying that I suspect this is a very simple solution that I am somehow barely missing.
I'm trying to write a script that will plot one set of data in four separate subplots (each showing a different view of a 3D shape the points are being plot in), but I only want to show the current points - as in, I don't want to see every point, just one set of points as they progresses with time (I'm capturing video of the plot to visualize movement with time). However, for every instant in time, there are n points to plot simultaneously. I know this should be simple, but I can't manage to get all n points to plot at once - I can only seem to get it to plot one point at a time, which is pretty meaningless when you have n markers moving with time, all of which you'd like to see moving at the same time.
The following code works to plot every point in sequence, but does not plot all n points together, refreshing those points for every t:
n = 0;
for i = 1:length(data)
% every marker occurs in one row of a specific set of data, and is split
% into x, y, z, so I correct here for each marker being every 3rd column
for j = 1:(cind/3) % cycle through every marker
x = markerLoc(i, j*3 - 2);
y = markerLoc(i, j*3 - 1);
z = markerLoc(i, j*3);
if j == 1 && i == 1 % set up the initial plots for each subplot
% s1,2,3,4 are the handles for the subplots
h1 = scatter3(s1,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
h2 = scatter3(s2,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
h3 = scatter3(s3,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
h4 = scatter3(s4,x, y, z, 'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
else % update data
% this is probably insanely redundant
set(h1, 'XData', x, 'YData', y, 'ZData', z);
set(h2, 'XData', x, 'YData', y, 'ZData', z);
set(h3, 'XData', x, 'YData', y, 'ZData', z);
set(h4, 'XData', x, 'YData', y, 'ZData', z);
end
end
frames(n) = getframe(gcf); % capture frames
n = n + 1;
end
Can anyone help find what I need to change here to make it plot, instead of after every j (individual marker), after ever nth j?
As it is, you are currently only updating the XData, YData, and ZData for one marker at each instant at a time. Instead you want to get rid of the inner loop and get an array of x, y, and z variables. You can then use these for the scatter3 calls as well as to update the XData, YData, and ZData.
for i = 1:length(data)
%// Get XYZ coordinates for all markers at this time and reshape so X,Y,Z are rows
xyz = reshape(markerLoc(i,:), 3, []);
if i == 1
%// Put these in an array so we can update them easier
h(1) = scatter3(s1, xyz(1,:), xyz(2,:), xyz(3,:), ...
'MarkerFaceColor', [0 .75 .75],...
'MarkerEdgeColor','k');
%// Just use copyobj to make a copy of this plot to all axes
h(2:4) = copyobj(h(1), [s2, s3, s4]);
else
set(h, 'XData', xyz(1,:), 'YData', xyz(2,:), 'ZData', xyz(3,:))
end
end
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:
I have many 3D scatter points (x, y, z) that are guaranteed to be within a triangle. I now wish to visualize z as one smooth 2D heat map, where positions are given by (x, y).
I can easily do it with meshgrid and mesh, if (x, y) together form a rectangle. Because I don't want anything falling outside of my triangle, I can't use griddate either.
Then how?
MWE
P = [0 1/sqrt(3); 0.5 -0.5/sqrt(3); -0.5 -0.5/sqrt(3)];
% Vertices
scatter(P(:, 1), P(:, 2), 100, 'ro');
hold on;
% Edges
for idx = 1:size(P, 1)-1
plot([P(idx, 1) P(idx+1, 1)], [P(idx, 2) P(idx+1, 2)], 'r');
end
plot([P(end, 1) P(1, 1)], [P(end, 2) P(1, 2)], 'r');
% Sample points within the triangle
N = 1000; % Number of points
t = sqrt(rand(N, 1));
s = rand(N, 1);
sample_pts = (1-t)*P(1, :)+bsxfun(#times, ((1-s)*P(2, :)+s*P(3, :)), t);
% Colors for demo
C = ones(size(sample_pts, 1), 1).*sample_pts(:, 1);
% Scatter sample points
scatter(sample_pts(:, 1), sample_pts(:, 2), [], C, 'filled');
colorbar;
produces
PS
As suggested by Nitish, increasing number of points will do the trick. But is there a more computationally cheap way of doing so?
Triangulate your 2D data points using delaunayTriangulation, evaluate your function with the points of the triangulation and then plot the resulting surface using trisurf:
After %Colors for demo, add this:
P = [P; sample_pts]; %// Add the edgepoints to the sample points, so we get a triangle.
f = #(X,Y) X; %// Defines the function to evaluate
%// Compute the triangulation
dt = delaunayTriangulation(P(:,1),P(:,2));
%// Plot a trisurf
P = dt.Points;
trisurf(dt.ConnectivityList, ...
P(:,1), P(:,2), f(P(:,1),P(:,2)), ...
'EdgeColor', 'none', ...
'FaceColor', 'interp', ...
'FaceLighting', 'phong');
%// A finer colormap gives more beautiful results:
colormap(jet(2^14)); %// Or use 'parula' instead of 'jet'
view(2);
The trick to make this graphic beautiful is to use 'FaceLighting','phong' instead of 'gouraud' and use a denser colormap than is usually used.
The following uses only N = 100 sample points, but a fine colormap (using the now default parula colormap):
In comparison the default output for:
trisurf(dt.ConnectivityList, ...
P(:,1), P(:,2), f(P(:,1),P(:,2)), ...
'EdgeColor', 'none', ...
'FaceColor', 'interp');
looks really ugly: (I'd say mainly because of the odd interpolation, but the jet colormap also has its downsides)
Why not just increase N to make the grid "more smooth"? It will obviously be more computationally expensive but is probably better than extrapolation. Since this is a simulation where s and t are your inputs, you can alternately create a fine grids for them (depending on how they interact).
P = [0 1/sqrt(3); 0.5 -0.5/sqrt(3); -0.5 -0.5/sqrt(3)];
% Vertices
scatter(P(:, 1), P(:, 2), 100, 'ro');
hold on;
% Edges
for idx = 1:size(P, 1)-1
plot([P(idx, 1) P(idx+1, 1)], [P(idx, 2) P(idx+1, 2)], 'r');
end
plot([P(end, 1) P(1, 1)], [P(end, 2) P(1, 2)], 'r');
% Sample points within the triangle
N = 100000; % Number of points
t = sqrt(rand(N, 1));
s = rand(N, 1);
sample_pts = (1-t)*P(1, :)+bsxfun(#times, ((1-s)*P(2, :)+s*P(3, :)), t);
% Colors for demo
C = ones(size(sample_pts, 1), 1).*sample_pts(:, 1);
% Scatter sample points
scatter(sample_pts(:, 1), sample_pts(:, 2), [], C, 'filled');
colorbar;
There is example of the web that shows how to do animated plot in a single figure.
However, I want to do two subplots in a single figure, such that they will show animation in a first subplot, and then the animation ina second subplot.
Using 'figure(1)' or 'figure (2)' and 'hold on', I can do the animation plot as follows. However, How do I call the subplot to do the similiar things?
So the effect I am looking for is: 1) figure that is opened and has two subplot. 2) plot the animated curve in the 1st subplot, then plot the animated curve in the 2nd subplot. 3) I want to go back to the 1st subplot to plot more things, and also go to 2nd subplot to plot more things.
figure(1); hold on; x = 1:1000;
y = x.^2;
%// Plot starts here
figure,hold on
%// Set x and y limits of the plot
xlim([min(x(:)) max(x(:))])
ylim([min(y(:)) max(y(:))])
%// Plot point by point
for k = 1:numel(x)
plot(x(k),y(k),'-') %// Choose your own marker here
%// MATLAB pauses for 0.001 sec before moving on to execue the next
%%// instruction and thus creating animation effect
pause(0.001);
end
Just do the subplot's in the loop:
for k = 1:numel(x)
subplot(1,2,1)
plot(x(k),y(k),'-') %// Choose your own marker here
subplot(1,2,2)
plot(x(1:k),y(1:k))
%// MATLAB pauses for 0.001 sec before moving on to execue the next
%%// instruction and thus creating animation effect
pause(0.001);
end
% Easiest way
x = rand(1, 11); y = rand(1, 11);
z = rand(1, 11); a = rand(1, 11);
figure
for i = 1 : 10
subplot(211)
plot(x(i : i+1), y(i : i+1), '.-k');
hold on; % include this if you want to show plot history
subplot(212)
plot(z(i : i+1), a(i : i+1), '.-k');
drawnow;
pause(0.1);
end
% If you don't want to call "plot" interatively
x = rand(1, 11); y = rand(1, 11);
z = rand(1, 11); a = rand(1, 11);
figure
subplot(211)
p1 = plot(NaN, NaN, 'marker', 'o');
subplot(212)
p2 = plot(NaN, NaN, 'marker', 'd');
for i = 1 : 10
set(p1, 'xdata', x(i : i+1), 'ydata', y(i : i+1));
set(p2, 'xdata', z(i : i+1), 'ydata', a(i : i+1));
drawnow;
pause(0.1);
end
First define your plot as a construct, so p1 = plot(x,y). Then you set up your loop and in the loop your write
set(p1,'YData',y);
This will update the plot p1s YData which is y. If you want to see it in an animated form just add a pause(0.1) %seconds after the set.
I am trying to program scatterplot with specific errorbars. The only build in function i found is
errorbar()
but this only enables me to make a 2d plot with errorbars in y direction. What i am asking for is a method to plot this with errorbars in x and y direction.
At the end my goal is to make a 3D-scatter-plot with 3 errorbars.
Perfect would be if the resulting image would be a 3d-plot with 3d geometric shapes (coordinate x,y,z with expansion in the dimension proportional to the errorbars) as 'marker'.
I found this page while searching the internet: http://code.izzid.com/2007/08/19/How-to-make-a-3D-plot-with-errorbars-in-matlab.html
But unfortunately they use only one errorbar.
My data is set of 6 arrays each containing either the x,y or z coordinate or the specific standard derivation i want to show as errorbar.
The code you posted looks very easy to adapt to draw all three error bars. Try this (note that I adapted it also so that you can change the shape and colour etc of the plots as you normally would by using varargin, e.g. you can call plot3d_errorbars(...., '.r'):
function [h]=plot3d_errorbars(x, y, z, ex, ey, ez, varargin)
% create the standard 3d scatterplot
hold off;
h=plot3(x, y, z, varargin{:});
% looks better with large points
set(h, 'MarkerSize', 25);
hold on
% now draw the vertical errorbar for each point
for i=1:length(x)
xV = [x(i); x(i)];
yV = [y(i); y(i)];
zV = [z(i); z(i)];
xMin = x(i) + ex(i);
xMax = x(i) - ex(i);
yMin = y(i) + ey(i);
yMax = y(i) - ey(i);
zMin = z(i) + ez(i);
zMax = z(i) - ez(i);
xB = [xMin, xMax];
yB = [yMin, yMax];
zB = [zMin, zMax];
% draw error bars
h=plot3(xV, yV, zB, '-k');
set(h, 'LineWidth', 2);
h=plot3(xB, yV, zV, '-k');
set(h, 'LineWidth', 2);
h=plot3(xV, yB, zV, '-k');
set(h, 'LineWidth', 2);
end
Example of use:
x = [1, 2];
y = [1, 2];
z = [1, 2];
ex = [0.1, 0.1];
ey = [0.1, 0.5];
ez = [0.1, 0.3];
plot3d_errorbars(x, y, z, ex, ey, ez, 'or')