Limits of the Waterfall function ... or not? - matlab

I have a problem to figure out how in a waterfall figure the x axis can correspond to the x values, and not their point number. This question seems rather simple but in my particular case (due to the size of vectors) it's not easy to get the correct figure. So i really need your help ... after several hours of unsatisfied results.
Assuming that two vectors x and y of the same length are recorded at a time t. This procedure is performed k times. I finally want to plot with waterfall y versus x for the different times.
I give you a script that corresponds to the experiment where xx is just added to get here two continuous functions x and y for the different times. The result is almost perfect but I would like the x-y values on the corresponding x, y axis instead of the point number.
xx=0:0.1:8;
for t=1:2:11
x(t,:)=sin(t*xx.^2);
y(t,:)=cos(t*xx.*4);
end
waterfall(x,y)
The problem comes probably from the different size of x, y with t. Thanks in advance for your advice.

Two comments:
waterfall takes either Z or X,Y,Z as coordinates. So it takes your x matrix as Z, and the other argument is mapped to the C input, which dictates color. You can see that the plot is the same if you do waterfall(x), except with different colors.
Your x is not monotonically increasing, so if you plot x(t,:) vs y(t,:) for any t, you'll get a web-like graph, not anything nice to look at.
So I'll plot xx vs y, and I'm modifying your y a bit so it looks nicer. I hope you can take this idea and modify it to do what you need.
The code below doesn't use waterfall at all, it simply calls plot3 once for each t. It might be possible to call plot3 with your full x and y matrices, but this is just as easy.
In the plot3 call, the x-coordinates are given by xx, the y-coordinates by t (simply repeated to match the expected size), and the z-coordinates by y:
xx = 0:0.1:8;
for t = 1:2:11
y = cos(t*xx/4);
plot3(xx,repmat(t,size(xx)),y)
hold on
end
xlabel('x')
ylabel('t')
zlabel('y=cos(tx/4)')

Related

3d plot with ksdensity in matlab

I have a problem in matlab.
I used a ksdensity function on a vector of deltaX, which was my computed X minus actual X.
And I did the same on deltaY.
Then I used plot on that data. This gave me two 2d plots.
As I have two plots showing how (in)accurate was my system in computing X and Y (something like gaussian bell it was). Now I would like to have one plot but in 3d.
The code was just like that:
[f,xi] = ksdensity(deltaX);
figure;
plot(xi,f)
Ok what I'm about to show is probably not the correct way to visualize your problem, mostly because I'm not quite sure I understand what you're up to. But this will show you an example of how to make the Z matrix as discussed in the comments to your question.
Here's the code:
x = wgn(1000,1,5);%create x and y variables, just noise
y = wgn(1000,1,10);
[f,xi] = ksdensity(x);%compute the ksdensity (no idea if this makes real-world sense)
[f2,xi2] = ksdensity(y);
%create the Z matrix by adding together the densities at each x,y pair
%I doubt this makes real-world sense
for z=1:length(xi)
for zz = 1:length(xi2)
Z(z,zz) = f(z)+f2(zz);
end
end
figure(1)
mesh(xi,xi2,Z)
Here's the result:
I leave it up to you to determine the correct way to visualize your density functions in 3D, this is just how you could make the Z matrix. In short, the Z matrix contains the plot elevation at each x,y coordinate. Hope this helps a little.

Assume that x, y, and z are Matlab arrays, plot the function e^(-x)sin(x) across the interval [0. 4pi]

x=linspace(0, 2*pi, 100);
y=sin(x);
z=exp(-x);
Given that x, y, and z are already initialized, how do I write a function that plots exp(-x)sin(x) across the interval [0, 4pi] without additional calls to sin or exp? Just need some help getting started.
Thanks to #Rayryeng for getting me started. I believe the following command more closely satisfies the question's specifications.
plot(x+x, z.*z.*y)
Well, you've already created arrays for sin and exp stored in y and z respectively. These arrays were created on the same domain as x. You just need to multiply both arrays together element-wise and plot the graph. It's as simple as doing:
plot(x, z.*y);
Here, .* stands for element-wise multiplication. If you were to do z*y, MATLAB interprets this as matrix multiplication where z and y are interpreted to be matrices. This is obviously not what you want.
However, your array of x only contains points from 0 to 2*pi. If you want to plot this from 0 to 4*pi, you have to modify your call to linspace:
x=linspace(0, 4*pi, 100); %// Change
y=sin(x);
z=exp(-x);
plot(x, z.*y);
Now, x will contain 100 points between 0 to 4*pi. For more information on basic MATLAB operations, check out this link: http://www.mathworks.com/help/matlab/matlab_prog/array-vs-matrix-operations.html. What you have asked falls into the basic realms of array and matrix operations.
Edit
In the spirit of your question, we can't modify linspace. You did something clever where we can simply scale our values of x by 2 or adding with x so that we have points going from 0 to 2*pi to 0 to 4*pi. Also, if we scale our points by 2, this means that our input argument into the function must also be scaled by 2. So, the final function we need to plot is:
y = exp(-2x)*sin(2x)
Noting your hint, exp(-2x) = exp(-x-x) = exp(-x)exp(-x). Further, note that sin(2x) performs a compression by a factor of 2 (tip of the hat goes to knedlsepp for noticing my blunder). Due to the periodic nature of sin(x), we know that elements will repeat after 2*pi, and so if you want to go to 4*pi, simply subsample y by a factor of 2 and then append these same elements to a new vector. Therefore, our expression for the function simplifies to:
y = exp(-x)exp(-x)sin(2x)
This leads to the answer alluded to knedlsepp:
plot(x+x, z.*z.*[y(1:2:end) y(1:2:end)]);
As such, you should consider changing your edits to match this answer instead. It isn't quite right with respect to the sin(x) part in your code.

Surface plot with 3 vectors Matlab

I need to be able to do a surface plot using data from 3 vectors. I found similar information, but no method seems to work with my data. My X and Y columns are evenly spaced, but not in increasing order. I tried different methods, but none of them seem to give me what I want, which is a simple surface linking close points together. I tried the following:
[X Y]=meshgrid(x,y);
Z=griddata(x,y,z, X,Y);
surf(X,Y,Z);
This is not exactly what I want, because it creates a surface at z=0 and makes it look more like a volume plot than just a surface. It also runs very slowly on my computer (probably from creating all the gridpoints). If I could get something that doesn't require as much memory it would be ideal (my vectors have about 20k values each), but this is not a necessity.
***Edit: I also tried using the scatteredInterpolant method found here,but the function doesn't seem to be recognized by MATLAB and I get this error:
Undefined function 'scatteredInterpolant' for input arguments of type 'double'.
Also here is an image of my problem:
You can see that we can't see under the surface, there is some z=0 plane blocking it.
If you have anything for me, any help is appreciated.
Thanks in advance.
**Edit 2: I added sample vectors, they're my x,y and z values from left to right.
***Edit 3: Here's an image of the triangulation I get. As you can see some points are being ignored for some reason, which gives those long and weird looking blue triangles.
Mike
As conventional methods seem to fail, I would suggest you to do it manually.
Create a Z matrix full of NaN values. The size of the matrix should be dependant on your x and y values.
Loop over all occuring x,y, pairs and put their (average?) z value in the right position of your Z matrix.
Loop over all NaN values and interpolate their value. Perhaps using filter2.
Use surf to plot the resulting surface
If you have points which are described by vectors, and you want to plot them you could always use a Delauny triangulation. The function in matlab is called Tri=delauny(X,Y,Z). The data generated by this function can be shown with either trimesh(Tri,X,Y,Z) or trisurf(Tri,X,Y,Z). Keep in mind trisurf is only for 3D data. If you want to adjust the transparancy of plots in your graph use the alpha setting.
I hope this helps
To me it looks like you just need to sort your data before plotting.
Here is an example which I believe is similar to your case (since I could not download your data).
x = [2 1 4 3 -1 -3 -4 -2];
y = [1 2 3 4 -1 -2 -3 -4];
z = 32 - x.*x - y.*y;
[X1 Y1] = meshgrid(x,y);
Z1 = 32 - X1.*X1 -Y1.*Y1;
surf(X1,Y1,Z1)
aux = sort([x;y],2);
x = aux(1,:);
y = aux(2,:);
[X2 Y2] = meshgrid(x,y);
Z2 = 32 - X.*X - Y.*Y;
figure()
surf(X2,Y2,Z2)
The first figure results in a very problematic surface:
The second figure contains the desired surface:

Matlab's Quiver3 plots only 4 vectors

I want to use the command quiver3(X,Y,Z,M,N,O)
in order to get a vector field, where all matrices are 10x10x10 arrays with real entries. Now I wanted to plot it and got only 4 vectors instead of my expected 1000. Does anybody here know, what I could possibly have done wrong?
If you need further information, I am available for your comments.
Assuming the problem occurs when attempting to display the data (rather than with attempting to display unallowed numerical values such as Inf or NaN), I think the problem is the range of norms of the vectors, such that only 4 show up.
The importance of the norm of the vectors relative to the range of the coordinate system is important, as illustrated by the following example:
Here all 10 random vectors show up:
Na = 10;
[X Y Z M N O] = deal(rand(Na,1),rand(Na,1),rand(Na,1),rand(Na,1),rand(Na,1),rand(Na,1));
quiver3(X,Y,Z,M,N,O)
But if some of the vectors are made 100 x bigger, only the smaller ones show up:
mul = 1e+3;
[X Y Z M N O] = deal(rand(Na,1),rand(Na,1),rand(Na,1),...
[mul*rand(Na/2,1);rand(Na/2,1)],...
[mul*rand(Na/2,1);rand(Na/2,1)],...
[mul*rand(Na/2,1);rand(Na/2,1)]);
quiver3(X,Y,Z,M,N,O)
Similarly if some of the vectors are made too small they don't show up:
mul = 1e-3;
[X Y Z M N O] = deal(rand(Na,1),rand(Na,1),rand(Na,1),...
[mul*rand(Na/2,1);rand(Na/2,1)],...
[mul*rand(Na/2,1);rand(Na/2,1)],...
[mul*rand(Na/2,1);rand(Na/2,1)]);
quiver3(X,Y,Z,M,N,O)
Vectors too large or too small relative to the axis are not displayed at all.
If it is a problem with scaling you may want to inspect your function and see how to narrow the range of x,y,z so that the vectors have a narrower range of values, or change the scale (logarithm?) so that all the data can be displayed in one figure.
edit
As an alternative to the question of how to display your data, you may want to consider using isosurfaces. Here's an example, with each red sphere representing a different isosurface in a spherical potential:

How to find the x-intercept of a plot in Matlab

I know there must be a really simple answer to this question, but I just can't seem to find it. (Guess I'm probably Googling the wrong terms.)
I am plotting some data in Matlab using the plot(x, data) function.
I want to find the x-intercept(s) of the line, i.e. the point(s) where y = 0.
In some cases, it may be that the data vector doesn't actually contain values equal to zero, so it's not just a matter of finding the indexes of the elements in data which are equal to zero, and then finding the corresponding elements in the x vector.
Like I said, it's a really simple problem and I'd think there's already some in-built function in Matlab...
Thank you for your help.
If you want to find X-intercept as interpolate between 2 closest points around X axes you can use INTERP1 function:
x0 = interp1(y,x,0);
It will work if x and y are monotonically increasing/decreasing.
x=-1.999:0.001:1.999;
y=(x-1).*(x+1);
plot(x,y)
hold on
plot(x,zeros(length(x),1),'--r')
find(abs(y)<1e-3)
So the last part will guarantee that even there is not exact y-intercept, you will still get a close value. The result of this code are the indices that satisfy the condition.
You can make a linear fit (1st order polynomial) to your data, then, from the slope and Y intercept of the fitted line, you'll be able to find X intercept. Here is an example:
x1 = 1:10;
y1 = x1 + randn(1,10);
P = polyfit(x1,y1,1);
xint = -P(2)/P(1);
if you want to know what is the slope and y_int, here it is:
Slope = P(1); % if needed
yint = P(2); % if need