How to plot parametric functions between infinite limits? - matlab

How to plot these parametric functions with infinite limits to get a circle using matlab?
x(t)=2t/(1+t.^2)
y(t)=(1-t.^2)/(1+t.^2)

I don't know about infinite limits but
%Construct a vector of t ranging from a very small number to a very large number
t = -1000:0.1:1000;
%Create x and y vectors based on your formula (with a couple of extra dots for element wise division)
x =2*t./(1+t.^2);
y =(1-t.^2)./(1+t.^2);
%Just normal plotting now
plot(x,y)
gives me a circle. There will still be a tiny gap around (0, -1) however.

Related

matlab: upsampling a zero contour

I am using the undocumented contours function in Matlab to obtain the zero contour of a function mapping R^2 to R. The function contours() calls contourc() to obtain the zero contour in terms of array indices, and contours() then performs linear interpolation to convert from (M,N) array indices to (Y,X) data coordinates. This works well and gives a zero contour which is essentially accurate to machine precision. However, attempting to interpolate along this zero contour to obtain additional points fails, apparently because the interpolated points deviate to a small extent from the true zero contour; the resulting error is too large for the intended application.
As a simple example, one can compute a zero contour of the peaks function, compute the function values along the contour, and then compute the function values at new points interpolated along the contour. The maximum error is roughly eps(max(Z(:)) for the points found by countours/countourc and about ten orders of magnitude higher for the interpolated points.
% compute the zero contours; keep part of one contour
[X,Y,Z] = peaks(999);
XY0 = contours(X, Y, Z, [0 0]);
XY0 = XY0(:,140:(XY0(2,1)+1)); % keep only ascending values in the first contour for interpolation
% interpolate points along the zero contour
x2y = griddedInterpolant(XY0(1,:), XY0(2,:), 'linear','none');
X0i = linspace(XY0(1,1), XY0(1,end), 1e4);
Y0i = x2y(X0i);
% compute values of the function along the zero contour
Zi = interp2(X,Y,Z, XY0(1,:), XY0(2,:), 'linear', NaN);
Z0i = interp2(X,Y,Z, X0i, Y0i, 'linear', NaN);
% plot results
figure;
subplot(1,3,1); plot(XY0(1,:), XY0(2,:), '.'); hold on; plot(X0i, Y0i, 'Linewidth',1);
xlabel('X_0'); ylabel('Y_0'); title('(X_0,Y_0), (X_{0i},Y_{0i})');
subplot(1,3,2); plot(XY0(1,:), Zi, '.');
xlabel('X_0'); ylabel('Z_0'); title('f(X_0,Y_0)');
subplot(1,3,3); plot(XY0(1,:), Zi, '.'); hold on; plot(X0i, Z0i, '.');
xlabel('X_0'); ylabel('Z_0'); title('f(X_{0i},Y_{0i})');
The error is almost certainly because the interpolant does not truly follow the zero contour (i.e., having the same tangent, curvature, and indeed all higher derivatives at each point). Each interpolated point thus deviates to a small degree from the path of the zero contour. This is true for all tested methods of interpolation. If the functional form of the zero contour were known, one could fit a function to the zero contour, which would likely give satisfactory results. However, for the application motivating this question, an analytical solution of the zero contour is not possible.
Given the inadequacy of interpolation to this task, how can new points along the zero contour be obtained? The points should be such that the value of the function is as close to zero as for the set of points returned by contourc. Increasing the grid resolution globally is not an option since the memory and computational expense increase with the square of the resolution. Locally sampling at high resolution in an iterative manner over consecutive short intervals of the zero contour is an option, but would take time to implement, and I'm not aware of existing code (e.g., in the FEX) to perform such a task. Also, since contourc is closed-source, adapting it to this task is not an option.
I solved this problem by taking the interpolated (X,Y) values as an approximation of the true zero contour and reinterpolating the Y coordinate of each pair with respect to Z values of the surface flanking the approximate zero in order to locate the Y coordinate at which Z=0 for each (X,Y) pair. In so doing, uniform spacing of the interpolated X values is preserved.
For each (iX,iY) pair, where iX and iY denote the (fractional) array indices of the X and Y coordinate grids for the points interpolated along the zero contour, the approximate iY values are reinterpolated with respect to the values of Z at positions flanking (in the Y dimension) the approximate zero, i.e., at (iX,floor(iY)) and (iX,ceil(iY)). The Z values at these flanking points are themselves obtained by performing bilinear interpolation of Z at these points.
After reinterpolation, the magnitude of the error is the same as that of the points originally returned by contourc/contours.

How to make smooth plot with matrix that don't have the same column and line [duplicate]

Let's say we have the following data:
A1= [41.3251
18.2350
9.9891
36.1722
50.8702
32.1519
44.6284
60.0892
58.1297
34.7482
34.6447
6.7361
1.2960
1.9778
2.0422];
A2=[86.3924
86.4882
86.1717
85.8506
85.8634
86.1267
86.4304
86.6406
86.5022
86.1384
86.5500
86.2765
86.7044
86.8075
86.9007];
When I plot the above data using plot(A1,A2);, I get this graph:
Is there any way to make the graph look smooth like a cubic plot?
Yes you can. You can interpolate in between the keypoints. This will require a bit of trickery though. Blindly using interpolation with any of MATLAB's commands won't work because they require that the independent axes (the x-axis in your case) to increase. You can't do this with your data currently... at least out of the box. Therefore you'll have to create a dummy list of values that span from 1 up to as many elements as there are in A1 (or A2 as they're both equal in size) to create an independent axis and interpolate both arrays independently by specifying the dummy list with a finer spacing in resolution. This finer spacing is controlled by the total number of new points you want to introduce in the plot. These points will be defined within the range of the dummy list but the spacing in between each point will decrease as you increase the total number of new points. As a general rule, the more points you add the less spacing there will be and so the plot should be more smooth. Once you do that, plot the final values together.
Here's some code for you to run. We will be using interp1 to perform the interpolation for us and most of the work. The function linspace creates the finer grid of points in the dummy list to facilitate the interpolation. N would be the total number of desired points you want to plot. I've made it 500 for now meaning that 500 points will be used for interpolation using your original data. Experiment by increasing (or decreasing) the total number of points and seeing what effect this has in the smoothness of your data.
I'll also be using the Piecewise Cubic Hermite Interpolating Polynomial or pchip as the method of interpolation, which is basically cubic spline interpolation if you want to get technical. Assuming that A1 and A2 are already created:
%// Specify number of interpolating points
N = 500;
%// Specify dummy list of points
D = 1 : numel(A1);
%// Generate finer grid of points
NN = linspace(1, numel(A1), N);
%// Interpolate each set of points independently
A1interp = interp1(D, A1, NN, 'pchip');
A2interp = interp1(D, A2, NN, 'pchip');
%// Plot the data
plot(A1interp, A2interp);
I now get the following:

Smooth plot of non-dependent variable graph

Let's say we have the following data:
A1= [41.3251
18.2350
9.9891
36.1722
50.8702
32.1519
44.6284
60.0892
58.1297
34.7482
34.6447
6.7361
1.2960
1.9778
2.0422];
A2=[86.3924
86.4882
86.1717
85.8506
85.8634
86.1267
86.4304
86.6406
86.5022
86.1384
86.5500
86.2765
86.7044
86.8075
86.9007];
When I plot the above data using plot(A1,A2);, I get this graph:
Is there any way to make the graph look smooth like a cubic plot?
Yes you can. You can interpolate in between the keypoints. This will require a bit of trickery though. Blindly using interpolation with any of MATLAB's commands won't work because they require that the independent axes (the x-axis in your case) to increase. You can't do this with your data currently... at least out of the box. Therefore you'll have to create a dummy list of values that span from 1 up to as many elements as there are in A1 (or A2 as they're both equal in size) to create an independent axis and interpolate both arrays independently by specifying the dummy list with a finer spacing in resolution. This finer spacing is controlled by the total number of new points you want to introduce in the plot. These points will be defined within the range of the dummy list but the spacing in between each point will decrease as you increase the total number of new points. As a general rule, the more points you add the less spacing there will be and so the plot should be more smooth. Once you do that, plot the final values together.
Here's some code for you to run. We will be using interp1 to perform the interpolation for us and most of the work. The function linspace creates the finer grid of points in the dummy list to facilitate the interpolation. N would be the total number of desired points you want to plot. I've made it 500 for now meaning that 500 points will be used for interpolation using your original data. Experiment by increasing (or decreasing) the total number of points and seeing what effect this has in the smoothness of your data.
I'll also be using the Piecewise Cubic Hermite Interpolating Polynomial or pchip as the method of interpolation, which is basically cubic spline interpolation if you want to get technical. Assuming that A1 and A2 are already created:
%// Specify number of interpolating points
N = 500;
%// Specify dummy list of points
D = 1 : numel(A1);
%// Generate finer grid of points
NN = linspace(1, numel(A1), N);
%// Interpolate each set of points independently
A1interp = interp1(D, A1, NN, 'pchip');
A2interp = interp1(D, A2, NN, 'pchip');
%// Plot the data
plot(A1interp, A2interp);
I now get the following:

number of contours in contourf function

What is the default for the contours in a contourf function in matlab?
For example:
Z = peaks(20);
contourf(Z);
What do each of these contours represent? If I don't specify the second term in contourf e.g. contourf(Z,10) which would give 10 contour lines, how does matlab choose the number of contours?
You can look up the detailed algorithm for calculating the initial contour level step sizes from MATLABROOT\toolbox\matlab\specgraph\#specgraph\#contourgroup\refresh.m, around line 25.
Basically, Matlab divides the range into ~10 steps, but adjusts that number a bit depending on the exact value of the range of z-values.
There is no default. You are defining the number of contours by using:
Z=peaks(20);
This in effect returns an 20x20 [m,n] matrix of peaks which is stored in Z.
The ranges of the x-axis and y-axis are based on the size of array Z.
The number of contour lines and the values of the contour lines are taken from the minimum and maximum values of peaks inside the Z array.
The Z array is populated with the peaks() function which uses Normal Distribution (or Gaussian distribution).
As the documentation of the
contourf function says:
The number of contour lines and the values of the contour lines are chosen automatically based on the minimum and maximum values of Z. The ranges of the x-axis and y-axis are [1:n] and [1:m], where [m,n] = size(Z).

Cumulative distribution in Matlab

I have a question on plotting probability distribution and cumulative distribution curves using Matlab. I apologize for asking a noob question but I am new to Matlab, having only used it for a few hours.
I have a set of data which has the size range for the sand particles found on a beach in millimeters (e.g: >2.00, 1.00–2.00, 0.50–1.00, <0.50).
And their corresponding percentages of finding these sand particles are as follows:
(e.g.: 30, 25.5, 35.9, 8.6).
How am I supposed to input the values in the Matlab system for it to plot the probability distribution and cumulative distribution curves on the same plot with different colors? Percentage should be the y-axis and the size range should be the x-axis.
If your dataset is literally 4 points, then you can simply enter them literally. For example, if my dataset was {(A, 1), (B, 2), (C, 3)}, then we could simply set y = [1, 2, 3] and x = {'a', 'b', 'c'}.
For distributions, you should take a look at the sum and cumsum functions.
For plotting, take a look at bar for frequency plots and plot for cumulative plots (this is just my preference). The documentation contains information on setting colors.
For plotting on the same graph, look at hold. To label your plot and your axes, look at xlabel, ylabel, and title.
Matlab has a good FAQ on setting the actual values that are displayed on each axis. For example, I can plot my dataset above by plotting the y vector only, and then setting the X tick labels to 'A', 'B', and 'C'.
I'd be careful with the cumulative distribution function (CDF). It might make more sense to reorder your data in increasing particle size (see fliplr() function) otherwise your CDF's interpretation will be suspect.
The cumsum() function can get your CDF from the given probability mass function (PMF).
label={'<0.50','0.50-1.00','1.00-2.00','>2.00'}';
pmf = [0.086 0.359 0.255 0.30]';
cdf = cumsum(pmf);
bar(pmf) % PMF
set(gca,'XTickLabel',label)
title('Sand Particle Size Distribution')
xlabel('Sand particle size (mm)')
figure
stairs(cdf,'ks-','LineWidth',2.0) % CDF
set(gca,'XTick',1:length(label),'XTickLabel',label)
ylabel('Percentile')
xlabel('Sand particle size (mm)')
ylim([0 1])