I have
x = linspace(-5,5,256)
y = 1./(1+x.^2)
plot(x,y,'...') %plot of (x,y)
I want to estimate this with a polynomial of order 10, such that the polynomial intersects the graph at 11 points.
So, I did this:
x2 = linspace(-5,5,11)
y2 = 1./(1+x2.^2)
p = polyfit(x2,y2,10) %finds coefficients of polynomial of degree 10 that fits x2,y2
y3 = polyval(p,x2)
plot(x,y,x2,y3,'...')
I thought the polyfit would give me the coefficients for a polynomial up to order 10, which intersects the points (x2,y2) (i.e 11 points)
then y3 is essentially just the y values of where the 10th order polynomial lands, so plotting them altogether would give me the 10th order polynomial, intersecting my original graph at 11 unique points?
What have I done wrong?
My result:
Your computations are correct, but you are not plotting the function the right way. The blue line in your generated plot is piecewise linear. That's because you are only evaluating your polynomial p at the interpolation points x2. The plot command then draws line segments between those points and you are presented with your unexpected plot.
To get the expected result you simply have to evaluate your polynomial more densely like so:
x3 = linspace(-5,-5,500);
y3 = polyval(p,x3);
plot(x3,y3);
Consider the points (1,3), (2,6.2) and (3,13.5). Use Matlab's builtin function polyfit to obtain the best parameters for fitting the model P = Poekt to this data
Related
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
I used the Matlab command polyfit to interpolate a curve. I then wanted to calculate the y-max value of that curve. I have found the roots for the polynomial, so i now have an x-value I want to insert in the polynomial from polyfit to get the y-value for that x-value.
I have difficulties to get it working properly.
P is the polynomial, so as you know, P(1)^4, P(2)^3... and so on
P = [-1.99405270507682e+26 5.55362828633395e+24 -5.80027044841956e+22 2.69238494640005e+20 -4.68659390860982e+17]
The x-value I want to insert to get a y-value is
x = 7.765633479578490e-04
The y-value should be about 17.7.
Am I thinking right here? The x-value is correct, I have compared it to my plot.
Thanks in advance guys!
Something is wrong in your calculations. With the values you give in your question, P(x) is enormous due to the enormous polynomial coefficients you have:
P =
-1.9941e+026 5.5536e+024 -5.8003e+022 2.6924e+020 -4.6866e+017
>> x = 7.765633479578490e-04
x = 7.7656e-004
>> y = polyval(P,x)
y = -2.9203e+017
These are the roots of your polynomial, they have very small imaginary parts, but given the enormous coefficients of the polynomial, they cannot be neglected:
>> format long g
>> roots(P)
ans =
0.00696463336211033 + 9.88579484856405e-07i
0.00696463336211033 - 9.88579484856405e-07i
0.00696084682252702 + 1.06977927834625e-06i
0.00696084682252702 - 1.06977927834625e-06i
I have two 2D points p1, p2 in MATLAB, and each point has a normal n1, n2. I wish to find the (cubic) polynomial which joins the two points and agrees with the specified normals at each end. Is there something built-in to MATLAB to do this?
Of course, I could derive the equations for the polynomial manually, but MATLAB's curve fitting toolbox has so much built-in that I assumed it would be possible. I haven't been able to find any examples of curve, spline or polynomial fitting where the normals are specified.
As an extrapolation of this, I would like to fit splines where each data point has a normal specified.
1. If your points are points of a function, then you need cubic Hermite spline interpolation:
In numerical analysis, a cubic Hermite spline or cubic Hermite
interpolator is a spline where each piece is a third-degree polynomial
specified in Hermite form: that is, by its values and first derivatives at the
end points of the corresponding domain interval.
Cubic Hermite splines
are typically used for interpolation of numeric data specified at
given argument values x(1), x(2), ..., x(n), to obtain a smooth
continuous function. The data should consist of the desired function
value and derivative at each x(k). (If only the values are provided,
the derivatives must be estimated from them.) The Hermite formula is
applied to each interval (x(k), x(k+1)) separately. The resulting
spline will be continuous and will have continuous first derivative.
Cubic polynomial splines can be specified in other ways, the Bézier
form being the most common. However, these two methods provide the
same set of splines, and data can be easily converted between the
Bézier and Hermite forms; so the names are often used as if they were
synonymous.
Specifying the normals at each point is the same as specifying the tangents (slopes, 1st derivatives), because the latter are perpendicular to the former.
In Matlab, the function for calculating the Piecewise Cubic Hermite Interpolating Polynomial is pchip. The only problem is that pchip is a bit too clever:
The careful reader will notice that pchip takes function values as
input, but no derivative values. This is because pchip uses the
function values f(x) to estimate the derivative values. [...] To do a
good derivative approximation, the function has to use an
approximation using 4 or more points [...] Luckily, using Matlab we
can write our own functions to do interpolation using real cubic
Hermite splines.
...the author shows how to do this, using the function mkpp.
2. If your points are not necessarily points of a function, then each interval should be interpolated by a quadratic Bezier curve:
In this example, 3 points are given: the endpoints P(0) and P(2), and P(1), which is the intersection of the tangents at the endpoints. The position of P(1) can be easily calculated from the coordinates of P(0) and P(2), and the normals at these points.
In Matlab, you can use spmak, see the examples here and here.
You could do something like this:
function neumann_spline(p, m, q, n)
% example data
p = [0; 1];
q = [2; 5];
m = [0; 1];
n = [1; 1];
if (m(2) ~= 0)
s1 = atan(-m(1)/m(2));
else
s1 = pi/2;
end
if (n(2) ~= 0)
s2 = atan(-n(1)/n(2));
else
s2 = pi/2;
end
hold on
grid on
axis equal
plot([p(1) p(1)+0.5*m(1)], [p(2) p(2)+0.5*m(2)], 'r', 'Linewidth', 1)
plot([q(1) q(1)+0.5*n(1)], [q(2) q(2)+0.5*n(2)], 'r', 'Linewidth', 1)
sp = csape([p(1) q(1)], [s1 p(2) q(2) s2], [1 1]);
fnplt(sp)
plot(p(1), p(2), 'k.', 'MarkerSize', 16)
plot(q(1), q(2), 'k.', 'MarkerSize', 16)
title('Cubic spline with prescribed normals at the endpoints')
end
The result is
I am trying to finish an assignment and I don't really know how to do what the question asks. I am not looking for a complete answer, but just an understanding on what I need to use/do to solve the question. Here is the question:
We are asked to provide an interpolant for the Bessel function of the first
kind of order zero, J0(x).
(a) Create a table of data points listed to 7 decimal places for the interpolation points
x1 = 1.0, x2 = 1.3, x3 = 1.6, x4 = 1.9, x5 = 2.2.
[Hint: See Matlab's help on BesselJ.]
(b) Fit a second-degree polynomial through the points x1, x2, x3. Use this interpolant
to estimate J0(1.5). Compute the error.
What exactly does BesselJ do? And how do I fit a second degree polynomial through the three points?
Thanks,
Mikeshiny
Here's the zeroth order Bessel function of the first kind:
http://mathworld.wolfram.com/BesselFunctionoftheFirstKind.html
Bessel functions are to differential equations in cylindrical coordinates as sines and cosines are to ODEs in rectangular coordinates.
Both have series representations; both have polynomial approximations.
Here's a general second-order polynomial:
y = a0 + a1*x + a2*x^2
Substitute in three points (x1, y1), (x2, y2), and (x3, y3) and you'll have three equations for three unknown coefficients a0, a1, and a2. Solve for those coefficients.
Take a look at the plot of y = J0(x) in the link I gave you. You want to fit a 2nd order poly through some range. So - pick one. The first point is (0, 1). Pick two more - maybe x = 1 and x = 2. Look up the values for y at those values of x from a J0 table and evaluate your coefficients.
Here are my three points: (0,1), (1, 0.7652), (2.4048, 0).
When I calculate the coefficients, here's the 2nd order polynomial I get:
J0(x) = 1 -0.105931124*x -0.128868876*x*x
I'm trying to do a scatter plot with a line of best fit in matlab, I can get a scatter plot using either scatter(x1,x2) or scatterplot(x1,x2) but the basic fitting option is shadowed out and lsline returns the error 'No allowed line types found. Nothing done'
Any help would be great,
Thanks,
Jon.
lsline is only available in the Statistics Toolbox, do you have the statistics toolbox? A more general solution might be to use polyfit.
You need to use polyfit to fit a line to your data. Suppose you have some data in y and you have corresponding domain values in x, (ie you have data approximating y = f(x) for arbitrary f) then you can fit a linear curve as follows:
p = polyfit(x,y,1); % p returns 2 coefficients fitting r = a_1 * x + a_2
r = p(1) .* x + p(2); % compute a new vector r that has matching datapoints in x
% now plot both the points in y and the curve fit in r
plot(x, y, 'x');
hold on;
plot(x, r, '-');
hold off;
Note that if you want to fit an arbitrary polynomial to your data you can do so by changing the last parameter of polyfit to be the dimensionality of the curvefit. Suppose we call this dimension d, you'll receive back d+1 coefficients in p, which represent a polynomial conforming to an estimate of f(x):
f(x) = p(1) * x^d + p(2) * x^(d-1) + ... + p(d)*x + p(d+1)
Edit, as noted in a comment you can also use polyval to compute r, its syntax would like like this:
r = polyval(p, x);
Infs, NaNs, and imaginaryparts of complex numbers are ignored in the data.
Curve Fitting Tool provides a flexible graphical user interfacewhere you can interactively fit curves and surfaces to data and viewplots. You can:
Create, plot, and compare multiple fits
Use linear or nonlinear regression, interpolation,local smoothing regression, or custom equations
View goodness-of-fit statistics, display confidenceintervals and residuals, remove outliers and assess fits with validationdata
Automatically generate code for fitting and plottingsurfaces, or export fits to workspace for further analysis