Extract trajectory at a contour level from streamline in MATLAB - matlab

When plotting streamlines in MATLAB using quiver, streamslice or similar, is it possible to extract the contour line at given contour level?
Take this example (I have numerical data in my case, but I will use analytical functions in the example):
[X,Y] = meshgrid(0:.02:1);
Z = X.*exp(-X.^2 - Y.^2);
[DX,DY] = gradient(Z,.2,.2);
figure
imagesc([0 1], [0 1], Z)
hold on
streamslice(X,Y,DX,DY) %how to extract a trajectory at a given contour level C?
hold off
colorbar
If not, is it possible to obtain them otherwise? I was thinking of using contour in this way,
contour(X,Y,sqrt(DX.*DX+DY.*DY), [1 1]*0.07)
but this is clearly wrong when I compare to the streamlines above.

hs = streamslice(X,Y,DX,DY); as result you obtain a vector with handles to the traject lines. For example, you can get the coordinates of the first traject line:
N_trajects = length(hs); % the number of all trajectories
n = 1; % the chosen trajectory
X_traject = get(hs(n),'XData');
Y_traject = get(hs(n),'YData');
or using new version of MATLAB:
X_traject = hs(n).XData;
Y_traject = hs(n).YData;
To extract countour lines data:
C = contour(X,Y,sqrt(DX.*DX+DY.*DY), [1 1]*0.07);
where C consits data with the contour lines. In your case there is one contour line only (X_contour = C(1,:), Y_contour = C(2,:)). In the case of many contour levels, to extract them see here or here or using this.
Now we know the coordinates of the trajectory and contour level. Thus you can find the point(s) of intersection between the trajectory and the contour level.

Related

matlab: Graph 2d lines on x,y and z axis in a 3d plot

Given a complex signal I have 3 dimensions: I-real part, Q-imaginary part, T-time.
I have been able to use the:
plot3(I,T,Q)
to plot the signal in matlab. I would now like to add the Q-imaginary part line graph to the z-plane and the I-real part line graph to the x,y plane. How can I add the additional lines to the graph? I included a picture of what I want it to look like:
What I have so far is this:
Commented code below:
% hold on for multiple plots
figure(1)
hold on
% Plot 3D Figure
plot3(I,T,Q)
% Plot on XY plane - means function in Z = 0
plot3(I,T,Q.*0)
% Plot on YZ plane - means function in X = 0
plot(I.*0,T,Q)
hold off
In your case the planes being plotted on aren't actually the axes' zeros. You may want to set the zero vector in each 2D plot to be any single-valued vector, which you can make the correct length by methods like this:
% vector of 2s the same size as Q
A = (Q./Q).*2;
% or
A = ones(size(Q)).*2;
% or
A = A.*0 + 2;
For instance, plotting a similar function to your image:
x = linspace(0,20,1000);
hold on
plot3(sin(x),x,cos(x))
plot3(sin(x),x,cos(x).*0 - 1)
plot3(sin(x).*0 + 1,x,cos(x))
grid on
hold off

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

Extend a line through 3 points matlab

Im just trying to draw a line through the following points in matlab. Currently the line extends only to the points. I need to to extend and intercept the x axis. The code is below
A = [209.45 198.066 162.759];
B = [1.805 1.637 1.115];
plot(A,B,'*');
axis([0 210 0 2]);
hold on
line(A,B)
hold off
If you want to augment your points with a corresponding y==0 point, I suggest using interp1 to obtain the x-intercept:
A = [209.45 198.066 162.759];
B = [1.805 1.637 1.115];
x0 = interp1(B,A,0,'linear','extrap'); %extrapolate (y,x) at y==0 to get x0
[newA, inds] = sort([x0 A]); %insert x0 where it belongs
newB = [0 B];
newB = newB(inds); %keep the same order with B
plot(A,B,'b*',newA,newB,'b-');
This will use interp1 to perform a linear interpolant, with extrapolation switched on. By interpolating (B,A) pairs, we in effect invert your linear function.
Next we add the (x0,0) point to the data, but since matlab draws lines in the order of the points, we have to sort the vector according to x component. The sorting order is then used to keep the same order in the extended B vector.
Finally the line is plotted. I made use of plot with a linespec of '-' to draw the line in the same command as the points themselves. If it doesn't bother you that the (x0,0) point is also indicated, you can plot both markers and lines together using plot(newA,newB,'*-'); which ensures that the colors match up (in the above code I manually set the same blue colour on both plots).

coordinates from contour in matlab where level is zero

I have wrote a program using Level Set Function for curve propagation. Curve is represented by level zero in contour plot. How can I get the coordinates of these curve as I march in time?
Contour are obtained at every time step. How to get the coordinates at each step?
A zero level contour from a set of points z(x,y) can be obtained by contourc. For instance, for the peaks-example of MATLAB, we obtain the contour lines with height 0 as follows:
c = contourc(peaks, [0,0]);
If this contour is a single line, this is all you need to do. However, the contour might consists of multiple islands (which is the case for this example), which means that you need to split the set of (x,y) coordinates in c somehow. A split based on NaN values can be obtained through:
c(:,~c(1,:)) = NaN;
and the result can be plot by
plot(c(1,:),c(2,:),'k');
If this is not sufficient, you could also construct a cell array c_split of islands:
b = find(~c(1,:))+1;
e = b+c(2,b-1)-1;
c_split = arrayfun(#(idx) c(:,b(idx):e(idx)), 1:numel(b), 'uni', 0)';
and the visualisation is very similar:
idx = 1;
plot(c_split{idx}(1,:),c_split{idx}(2,:),'k');
If the contours need to be stored for multiple time steps, you combine all results into a cell:
c_all{idx} = c;

How can I contour plot a custom function?

I have a custom function which returns either 0 or 1 depending on two given inputs:
function val = myFunction(val1, val2)
% logic to determine if val=1 or val=0
end
How can I create a contour plot of the function over the x,y coordinates generated by the following meshgrid?
meshgrid(0:.5:3, 0:.5:3);
This plot will just simply display where the function is 0 or 1 on the contour map.
If your function myFunction is not designed to handle matrix inputs, then you can use the function ARRAYFUN to apply it to all the corresponding entries of x and y:
[x,y] = meshgrid(0:0.5:3); %# Create a mesh of x and y points
z = arrayfun(#myFunction,x,y); %# Compute z (same size as x and y)
Then you could use the function CONTOUR to generate a contour plot for the above data. Since your z data only has 2 different values, it would probably make sense for you to only plot one contour level (which would be at a value of 0.5, halfway between your two values). You might also want to instead use the function CONTOURF, which produces color-filled contours that will clearly show where the ones and zeroes are:
contourf(x,y,z,1); %# Plots 1 contour level, filling the area on either
%# side with different color
NOTE: Since you are plotting data that only has ones and zeroes, plotting contours may not be the best way to visualize it. I would instead use something like the function IMAGESC, like so:
imagesc(x(1,:),y(:,1),z);
Keep in mind the y-axis in this plot will be reversed relative to the plot generated by CONTOURF.
The following will do it:
function bincontour
clear; clc;
xrange = 0:.5:3;
yrange = 1:.5:5;
[xmesh, ymesh] = meshgrid(xrange, yrange);
z = arrayfun(#myFunction, xmesh, ymesh);
contourf(xrange, yrange, z, 5)
end
function val = myFunction(val1, val2)
val = rand() > 0.5;
end