Matlab error message regarding use of polyfit function in script file - matlab

I am trying to run a script file which draws a line on a plotted graph. Sometimes the script file works but occasionally it does not work and the line drawn on the graph is not where I want it. When the file does not work I get the following error message:
Warning: Polynomial is not unique. Degree >= number of data points.
> In polyfit at 70
In FIXING_force_and_rate_of_rise at 48
Does anyone know what this error message means? What does it mean when a polynomial is not unique?
If it helps, when I click on the error message I get taken to this explanation:
Solve least squares problem.
[Q,R] = qr(V,0);
ws = warning('off','all');
p = R\(Q'*y);
% Same as p = V\y;
warning(ws);
if size(R,2) > size(R,1)
warning(message('MATLAB:polyfit:PolyNotUnique'))
elseif warnIfLargeConditionNumber(R)
if nargout > 2
warning(message('MATLAB:polyfit:RepeatedPoints'));
else
warning(message('MATLAB:polyfit:RepeatedPointsOrRescale'));
end
A section of the code I am trying to run is pasted below. Line 48 is where I think the error is: [SlpBL2]=polyfit(Time_scale(300:T2), Force_trace(300:T2),1);
Reject the 1st 300 data points
BL1=min(Force_trace(300:end));
col='rcgy'
figure; set(gcf, 'windowstyle', 'docked', 'color', 'w')
for j=1:100
cla
Force_trace=Force_trace-BL1;
Peak1=max(Force_trace(300:end-30));
Extrapolation_point=Peak1*0.10;
D=Force_trace<Extrapolation_point;
T2=find(D,1,'last');
[SlpBL2]=polyfit(Time_scale(300:T2), Force_trace(300:T2),1);
Slope=SlpBL2(1);
BL2=SlpBL2(2);
plot(Time_scale, Force_trace)
hold on
plot([0, Time_scale(T2)], [BL2, Time_scale(T2)*Slope+BL2],col(1))
disp(['round number ' int2str(j) ' baseline is ' num2str(BL2)])
if abs(BL2)<1e-10
break
end
BL1=BL2;
drawnow
end
Thanks in advance for your help!

Code discussion
Since you are fitting a one-degree polynomial to data, passing less than two data points is the only reason that error would be thrown.
This will happen if T2 is always 300 or empty (meaning that D is all false.
Explanation
In order to exactly fit a polynomial of degree n, n+1 data points are required to uniquely determine the n+1 coefficients of the polynomial.
For example, a cubic has the form:
.
A cubic equation requires four points of data to uniquely determine the four coefficients.
With less than n+1 data points, an exact polynomial can not be created since, assuming there is an underlying function from which the data was drawn, there are an infinite number of solutions.
However, a polynomial whose coefficients form the smallest/shortest solution can readily be calculated; this is the least-squares solution.
This brief overview (section 2) gives a succinct overview of this and overdetermined solutions, which is more common in my experience.
Consider this input:
>> x = linspace(0,1,50);
>> y = x.^3 + x.^2;
>> p3 = polyfit(x([1,25,50]),y([1,25,50]),3);
Warning: Polynomial is not unique; degree >= number of data points.
> In polyfit at 70
>> p4 = polyfit(x([1,10,25,50]),y([1,10,25,50]),3);
and the plot here:
The undetermined solution follows the true function closely but not exactly.

Related

comparing generated data to measured data

we have measured data that we managed to determine the distribution type that it follows (Gamma) and its parameters (A,B)
And we generated n samples (10000) from the same distribution with the same parameters and in the same range (between 18.5 and 59) using for loop
for i=1:1:10000
tot=makedist('Gamma','A',11.8919,'B',2.9927);
tot= truncate(tot,18.5,59);
W(i,:) =random(tot,1,1);
end
Then we tried to fit the generated data using:
h1=histfit(W);
After this we tried to plot the Gamma curve to compare the two curves on the same figure uing:
hold on
h2=histfit(W,[],'Gamma');
h2(1).Visible='off';
The problem s the two curves are shifted as in the following figure "Figure 1 is the generated data from the previous code and Figure 2 is without truncating the generated data"
enter image description here
Any one knows why??
Thanks in advance
By default histfit fits a normal probability density function (PDF) on the histogram. I'm not sure what you were actually trying to do, but what you did is:
% fit a normal PDF
h1=histfit(W); % this is equal to h1 = histfit(W,[],'normal');
% fit a gamma PDF
h2=histfit(W,[],'Gamma');
Obviously that will result in different fits because a normal PDF != a gamma PDF. The only thing you see is that for the gamma PDF fits the curve better because you sampled the data from that distribution.
If you want to check whether the data follows a certain distribution you can also use a KS-test. In your case
% check if the data follows the distribution speccified in tot
[h p] = kstest(W,'CDF',tot)
If the data follows a gamma dist. then h = 0 and p > 0.05, else h = 1 and p < 0.05.
Now some general comments on your code:
Please look up preallocation of memory, it will speed up loops greatly. E.g.
W = zeros(10000,1);
for i=1:1:10000
tot=makedist('Gamma','A',11.8919,'B',2.9927);
tot= truncate(tot,18.5,59);
W(i,:) =random(tot,1,1);
end
Also,
tot=makedist('Gamma','A',11.8919,'B',2.9927);
tot= truncate(tot,18.5,59);
is not depending in the loop index and can therefore be moved in front of the loop to speed things up further. It is also good practice to avoid using i as loop variable.
But you can actually skip the whole loop because random() allows to return multiple samples at once:
tot=makedist('Gamma','A',11.8919,'B',2.9927);
tot= truncate(tot,18.5,59);
W =random(tot,10000,1);

Solving system of equations to gain desired step response

I need to obtain the values of a, b and c in the following equations so that the step response of the system matches that of the figure below.
x_dot = a*x + b+u;
y = c*x;
Where x_dot is the first derivative of x.
I have been trying to achieve this through Matlab and have so far achieved the following, using just arbitrary values for a, b and c for testing purposes:
clc;
close all;
clear all;
a=1;
b=2;
c=3;
tspan = [0:0.01:12];
x_dot = a*x+b*xu;
x = (a*x^2)/2 + b*u*x;
y = c*x;
f = #(t,x) [a*x(1)+b*x(2); c*x(1)];
[t, xa] = ode45(f,tspan,[0,0]);
plot(t,xa(:,1));
This certainly sounds like a parameter estimation problem as already hinted. You want to minimise the error between the outcome modelled using your ode and the values in your graph (fitting your three parameters a,b and c to the data).
A first step is to write an error function that takes the ode output values and compares how close it is to the data values (sum of least squares error for instance).
Then you have to search through a range of a,b,c values (which may be a large search space) and you pick the set of (a,b,c) which minimise your error function (i.e. get as close to your graph as possible).
Many search/optimisation strategies exist (.. e.g. genetic algorithm/etc.).
Please Note that the parameters are elements of real numbers(which includes negative values and extremely large or small values), the large search space is usually what makes these problems difficult to solve.
Also I think you have to be careful of initial conditions e.g. [0,0] doesn't seem to lead to interesting results. (try a = -0.5,b=0.2 and c=-0.00000001, with IC of [0,10] as below)
clc;
close all;
clear all;
a=-0.5;
b=0.2;
c=-0.00000001;
tspan = [0:0.01:12];
f = #(t,x) [a*x(1)+b*x(2); c*x(1)];
[t, xa] = ode45(f,tspan,[0,10]);
plot(t,xa);
hold on
plot(t,4)
Here 10 is the starting point of the green line and blue line starts at 0. What I would also note is that the IC change the results.. so there any many possible solutions for a,b,c given IC.
Looks interesting.. good luck.

MATLAB estimateUncalibratedRectification non-deterministic behavior

I have written the function below to perform image rectification. I am using just the standard MATLAB library functions (estimateUncalibratedRectification and estimateFundamentalMatrix) and my own wrapper function to MATLAB's matchFeatures to perform stereo rectification. Yet, with the same inputs I get different results every time. I know this is related to the use of RANSAC to estimate the fundamental matrix. However, the rectification is terrible sometimes and passable others. For example, over 10 different runs of my function with identical input, two results were okay, while 8 gave me variations on this error:
Warning: An epipole may be located inside of an image. The epipoles
are located at [285.8503,76.1656] in I1 and [265.5734,130.3931] in I2,
but the specified imageSize was [320,568]. Severe distortion may
result if T1 or T2 are used to transform these images. See
isEpipoleInImage for more information.
> In coder.internal.warning (line 7)
In cvalgEstimateUncalibratedRectification (line 114)
In estimateUncalibratedRectification (line 107)
In pairwiseTransformation (line 48)
I believe that this means that the rectification was unable to project the epipole to infinity.
What's going on here? It is worth noting that I have 279 putative matches and 32 inlierMatches between my images.
My function:
function [t1, t2] = pairwiseTransformation(img1, img2, features1, features2)
% Identify putative matches
[matches1, matches2] = matchFeaturePoints(rgb2gray(img1), features1, ...
rgb2gray(img2), features2);
% Estimate the fundamental matrix so that matches2' * F * matches1 = 0
% F transforms matches1 to a line that runs through the corresponding
% point in matches1. Therefore, any rotation and translation derived from F
% (and E) will apply to camera 2's relative position, holding camera 1 fixed.
[F, inliers] = estimateFundamentalMatrix(matches1, matches2, 'Method', 'RANSAC', ...
'NumTrials', 2000, 'DistanceThreshold', 1e-4);
% Use the RANSAC inliers to determine the relative position of img2 compared to img1
inlierMatches1 = matches1(inliers, :);
inlierMatches2 = matches2(inliers, :);
[t1, t2] = estimateUncalibratedRectification(F, inlierMatches1, inlierMatches2, ...
size(img1));
r1 = imwarp(img1, projective2d(t1), 'OutputView', imref2d(size(img1)));
r2 = imwarp(img2, projective2d(t2), 'OutputView', imref2d(size(img1)));
figure;
subplot(2,2,1),imshow(img1)
subplot(2,2,2),imshow(img2)
subplot(2,2,3),imshow(r1)
subplot(2,2,4),imshow(r2)
end
Here's a decent rectification (top row is original images, bottom is rectified):
And here's a totally botched effort that gave the epipole warning:
32 inlier matches seems too few... How do your putative matches look?
One thing to try is to tweak the parameters of estimateFundamentalMatrix. I would use MSAC instead of RANSAC, and increase the DistanceThreshold to something like .1 or even 1. At the same time you may want to increase the Confidence parameter, maybe to 99.99. That would force RANSAC to go through more trials, and increase your chances of finding the right solution.
The other thing to try is to get more and better putative matches from matchFeatures. You should try tweaking the parameters of your feature detector function to get more features, and then tweak the parameters of matchFeatures to make sure that the matches are still good. You can also try different detectors and descriptors.

How can I use of norm(a,b) in matlab if a, b are double type?

I must to use angle = atan2(norm(cross(a,b)),dot(a,b)), for calculating the angle between two vectors a,b and these are double type and norm is undefined for this type. How do I resolve this problem? I need to calculate the angle between two vectors this way.
In your comments, you have shown us how you are actually writing out the angle calculation and it is not the same as how you have put it in your post.
atan2(norm(cross(I(i,j,:),I_avg)),dot(I(i,j,:),I_avg));
I is an image you are loading in. I'm assuming it's colour because of the way you are subsetting I. Because I is a 3D matrix, doing I(i,j,:) will give you a 1 x 1 x 3 vector when in fact this has to be a 1D vector. norm does not recognize this structure which is why you're getting this error. Therefore, you need to use squeeze to remove the singleton dimensions so that this will become a 3 x 1 vector, rather than a 1 x 1 x 3 vector. As such, you need to rewrite your code so that you're doing this instead. Bear in mind that in your comments, angle is always overwritten inside the for loop, so you probably want to save the results of each pixel. With this, you probably want to create a 2D array of angles that will store these results. In other words:
I=imread('thesis.jpg');
I = double(I);
angles = zeros(m,n);
I_avg = squeeze(I_avg); %// Just in case
for i=1:m
for j=1:n
pixels = squeeze(I(i,j,:)); %// Add this statement and squeeze
angles(i,j) = atan2(norm(pixels,I_avg)),dot(pixels,I_avg)); %// Change
end
end
Minor note
MATLAB has a built-in function called angle that determines the angle from the origin to a complex number in the complex plane. It is not recommended you call your variable angle as this will unintentionally shadow over the angle function, and any other code that you create from this point onwards may rely on that actual angle function, and you will get unintended results.
Another minor note
Using i and j as loop variables is not recommended. These letters are reserved for the complex number, and this can produce unintentional results. Take a look at this question and post by Shai here - Using i and j as variables in Matlab. As such, it is suggested you use other variable names instead.
As #rayryeng has successfully answered this question, I would like to turn my post into a more general one by sharing my experience in debugging in Matlab. I hope anyone who somehow managed to find this post get more or less thinking about the habits a good programmer should have.
The question goes like: "How would I do if I get errors?"
Here's an excellent article by Eric in which he lists the rule-of-thumbs when you encounter a bug and wish to get rid of it. It's originally been cited by Stackoverflow, and that's the reason I read it.
If you still get no clue / idea how you can play with your code, see how this person does:
Pin-point the buggy line
(The number should start with 0) Make sure before running a script, you clear out any previously stored variables, including the notorious i and j's (you should never see them in any workspace). If any one is needed for the buggy code to run, save('buggy.mat','importantvar') before clear and load('buggy.mat') after clear.
By doing so, you can isolate your buggy code from anything else, which could have bad influences. For example, in a previously called script, there is a line
double = [2,4,6]; % you should never name a variable `double`
and in the next script, you have
>> e = str2num('uint8(200)')
e =
200
>> double(e)
Index exceeds matrix dimensions.
>>
>> f = single(2.36)
f =
2.3600
>> double(f)
Subscript indices must either be real positive integers or
logicals.
>>
The reason is double is no longer an inbuild function, but a user-defined variable. Too bad to pick up a name carelessly!
....anyway, let's clear the workspace and get rid of double.
>> clear
Read the error message, thoroughly.
Now let's begin with OP's problem. The original code (trimmed) goes like this -
img = imread('peppers.png');
a = img(300,200,:);
b = img(200,300,:);
d = norm(cross(a,b));
.... hence the error
Undefined function 'norm' for input arguments of type 'uint8'.
Error in untitled (line 6)
d = norm(cross(a,b));
Most beginners are only interested in the first line of the error message, which by it alone usually doesn't provide any useful help, or only in the red color, which leads to the famous question "my code does not work!"
But think twice. You still have another 2 lines unread! Error in untitled (line 6) says I'm running a script named untitled and the (first) error lies in line 6, and the code in that line is d = norm(cross(a,b));.
Now, at least you know a little more about your code - "My code d = norm(cross(a,b)); doesn't work!"
Although most likely we may also vote this kind of question to get closed, it's still much much better than a simply "It does not work!".
Now we can pin-point the buggy line
try
% this line will raise an error
d = norm(cross(a,b));
catch err
disp(err.message)
end
Look into the functions
First, make sure the inner function cross works as expected -
>> cross(a,b)
ans(:,:,1) =
0
ans(:,:,2) =
255
ans(:,:,3) =
0
>>
Good. So now we can even narrow down the error to the outer norm.
One more thing to mention. You can always find Mathworks' documentation for any in-build function, by typing "matlab function", such as "matlab norm" in Google (or any other search engine) and clicking on the first result. If you prefer, you can also type in Matlab command window doc _function_ such as doc norm and read the doc in Matlab. It's of course a pleasure of us on Stackoverflow to give you the reference by doing the same thing, but it takes a longer time because a human is, in this aspect, always slower than a search engine.
The error reads Undefined function 'norm' for input arguments of type 'uint8'.. So the input for norm should not be uint8, unsigned 8-bit integer. But what should it be?
% why `norm` "does not work"?
% this line runs perfectly well
norm(cross([1,2,3], [4,5,6]))
% so what is working?
class([1,2,3]) % so `norm` works for `double`
One thing we can do now is convert a and b to double precision. Let's try it now.
% try fixing 'uint8' error
a2 = double(a);
b2 = double(b);
whos a b % now they are double, which `norm` should work for
try
% this line will raise an error
d = norm(cross(a2,b2));
catch err
disp(err.message)
end
Now the error becomes Input must be 2-D.. What's wrong with the input?
% what is "must be 2-D" error?
size(a2) % a2 is 3-D
disp(b2) % b2 is also 3-D
This gives output in command window
ans =
1 1 3
(:,:,1) =
255
(:,:,2) =
150
(:,:,3) =
0
In OP's problem, he/she is trying to calculate something about color difference (to the best of my knowledge) which involves the angle between two color vectors in RGB space. So the vectors are needed. With imread, each pixel of the image is stored as 3 elements in the matrix, first 2 dimension being its physical position, the 3 dimension being RGB channel components. Hence pixel(200,300) with color rgb[255,150,0] is stored by us in variable b wihch is a 3-D vector.
By understanding what we need and what Matlab can do, we can combine these two points into one. We need the norm of the cross product of a and b, while the useful information (the 3 component values) is stored in the 3rd dimension. Matlab can calculate the norm of the cross product of a vector with all its information in the 1st dimension. (Here, "dimension" refers to that of the Matlab variable; a vector with 3 elements in its 1st dimension is physically a 3-D vector).
After thinking twice, we are now able to debug our code - just put all 3 elements into the 1st dimension.
% so we want the 3 elements in the 3rd dimension become in the 1st dim
a3 = squeeze(a2);
b3 = reshape(b2,numel(b2),[]);
try
d = norm(cross(a3,b3));
catch err
disp(err.message)
end
d
Bonus: If by default Matlab treats a 3-D vector as a "1-D array", then most probably the cross function has not been working correctly. Let's make a check -
>> clear
>> a = [1,2,3]
a =
1 2 3
>> b=[4,5,6]
b =
4 5 6
>> cross(a,b)
ans =
-3 6 -3
>>
The result should be the same as the one we can get by calculating by hand.
Now if we put the components into the 3rd dimension of the variable -
>> clear
>> a(1,1,:)=[1,2,3]
a(:,:,1) =
1
a(:,:,2) =
2
a(:,:,3) =
3
>> b(1,1,:)=[4,5,6]
b(:,:,1) =
4
b(:,:,2) =
5
b(:,:,3) =
6
>> cross(a,b)
ans(:,:,1) =
-3
ans(:,:,2) =
6
ans(:,:,3) =
-3
>>
.... seems OK. cross also puts the result in the 3rd dimension. In fact, Mathworks' documentation says
If A and B are vectors, then they must have a length of 3.
If A and B are matrices or multidimensional arrays, then they must
have the same size. In this case, the cross function treats A and B as
collections of three-element vectors. The function calculates the
cross product of corresponding vectors along the first array dimension
whose size equals 3.
At last, one thing is always correct to anyone who wants to do something with programming - be cautious and prudent when writing your code.

Matlab, on the quest to find a simple way to control the output of a function

I have already asked a similar question here, I will try this time to be a lot more elaborate in consideration that what puzzles me the most about Matlab still is how to handle/control output as in plotting/listing.
I have the following function
function e = calcEulerSum2(n)
for i=1:n % step size still one, although left blank
e = 1;
e = e + sum(1./factorial(1:n)); % computes a vector of length n and takes
end % the factorial of its entries, then piecewise division
end
To approximate e using the Taylor Summation method. I am now asked to compute the absolute error using
abserror(n):=abs(calcEulerSum2(n)-exp(1))
for values of n= 10^0,10^1,...,10^16.
My idea was to make the above function sensitive for vector input (if you call it like that, I have read vectorization on here as well). I thought this would be the best thing I could do, because I obviously want to evaluate the above function for a couple of values of n and then maybe plot the result in a graph to see the results.
However, I believe that my understanding of MATLAB is too rudimentary as of now to find a simple solution to that problem.
Additional: With the help of this website I already managed to solve a similar problem, using a recursive definition of e to get a vector output for each successful iteration using:
function e = calcEulerSum3(n)
for i = n % here the idea is to let n be a continuous vector
e(1)=1; % base case
e(i+1)=e(i)+1/factorial(i); % recursive definition to approx e
end
This function now understands vector input, but only if the vector is what I would call continuous on the integer line, for example n'=[ 1 2 3 4 5 ] and so on to make the recursive iteration through a vector work. This time however, my vector n as above would destroy this concept.
Question(s):
Are there simple ways to handle the above output abserror(n) ?, because I have a feeling that I am overachieving by trying to vectorize my functions
Update: As suggested by #vish the following function does a much better job for my purpose:
function e = calcEulerSum2(n) %Updated
for i=1:n % step size still one, although left blank
e = 1;
e = e + cumsum(1./factorial(1:n)); % computes a vector of length n and takes
end % the factorial of its entries, then piecewise division
end
the output of this program for n=3 would be
calcEulerSum2(3)
ans =
2.0000 2.5000 2.6667
This is great and indeed what I am looking for, but lets say I want to plot the absolute error now for several values of n, for the sake of the argument I will choose smaller values (because I understand that 10^16! is really blunt to input), but still many. So if I decide I want to print out the absolute error abserror(n) for the following values of n
n = [1 4 9 11 17 18 19 22 27 29 31 33 ]
how would I do that?
Not sure you are computing what you think you are computing.
The for loop is totally not needed since you keep overwriting e at every iteration and you only return the last one.
factorial(1:3) == [1,2,6]
then you sum the reciprocals.
The first iteration of the loop factorial(1:1) goes nowhere.
Try
cumsum(1./factorial(1:7))
l think that's what you wanted
Edit: , factorial(10^5) is too big to be meaningful, i think going from 1 to n=16 will give you good enough results. (not 10^16)
2nd edit
run this
N=0:16;
res = exp(1) - cumsum(1./factorial(N))
see what happens
you can also plot it on a log scale.
semilogy(res)