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.
I want to add objects to my matlab plots which have defined x limits but span the whole y range. Examples are vertical lines or shaded regions delimited by two x values. I am aware of the option to use the current plot limits like this:
plot(1:10)
yl = ylim();
% Use y limits of current plot as y values
patch([ 3 3 5 5 ],[ yl(1) yl(2) yl(2) yl(1) ], 'red');
However I want my users to be able to increase plot y limits afterwards (e.g. to synchronize limits of multiple plots) and also want them to continue profiting from Matlab's automatic setting of plot limits.
This would be archivable if I would use the following code to set the y coordinates of my objects to the largest and smallest possible integers, respectively (intmax() and intmin() in Matlab) and tell Matlab not to consider that object during calculation of plot limits.
plot(1:10)
% Make graphical object which spans the whole possibly y range
p = patch([ 3 3 5 5 ],[ intmin intmax intmax intmin ], 'red');
% Does something like the following function exist?
exemptFromPlotLimitsCalculation(p)
Is this possible in Matlab?
You could plot the patch (or fill) really large (for example by using realmax) and exclude it from rescaling by setting the property YLimInclude to off
patch([3 3 5 5], realmax*[ -1 1 1 -1], 'red', 'YLimInclude', 'off');
have a look at this
In the postActionCallback you can resize your patch
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).
I have the following matlab code for approximating a differential equation via the Euler-method:
% Eulermethod
a=0;
b=0.6;
Steps=6;
dt=(b-a)/Steps;
x=zeros(Steps+1,1);
x(1,1)=1;
y=zeros(Steps+1,1);
for i=1:Steps
x(i+1,1)=x(i,1)+dt*(x(i,1)*x(i,1)+1);
end
plot(x)
I want to be able to plot the solution plot for several different values of Steps in one plot and have the x-axis go from 0 to 0.6 instead of from for example 1 to 100 000 etc. Can this be done?
If you use the hold on command this will allow you achieve multiple plots on the same figure. Similarly, if you separate your data into x and y vectors, you can plot them against eachother by passing 2 vectors to plot instead of just one. For example
figure
hold on
for i=1:m
x = [];
y = [];
%% code to populate your vectors
plot(x,y)
end
You should now see all your plots simultanesously on the same figure. If you want x to be composed of n equally spaced elements between 0 and 0.6, you could use the linspace command:
x = linspace(0.0,0.6,n);
In order to distinguish your plots, you can pass an extra paramter to the function .For example
plot(x,y,'r+')
will plot the data as a series of red + symbols.
Plot can take more arguments: plot(x_axis,values, modifiers);
If x-axis is a vector of M elements, values can be a matrix of MxN elements, each of which are drawn with a separate color.
I have a matrix with 1000 real numbers within range -3 to 3. I have to plot the numbers on a graph so as to get a continuous curve combining all the points. The matrix name is Points and it is 1000 by 1 matrix.
try
plot(Points(:)); % plot the points
ylim([-3 3]); % set the y limits