MATLAB - Surf Plot data structure - matlab

I have done calculations with 2 different methods. For those calculations I have varied 2 parameters: x and y
In the end, I have calculated the % ERROR between both methods, for each variation.
Now I want to create a 3D surface plot from the results:
x -> on x axis
y -> on y axis
Error -> on z axis
Here is a sample of the data:
A = [
-0.1111 1.267 9.45680081826912
-0.1111 2.6 212.361735695025
-0.25 1.533 40.5729362609655
-0.25 2.867 601.253624894196
-0.4286 1 0.12116749607863
-0.4286 3.4 79.6948438921078
-0.6667 2.067 33.3495544017519
-0.6667 3.667 141.774875517481
-1 2.6 -0.0399171449531781
0.09091 1.533 163.7083541414 ];
But, when I try to plot it with surf function:
x = A(:,1);
y = A(:,2);
z = A(:,3);
surf(x,y,z)
, I get an error:
Error using surf (line 75)
Z must be a matrix, not a scalar or vector
Error in ddd (line 27)
surf(x,y,z)
Can you help me with a code that can restructure the data in the format acceptable for the surf function?
P.S. - I am currently trying to write some sample code with my first attempts. I will post it as soon as I get to somewhere.

The surf function needs a grid of X,Y-values as input. Your data however is simply three vectors with some combinations, not a full grid. As described in the documentation, the meshgrid function is often helpful to create such grid matrices. Use the unique function to select all unique values in x and y and create matrices of all possible combinations:
[X,Y] = meshgrid(unique(x),unique(y));
To create a Z matrix which fits the [X,Y] grid, the griddata function is helpful:
Z = griddata(x,y,z,X,Y);
Now you can call surf with the grid matrices as input:
surf(X,Y,Z);

create the grid for the first and second column and calculate Z using your formula.
help meshgrid in MATLAB

Related

Plotting a Matrix in 3D space in MATLAB without using mesh and surf type of plots

I am not familiar with MATLAB environment and I want to draw a matrix in a way that presents each cell of a matrix as a point in the 3D space.
For example present matrix "A " with the following points in 3D space:
x=1, y=1 Z= 10 , x=1, y=3 Z=27 until reach the point x=3, y=3, z=26.
A =
10 15 27
56 87 2
90 87 26
I do not want to use mesh and surf. I am looking for diagram like plot3 digram.I tried plot3 but it does not show the value of z correctly.
i=1:3;
j=1:3;
plot3(i,j,A(i,j))
In the above figure; 3 values are presented for when x=3 and y=3 however it should present these values for x=1,y=3; x=2,y=3;x=3,y=3
To begin I would recommend you to change your variable names. I'll use x and y instead of i and j. In many language these symbols are more typically used for scalar index rather than full vector indices, and in Matlab they can have a special significance (they are used to represent complex numbers).
That said, in your statement i=1:3; you only generate 3 indices, but you have 9 values to plot in your matrix. These 3 indices have to be repeated (3 times in your case, one for each column). So a proper x and y generation would be:
%% // Manual mesh/coordinate generation
x = bsxfun(#times,1:size(A,1), ones([size(A,2) 1])) ;
x = x(:) ;
y = bsxfun(#times, ones([1 size(A,1)]) , (1:size(A,2)).' ) ;
y = y(:) ;
With that you can use at your convenience scatter3 or plot3:
hscat = scatter3( x, y, A(:) ) ;
hp3 = plot3( x, y, A(:),'Marker','o','LineStyle','none') ;
%// will both produce exactly the same result
Now please consider the fact that the way I generated the x and y coordinate is nothing more than what meshgrid would do for you (or the more dimension generic ndgrid).
For example, in the code below, the 3 plotting methods will produce exactly the same ouput than above, so just take your pick:
%% define a grid
[X,Y] = meshgrid( 1:size(A,1) , 1:size(A,2) ) ;
%% // surface plot (but only points visible, no line)
hsurf = surf(X,Y,A,'Marker','o','LineStyle','none','FaceColor','none') ;
%% // scatter3
hscat = scatter3( X(:), Y(:), A(:) ) ;
%% // plot3
hp3 = plot3( X(:), Y(:), A(:),'Marker','o','LineStyle','none') ;
Why reinvent the wheel when you have one at hand ... meshgrid do the job for you in less code instruction ;-)
To generate the coordinates, you should use ndgrid (or meshgrid, which swaps X and Y.):
[X, Y] = ndgrid(1:3, 1:3);
plot3 is going to connect the input points with a line, so if you want distinct points in your plot, use scatter3:
scatter3(X(:), Y(:), A(:));
(You can also use plot3 in the same way if you want the lines.)

Draw a line with non-Cartesian coordinates in MATLAB

MATLAB's surf command allows you to pass it optional X and Y data that specify non-cartesian x-y components. (they essentially change the basis vectors). I desire to pass similar arguments to a function that will draw a line.
How do I plot a line using a non-cartesian coordinate system?
My apologies if my terminology is a little off. This still might technically be a cartesian space but it wouldn't be square in the sense that one unit in the x-direction is orthogonal to one unit in the y-direction. If you can correct my terminology, I would really appreciate it!
EDIT:
Below better demonstrates what I mean:
The commands:
datA=1:10;
datB=1:10;
X=cosd(8*datA)'*datB;
Y=datA'*log10(datB*3);
Z=ones(size(datA'))*cosd(datB);
XX=X./(1+Z);
YY=Y./(1+Z);
surf(XX,YY,eye(10)); view([0 0 1])
produces the following graph:
Here, the X and Y dimensions are not orthogonal nor equi-spaced. One unit in x could correspond to 5 cm in the x direction but the next one unit in x could correspond to 2 cm in the x direction + 1 cm in the y direction. I desire to replicate this functionality but drawing a line instead of a surf For instance, I'm looking for a function where:
straightLine=[(1:10)' (1:10)'];
my_line(XX,YY,straightLine(:,1),straightLine(:,2))
would produce a line that traced the red squares on the surf graph.
I'm still not certain of what your input data are about, and what you want to plot. However, from how you want to plot it, I can help.
When you call
surf(XX,YY,eye(10)); view([0 0 1]);
and want to get only the "red parts", i.e. the maxima of the function, you are essentially selecting a subset of the XX, YY matrices using the diagonal matrix as indicator. So you could select those points manually, and use plot to plot them as a line:
Xplot = diag(XX);
Yplot = diag(YY);
plot(Xplot,Yplot,'r.-');
The call to diag(XX) will take the diagonal elements of the matrix XX, which is exactly where you'll get the red patches when you use surf with the z data according to eye().
Result:
Also, if you're just trying to do what your example states, then there's no need to use matrices just to take out the diagonal eventually. Here's the same result, using elementwise operations on your input vectors:
datA = 1:10;
datB = 1:10;
X2 = cosd(8*datA).*datB;
Y2 = datA.*log10(datB*3);
Z2 = cosd(datB);
XX2 = X2./(1+Z2);
YY2 = Y2./(1+Z2);
plot(Xplot,Yplot,'rs-',XX2,YY2,'bo--','linewidth',2,'markersize',10);
legend('original','vector')
Result:
Matlab has many built-in function to assist you.
In 2D the easiest way to do this is polar that allows you to make a graph using theta and rho vectors:
theta = linspace(0,2*pi,100);
r = sin(2*theta);
figure(1)
polar(theta, r), grid on
So, you would get this.
There also is pol2cart function that would convert your data into x and y format:
[x,y] = pol2cart(theta,r);
figure(2)
plot(x, y), grid on
This would look slightly different
Then, if we extend this to 3D, you are only left with plot3. So, If you have data like:
theta = linspace(0,10*pi,500);
r = ones(size(theta));
z = linspace(-10,10,500);
you need to use pol2cart with 3 arguments to produce this:
[x,y,z] = pol2cart(theta,r,z);
figure(3)
plot3(x,y,z),grid on
Finally, if you have spherical data, you have sph2cart:
theta = linspace(0,2*pi,100);
phi = linspace(-pi/2,pi/2,100);
rho = sin(2*theta - phi);
[x,y,z] = sph2cart(theta, phi, rho);
figure(4)
plot3(x,y,z),grid on
view([-150 70])
That would look this way

drawing 3d contour plot from 3d vector

I want to draw a contour plot for 3D data.
I have a force in x,y,z directions I want to plot the contour3 for that
the dimensions of the Fx = 21x21X21 same for Fy and Fz
I am finding force = f*vector(x,y,z)
Then
Fx(x,y,z) = force(1)
Fy(x,y,z) = force(2)
Fz(x,y,z) = force(3)
I did the following but it is not working with me ?? why and how can I plot that
FS = sqrt(Fx.^2 + Fy.^2 + Fz.^2);
x = -10:1:10;
[X,Y] = meshgrid(x);
for i=1:length(FS)
for j = 1:length(FS)
for k=1:length(FS)
contour3(X,Y,FS(i,j,k),10)
hold on
end
end
end
This is the error I am getting
Error using contour3 (line 129)
When Z is a vector, X and Y must also be vectors.
Your problem is that FS is not the same shape as X and Y.
Lets illustrate with a simple example:
X=[1 1 1
2 2 2
3 3 3];
Y=[1 2 3
1 2 3
1 2 3];
Z=[ 2 4 5 1 2 5 5 1 2];
Your data is probably something like this. How does Matlab knows which Z entry corresponds to which X,Y position? He doesnt, and thats why he tells you When Z is a vector, X and Y must also be vectors.
You could solve this by doing reshape(FS,size(X,1),size(X,2)) and will probably work in your case, but you need to be careful. In your example, X and Y don't seem programatically related to FS in any way. To have a meaningful contour plot, you need to make sure that FS(ii,jj,k)[ 1 ] corresponds to X(ii,jj), else your contour plot would not make sense.
Generally you'd want to plot the result of FS against the variables your are using to compute it, such as ii, jj or k, however, I dont know how these look like so I will stop my explanation here.
[ 1 ]: DO NOT CALL VARIABLES i and j IN MATLAB!
I'm not sure if this solution is what you want.
Your problem is that contour and contour3 are plots to represent scalar field in 2D objects. Note that ball is 2D object - every single point is defined by angles theta and phi - even it is an object in "space" not in "plane".
For representation of vector fields there is quiver, quiver3, streamslice and streamline functions.
If you want to use contour plot, you have to transform your data from vector field to scalar field. So your data in form F = f(x,y,z) must be transformed to form of H = f(x,y). In that case H is MxN matrix, x and y are Mx1 and Nx1 vectors, respectively. Then contour3(x,y,H) will work resulting in so-called 3D graph.
If you rely on vector field You have to specify 6 vectors/matrices of the same size of corresponding x, y, z coordinates and Fx, Fy, Fz vector values.
In that case quiver3(x,y,z,Fx,Fy,Fz) will work resulting in 6D graph. Use it wisely!
As I comment the Ander's answer, you can use colourspace to get more dimensions, so You can create 5D or, theoretically, 6D, because you have x, y, z coordinates for position and R, G, B coordinates for the values. I'd recommend using static (x,y,R,G,B) for 5D graph and animated (x,y,t,R,G,B) for 6D. Use it wisely!
In the example I show all approaches mentioned above. i chose gravity field and calculate the plane 0.25 units below the centre of gravity.
Assume a force field defined in polar coordinates as F=-r/r^3; F=1/r^2.
Here both x and yare in range of -1;1 and same size N.
F is the MxMx3 matrix where F(ii,jj) is force vector corresponding to x(ii) and y(jj).
Matrix H(ii,jj) is the norm of F(ii,jj) and X, Y and Z are matrices of coordinates.
Last command ensures that F values are in (-1;1) range. The F./2+0.5 moves values of F so they fit into RGB range. The colour meaning will be:
black for (-1,-1,-1),
red for (1,-1,-1),
grey for (0,0,0)
Un-comment the type of plot You want to see. For quiver use resolution of 0.1, for other cases use 0.01.
clear all,close all
% Definition of coordinates
resolution=0.1;
x=-1:resolution:1;
y=x;
z=-.25;
%definition of matrices
F=zeros([max(size(x))*[1 1],3]); % matrix of the force
X=zeros(max(size(x))*[1 1]); % X coordinates for quiver3
Y=X; % Y coordinates for quiver3
Z=X+z; % Z coordinates for quiver3
% Force F in polar coordinates
% F=-1/r^2
% spherical -> cartesian transformation
for ii=1:max(size(x))
for jj=1:max(size(y))
% temporary variables for transformations
xyz=sqrt(x(ii)^2+y(jj)^2+z^2);
xy= sqrt(x(ii)^2+y(jj)^2);
sinarc=sin(acos(z/xyz));
%filling the quiver3 matrices
X(ii,jj)=x(ii);
Y(ii,jj)=y(jj);
F(ii,jj,3)=-z/xyz^2;
if xy~=0 % 0/0 error for x=y=0
F(ii,jj,2)=-y(jj)/xyz/xy*sinarc;
F(ii,jj,1)=-x(ii)/xyz/xy*sinarc;
end
H(ii,jj)=sqrt(F(ii,jj,1)^2+F(ii,jj,2)^2+F(ii,jj,3)^2);
end
end
F=F./max(max(max(F)));
% quiver3(X,Y,Z,F(:,:,1),F(:,:,2),F(:,:,3));
% image(x,y,F./2+0.5),set(gca,'ydir','normal');
% surf(x,y,Z,F./2+.5,'linestyle','none')
% surf(x,y,H,'linestyle','none')
surfc(x,y,H,'linestyle','none')
% contour3(x,y,H,15)

Computing and plotting pdf of U as a function of two uniformly distributed random variables

I am working on a joint pdf problem in which the random variable
U = sqrt(X^2+Y^2)
X and Y are uniformly distributed over (-2,2). I want to plot joint pdf of X and Y. Then compute pdf of U and plot it as well. I am using matlab R2011a, and so far, I have come up with the following code. On running the code I got an error message
Undefined function or method 'makedist' for input arguement type 'char'.
I found out that makedist is not on 2011 version. So I tried using
a=-2;
b=2;
X=a+(b-a)*rand(-10,10);
Y= a+(b-a)*rand(-10,10).
However, I am not sure how to compute pdfs of X and Y, and then joint pdf of XY from this. Any help, partial or holistic, is appreciated.
Here is the matlab code for the problem
%% Create distribution objects for X~U(-2,2) and Y~U(-2,2)
pdx=makedist('Uniform','lower',-2,'upper',2);
pdy=makedist('Uniform','lower',-2,'upper',2);
%Compute the pfs
x_ref=-10:1:10;
y_ref=-10:1:10;
pdf_x=pdf(pdx,x_ref);
pdf_y=pdf(pdy,y_ref);
% Plot the pdfs
figure 1;
stairs(x_ref,pdf_x,'g','Linewidth',2);
hold on;
stairs(y_ref,pdf_y,'r','Linewidth',2);
ylim([0 1.5]);
hold off;
% Joint pdf of x and Y
pdfXY=pdf_x*pdf_y;
figure 2;
plot(pdfXY);
%CDF and PDF of U
U=sqrt(X^2+Y^2);
Umin=0;
Umax=sqrt(b^2+b^2);
a=lower;
b=upper;
x=sqrt(U^2-Y^2);
xmin=0;
xmax=x;
ymin=0;
ymax=U;
Ucdf=integral2(pdfXY,xmin,xmax,ymin,ymax);
% plot CDF of U
figure 3;
plot(Ucdf)
I am just looking to plot the regions than for any specific sample set. X and Y are continuous independent uniform random variables.
As your x and y are independent at random, the theoretical joint distribution is just a product of the two
P(x,y) = P(x)*P(y)
In terms of MATLAB code, you may think of x and y running along two different dimensions:
N = 10; %// think of a probability mass function over N points
x = linspace(-2,2, N);
y = linspace(-2,2, N)';
Px = ones(N,1)./N;
Py = ones(1,10)./N;
%// Then the joint will be:
Jxy = bsxfun(#times, Px , Py);
figure
pcolor(x,y,Jxy)
You can now plug whatever distribution you like, if they are independent for Px and Py, and it will work

How to constrain a variable in Matlab

Matlab newb here. I have searched and haven't found how to do the following:
x=0.1:1/100:10;
y=exp(a(a>=-1&a<=1)*sqrt(x));
plot(x,y)
I realize that the dimensions of x and a don't match, but I just want to express: "what does y look like when a constant, a, is constrained between -1 and 1", for example.
Any hints are appreciated. Thanks in advance.
Assuming a and x are independent, you can go along these lines, using bsxfun to compute y for all combinations of a and x:
x = 0.1:1/100:10; %// define x values
a = linspace(-1,1,10); %// define a values
y = exp( bsxfun(#times, a, sqrt(x).') ); %'// compute y for all combinations
plot(x,y); %// this plots each column of y. Each colum represents a value of a
Or plot as a 3D graph (y as a function of a and x):
mesh(a,x,y)
xlabel('a')
ylabel('x')
zlabel('y')
You can do as follows:
x=0.1:1/100:10; % 991 clips
a=-1:1/495:1; % use 1/495 here to make it also 991 clips
y=exp(a.*sqrt(x));
plot(x,y)
This will give you the following figure: