Basic Signal Plotting - matlab

I have run it for the whole day and the error keeps on happening the prompt says "vector lengths must match" below is my code. What seems to be the problem?
fs=8000;
t=0:1/fs:3;
z1=e.^(-t);
figure(1)
subplot(211)
plot(t,z1)
axis([0 3 -1 1])
hold on
z2=sin(10*pi*t);
subplot(211)
plot(t,z2)
axis([0 3 -1 1])
z3=(e.^(-t)).*(sin(10*pi*t));
subplot(212)
plot(t1,z3)
axis([0 3 -1 1])

I'm writing this as an answer rather than a comment because you can't paste images into comments. I just ran your code in Octave exactly as you listed it except for line 15 (penultimate line) where I changed plot(t1,z3) to plot(t,z3), as suggested by #josSan, since t1 is not defined and the formula for z3 suggests that it is a function of t. It spat out the following with no errors:
It looks like your code is correct, at least if run in Octave. I don't have Matlab so I couldn't try it in that, but as #josSan points out, Matlab doesn't have built-in constants so your use of e would give an error, though it would be something like 'e' undefined near line 3 rather than mismatching vector lengths. However, it would probably be more efficient and accurate to use exp(-t) instead of e.^(-t) whichever application you are using.

Related

Matlab error message regarding use of polyfit function in script file

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.

Using Euler's Method in Matlab

First time post here. Pretty frustrated right now working on this assignment for class.
Basically, the idea is to use Euler's method to simulate and graph an equation of motion. The equation of motion is in the form of an ODE.
My professor has already put down some code for slightly similar system and would like us to derive the equation of motion using Lagrange. I believe that I have derived the EOM correctly, however I am running into problems on the Matlab side of things.
What's weird is that using a similar technique on another, seperate EOM, I have no issues. So I am unsure what I am doing wrong.
Here's the code for the part that is working correctly:
close all; clear all; clc;
% System parameters
w = 2*pi;
c = 0.02;
% Time vectors
dt = 1e-5;
t = 0:dt:4;
theta = zeros(size(t));
thetadot = zeros(size(t));
% Initial conditions
theta(1)=pi/2; %theta(0)
thetadot(1)=0; %thetadot(0)
for I = 1 : length(t)-1;
thetaddot = -c*thetadot(I)-w^2*sin(theta(I));
thetadot(I+1)=thetadot(I)+thetaddot*dt;
theta(I+1)=theta(I)+thetadot(I)*dt ;
end
figure(1);
plot(t,theta,'b');
xlabel('time(s)');
ylabel('theta');
title('Figure 1');
zoom on;
% Output the plot to a pdf file, and make it 6 inches by 4 inches
printFigureToPdf('fig1.pdf', [6,4],'in');
% Open the pdf for viewing
open fig1.pdf
Everything runs fine, except Matlab complains about the printFigureToPdf command.
Now, here is the code for the problem that I am having issues with.
close all; clear all; clc; clf
% System parameters
m=0.2;
g=9.81;
c=.2;
d=0.075;
L=0.001; %L is used for Gamma
B=0.001; %B is used for Beta
W=210*pi; %W is used for Omega
%Time vectors
dt = 1e-6; %Time Step
t=0:dt:10; %Range of times that simulation goes through
x=zeros(size(t));
xdot=zeros(size(t));
%Initialconditions
x(1)=0;%x(0)
xdot(1)=0; %xdot(0)
for I = 1 : length(t)-1;
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x-L*W*sin(W*t)).^(-4)-(d-x-L*W*sin(W*t)).^(-4)));
xdot(I+1)=xdot(I)+xddot*dt;
x(I+1)=x(I)+xdot(I+1)*dt ;
end
figure(1);
plot(t,x,'b');
xlabel('time(s)');
ylabel('distance(m)');
title('Figure 2');
zoom on;
% Output the plot to a pdf file, and make it 6 inches by 4 inches
printFigureToPdf('fig1.pdf', [6,4],'in');
% Open the pdf for viewing
open fig1.pdf
With this code, I followed the same procedure and is giving an error on line 23: "In an assignment A(I) = B, the number of elements in B and I must be the same."
Like I said, I am confused because the other code worked okay, and this second set of code gives an error.
If anyone could give me a hand with this, I would greatly appreciate it.
Thanks in advance,
Dave
Edit: As suggested, I changed x(I+1)=x(I)+xdot(I+1)*dt to x(I+1)=x(I)+xdot(I)*dt. However, I am still getting an error for line 23: "In an assignment A(I) = B, the number of elements in B and I must be the same."
Line 23 is: xdot(I+1)=xdot(I)+xddot*dt;
So, I tried adjusting the code as suggested for the other line to xdot(I+1)=xdot(I)+xddot(I)*dt;
After making this change, Matlab gets stuck, I tried letting it run for a few minutes but won't execute. I ended up having to close and reopen the application.
The error In an assignment A(I) = B, the number of elements in B and I must be the same. is something you should understand because it may pop up frequently in Matlab if you are not careful.
In your case, you are trying to assign 1 element value xdot(I+1) with something which has more than 1 element xdot(I)+xddot*dt.
Indeed, if you step through the code line by line and observe your workspace, you will notice that xddot is not a scalar value as intended, but a full blown vector the size of t. This is because in the precedent line where you define xddot:
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x-L*W*sin(W*t)).^(-4)-(d-x-L*W*sin(W*t)).^(-4)));
you still have many references to x (full vector) and t (full vector). You have to replace all these references to full vectors to only one index of them, i.e use x(I) and t(I). The line becomes:
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x(I)-L*W*sin(W*t(I))).^(-4)-(d-x(I)-L*W*sin(W*t(I))).^(-4)));
With that your code runs just fine. However, it is far from optimized and it runs relatively slow. I have a powerful machine and it still takes a long time to run for me. I suggest you reduce your time step to something more sensible, at least when you are still trying your code. If you really need that kind of precision, first make sure your code runs fine then when it is ready let it run at full precision and go have a coffee while your computer is doing the work.
The snippet below is the loop part of your code with the correct assignment for xddot. I also added a simple progress bar so you can see that your code is doing something.
hw = waitbar(0,'Please wait...') ;
npt = length(t)-1 ;
for I = 1 : npt
xddot =-1/m*(c*xdot(I)-c*L*W*cos(W)+m*g-3*B*((d+x(I)-L*W*sin(W*t(I))).^(-4)-(d-x(I)-L*W*sin(W*t(I))).^(-4)));
xdot(I+1) = xdot(I)+xddot*dt;
x(I+1) = x(I)+xdot(I+1)*dt ;
pcdone = I / npt ;
waitbar(pcdone,hw,[num2str(pcdone*100,'%5.2f') '% done'])
end
close(hw)
I strongly suggest you reduce your time step to dt = 1e-3; until you are satisfied with everything else.
In the final version, you can remove or comment the calls to the waitbar as it slows down things too.

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.

Incorrect Square Wave Plot

I'm embarrassed to ask this as I believe I may be missing something obvious, but I just can't see where I am going wrong. As part of a larger program I am investigating the application of discretisation methods to approximate the convection equation on a square wave. However, I have noticed that in some cases the bounds of my square wave are being incorrectly applied. It should have the initial conditions of 1 when 10.25<=X<=10.5 and 0 everywhere else. This is an example of the issue:
L=20; %domain length
dx=0.01; %space step
nx=(L/dx); %number of steps in space
x=0:dx:(nx-1)*dx; %steps along x
sqr=zeros(1,nx); %pre-allocate array space
for j=1:nx
if ((10.25<=x(j))&&(x(j)<=10.5))
sqr(j)=1;
else
sqr(j)=0;
end
d=plot(x,sqr,'r','LineWidth',2); axis([10.1 10.6 0 1.1]);
drawnow;
In this case, the wave displays incorrectly, with x=10.5 taking a value of 0 and not 1, like so:
https://dl.dropboxusercontent.com/u/8037738/project/square_wave.png
The weird thing is that if I change the domain length to a different value it sometimes displays correctly. This is when the domain length is set to 30 and it displays correctly:
https://dl.dropboxusercontent.com/u/8037738/project/square_wave_correct.png
I really don't understand because my x array is always discretised in 0.01 intervals, so it will never 'miss' 10.5 when it loops through. I hope I have explained this problem adequately enough and if it is a stupid mistake on my part I apologise in advance.
You forgot the end when you finish with the if
L=20; %domain length
dx=0.01; %space step
nx=(L/dx); %number of steps in space
x=0:dx:(nx-1)*dx; %steps along x
sqr=zeros(1,nx); %pre-allocate array space
eps = 1.e-8;
for j=1:nx
if ((10.25-eps<=x(j))&&(x(j)<=10.5+eps))
sqr(j)=1;
else
sqr(j)=0;
end
end
d=plot(x,sqr,'r','LineWidth',2); axis([10.1 10.6 0 1.1]);
drawnow;
I also recomend you to use a small tolerance when using comparisons with float values, like the x(j)<=10.5
if you se the difference at that point, matlab tell you
x(1051)-10.5
ans =
1.776356839400250e-15
so because of the round-off the value of x(j) was lightly larger that 10.5, not equal as you were expecting
Your issue is that the x values do not fall exactly on the space step. For example, if you look at the following:
j=1051;
format long;
x(j)
ans =
10.500000000000002
The answer from sebas fixes this issue by adding the tolerance to each of the bounds. You could also try rounding x(j) to the nearest 100th before performing the logic in the if statement:
roundn(x(j), -2)

Issue in mean square error plot

There are 2 column vectors A,B containing 100 data values. I intend to plot the MSE(mean square error ) using the following code but all I get is a single dot instead of a line plot. Please help how to go about it.
A=x(:,1);
B=y(:,1);
er=(double(A)-double(B)).^2;
row_er=mean(er,2); % variable changed
plot(row_er);
This script works fine.
A = randn(10, 1);
B = randn(10, 1);
er=(double(A)-double(B)).^2;
row_e=mean(er,2);
plot(row_e)
Probably you have a typo (row_er)
row_e=mean(er,2);
plot(row_er);
Please notice that the command mean returns the mean of a vector (which is one simple value). If you want to plot plot the square error then you just plot((A-B).^2).
But... If you are interested in plotting the mean square error with, say, 10 samples average, you will have a plot with only 10 points (100 / 10 because each 10 data points are averaged to give you one point).
The command would be
plot(blkproc((A-B).^2,[10,1],'mean'))
hope it helps.