Using Surf and Peaks for non square Matrices - matlab

Im trying to use meshgrid with peak. When I use square matrices like:
[x,y] = meshgrid(1:10,1:10)
z = peaks(10)
surf(x,y,z)
Everything works fine.
However, when I use Non square matrices:
[x,y] = meshgrid(-30000:500:0,10:500);
z = peaks(?)
surf(x,y,z)
Im getting the following error:
Data dimensions must agree.
Any idea how to make it work?
Thank you.

When you plot a function using surf the variables you pass it must all be the same size. Although you are changing the x and y matrices to non-square matrices, you are not creating a correspondingly sized z matrix. If you look at the documentation for peaks, this tells you that this function can only produce square outputs, which complicates things somewhat. I would suggest that you try to plot some other example function instead.
If you absolutely must plot the peaks function, you could use some kind of interpolation:
x = 1:10;
y = 1:10;
[x_mesh, y_mesh] = meshgrid(x,y);
z = peaks(10);
x2 = 1:0.1:10;
y2 = 1:0.5:10;
[x2_mesh, y2_mesh] = meshgrid(x2, y2);
z2 = interp2(x_mesh, y_mesh, z, x2_mesh, y2_mesh);
surf(x2_mesh, y2_mesh, z2);
This gives me the following plot:

Related

Plotting a coloured 3D figure in MATLAB

I have 3 axes: X of size N, Y of size M and Z of size O, which correspond to the coordinates of my data.
I have a matrix: DATA of size MxNxO, which corresponds to the module for each points.
I would like to plot the MATLAB figure of coordinate X, Y, Z and color the point depending of the value of the matrix DATA of size MxNxO.
I tried lots of functions such as scatter3, surf, plot3, but none is working as I wanted.
This is what I tried:
n = 10;
x = linspace(0,10,n);
y = linspace(0,10,n);
z = linspace(0,10,n);
DATA = randn(n,n,n);
scatter3(x,y,z,DATA);
This code didn't work because DATA is not the same size as x, y, z. I also tried with:
[X,Y,Z] = ndgrid(x,y,z)
scatter3(X,Y,Z,DATA);
but this didn't work either.
The trick with scatter3() is to "unroll" your matrices to a column vector, and don't forget that the fourth argument is size, rather than colour:
n = 10;
x = linspace(0,10,n);
y = linspace(0,10,n);
z = linspace(0,10,n);
[X,Y,Z] = ndgrid(x,y,z);
DATA = randn(n,n,n);
% here 3 is the size. You can set it to a different constant, or vary it as well
scatter3(X(:), Y(:), Z(:), 3, DATA(:));
Results in
You can colour a surface, see its documentation, however, it doesn't seem to make much sense in your case, given you have a full cube of data points. A surface is 2D, whereas your data is 3D. For a 2D surface, simply follow the example in the docs:
n = 10;
x = linspace(0,10,n);
y = linspace(0,10,n);
Z = rand(n);
DATA = randn(n);
surf(x, y, Z, DATA);
Images rendered in R2007b, syntax cross-checked with the documentation.
If you've got a surface defined by an M -by- 4 array containing X, Y, Z and Data, you can use delaunay() to create a Delaunay triangulation of your points and then trisurf() to plot that. Note that this still requires a 2D surface, albeit it can vary in three dimensions. The cube of data in your example still doesn't make sense to plot as a surface, even with this method.

Gaussian Contour plot of 3 variables - MATLAB

I have generated a 3D plot that resembles Gaussian distribution, with random variables Y, X1, and X2 (1000x1) vectors. Y is on the vertical axis, X1, and X2 are horizontal.
Specifically, this is the code I used for the plot:
plot3(x(:,1),x(:,2),y,'.')
The graph that has been created has this form:
What I also want to produce is something like that:
But, when I use this code:
contour(x(:,1),x(:,2),y);
I receive a message that:
Error using contour (line 48)
Z must be at least a 2x2 matrix.
I really don't get how to fix that problem, I assume Z is the Y but I don't understand why it has to be 2x2 at least. Anyhow, any help would be much appreciated.
You cannot create a contour over scattered data, you need a grid. It is possible to interpolate the data on a grid of NxN samples in the XY domain, using griddata (here the domain is [-2,2]x[-2,2] as an example):
N = 200;
xi = linspace(-2, 2, N);
yi = linspace(-2, 2, N);
[XI, YI] = meshgrid(xi, yi);
ZI = griddata(x(:,1), x(:,2), y, XI, YI, 'v4');
contour(XI,YI,ZI);
More info on how to interpolate scattered data here.

How to plot using surf gird in 2D using function value

if the function F is available it is easy to draw surf plot i.e.
x=1:0.1:4;
y=1:0.1:4;
[X,Y]=meshgrid(x,y);
Z=sin(X).^2+cos(Y).^2;
surf(X,Y,Z);
view(2) ;
in my case I calculated F function using least square:
for example I have x and y vectors
x = [0 9.8312 77.1256 117.9810 99.9979];
y = [0 2754.5 4043.3 5376.3 5050.4];
the linear function of these two vector is define by
F= [1149.73 , 37.63];
therefore the estimation is equal to
z= [ones(5,1) x']*F';
which is
z = [1149.73 1519.67 4051.96 5589.35 4912.65];
and if it is plotted
plot(x,y,'b.');
hold on;plot(x,y,'b-');
hold on; plot(x,z,'-r');
The linear z ( red line) is showing correctly. Now I want to plot it for all possible combination of x and y using grid and I need to have a mesh for all inputs
[X,Y] = meshgrid(x,y);
but how to make the Z matrix to show the intensity plot of function Z? The Z suppose to have high intensity close to z value and less value far from it. I should suppose to get something like this
Thanks
P.S: the F is calculated using pinv (least square).
You have to interpolate the scattered data to plot it on grid. Here is a simple example for your x, y and z vectors
xi=linspace(min(x),max(x),100)
yi=linspace(min(y),max(y),100)
[XI YI]=meshgrid(xi,yi);
ZI = griddata(x,y,z,XI,YI);
contourf(XI,YI,ZI)

3d-plotting surface 2x^2 + 3y^2 + z^2 = 6

I was trying to plot the above surface in octave/matlab and ran into the this problem.
My code is as follows:
x = linspace(-sqrt(3),sqrt(3),1000);
y = linspace(-sqrt(2),sqrt(2),1000);
z = sqrt(6-2*x.^2-3*y.^2);
surf(x,y,z)
I got the error:
error: mesh: X, Y, Z arguments must be real.
I understand this was because some (x,y)s would result in negative 6-2*x.^2-3*y.*2, but I don't know how to tackle this because I can't trim either part of x or y. Any one can help? Thanks
It depends what you want to do with the non-real values of z.
One thing you could do is to set all these values to zero or NaN (as per #hbaderts' comment):
z = sqrt(6-2*x.^2-3*y.^2);
z( imag(z)~=0 ) = NaN;
One more thing though: your code might have a problem because z is a length-1000 vector, and you want it to be a 1000x1000 matrix. You should use meshgrid() on x and y to get two-dimensional matrices everywhere:
x = linspace(-sqrt(3),sqrt(3),1000);
y = linspace(-sqrt(2),sqrt(2),1000);
[xx,yy] = meshgrid(x,y);
z = sqrt(6-2*xx.^2-3*yy.^2);
z( imag(z)~=0 ) = NaN;
surf(xx,yy,z,'edgecolor','none')
(thanks #LuisMendo for the 'edgecolor','none' suggestion for better visualization.)
Running the above piece of code on octave gives this plot:

data type to store precision more than double in matlab

I an working in matlab, recently I am doing research in image processing. this time I am implementing a research paper this paper, in which I am getting problem to store precision more than double. kindly check the equation 6 of that paper.
I am facing problem in following code..
img = imread('Einstein.bmp');
exponent = double(zeros(size(img,1),size(img,2)));
s = double(zeros(size(img,1),size(img,2)));
sigma=1;
for i=1:size(img,1)
for j=1:size(img,2)
exponent(i,j) = double(((i^2)+(j^2))/(2*(sigma^2)));
s(i,j) = double(exp(-exponent(i,j)));
end
end
After some values, s(i,j) gives 0 for all values but that values should not be 0. how can I avoid that problem?
Looking at your code, it seems you are trying to create a 2D Gaussian function centered at (0,0). The kernel width you are using is really small: sigma=1, seeing you are computing the function over the entire grid of an image pixels. So no wonder you are getting all zeros except for a tiny portion in the top-left corner of the matrix S.
Here is a more efficient way to create the kernel centered around the middle:
% 100x100 grid
r = 100; c = 100;
[x,y] = ndgrid(1:r,1:c);
% sigma = 20
sigma = max([r c])/5;
% 2D gaussian function
z = sum(bsxfun(#minus, [x(:) y(:)], [r c]./2).^2, 2);
z = exp(-z ./ (2*sigma^2)) ./ (sigma^2 * 2*pi);
z = reshape(z, [r c]);
If you have access to the Statistics toolbox, use mvnpdf to it write as:
z = mvnpdf([x(:) y(:)], [r c]./2, eye(2)*sigma^2);
z = reshape(z, [r c]);
or if you have the Image processing toolbox, simply use fspecial:
z = fspecial('gaussian', [r c], sigma);
The result:
imshow(z, 'DisplayRange',[], 'InitialMag','fit')
axis on, colorbar
Note that the matrix is normalized so that the integral is one (hence the small values). That's why I turned off the default [0,1] range when displaying as an image.
You could also simply map it into [0,1] range using: z = (z - min(z(:))) ./ range(z(:))
Here is the resulting matrix when viewed as a surface:
surf(x,y,z)
axis vis3d
It appears that matlab only uses 64-bit doubles, but you might have luck with one of the arbitrary precision libraries available for matlab.