I'm a bit confused about the angle() function in Matlab, in particular when applied to an array of real numbers.
The angle() function should give me the phase of a complex number. Example: y = a + bi, ==> phase = arctan(b/a). Indeed, the following works:
for t=1:1000
comp(t) = exp(1i*(t/10));
end
phase_good_comp1 = unwrap(angle(comp)); %this gives me the right answer
b = imag(comp);
a = real(comp);
phase_good_comp2 = atan(b./a); %this gives me the right answer too, but
wrapped (not sure if there is a way to unwrap this, but unwrap() does not
work)
figure(1)
plot(phase_good_comp1)
hold on
plot(phase_good_comp2,'--r')
legend('good phase1', 'good phase2')
title('complex number')
Here's the plot for the complex numbers --
Note that I can use either the angle() function, or the explicit definition of phase, as I have shown above. Both yield good results (I can't unwrap the latter, but that's not my issue).
Now if I apply the same logic to an array of real numbers, I should get a constant phase everywhere, since no imaginary part exists, so arctan(b/a) = arctan(0) = 0. This works if I use the explicit definition of phase, but I get a weird result if I use angle():
for t=1:1000
ree(t) = cos((t/10));
end
phase_bad_re = unwrap(angle(ree)); %this gives me an unreasonable (?) answer
b = imag(ree);
a = real(ree);
phase_good_re = atan(b./a); %this gives me the right answer
figure(1)
plot(phase_bad_re)
hold on
plot(phase_good_re,'--r')
legend('bad phase', 'good phase')
title('real number')
Here's the plot for the real numbers --
Why the oscillation when I use angle()???
The Matlab documentation tells you how to compute this:
The angle function can be expressed as angle(z) = imag(log(z)) = atan2(imag(z),real(z)).
https://www.mathworks.com/help/matlab/ref/angle.html
Note that they define it with atan2 instead of atan.
Now your data is in the range of cosine, which includes both positive and negative numbers. The angle on the positive numbers should be 0 and the angle on the negative numbers should be an odd-integer multiple of pi in general. Using the specific definition that they've chosen to get a unique answer, it is pi. That's what you got. (Actually, for the positive numbers, any even-integer multiple of pi will do, but 0 is the "natural" choice and the one that you get from atan2.)
If you're not clear why the negative numbers don't have angle = 0, plot it out in the complex plane and keep in mind that the radial part of the complex number is positive by definition. That is z = r * exp(i*theta) for positive r and theta given by this angle you're computing.
Since sign of cosine function is periodically changed, angle() is also oscillated.
Please, try this.
a=angle(1);
b=angle(-1);
Phase of 1+i*0 is 0, while phase of -1+i*0 is 3.14.
But, in case of atan, b/a is always 0, so that the result of atan() is all 0.
Related
Background: I am working on a problem similar to the nonlinear logistic regression described in the link [1] (my problem is more complicated, but link [1] is enough for the next sections of this post). Comparing my results with those obtained in parallel with a R package, I got similar results for the coefficients, but (very approximately) an opposite logLikelihood.
Hypothesis: The logLikelihood given by fitnlm in Matlab is in fact the negative LogLikelihood. (Note that this impairs consequently the BIC and AIC computation by Matlab)
Reasonning: in [1], the same problem is solved through two different approaches. ML-approach/ By defining the negative LogLikelihood and making an optimization with fminsearch. GLS-approach/ By using fitnlm.
The negative LogLikelihood after the ML-approach is:380
The negative LogLikelihood after the GLS-approach is:-406
I imagine the second one should be at least multiplied by (-1)?
Questions: Did I miss something? Is the (-1) coefficient enough, or would this simple correction not be enough?
Self-contained code:
%copy-pasting code from [1]
myf = #(beta,x) beta(1)*x./(beta(2) + x);
mymodelfun = #(beta,x) 1./(1 + exp(-myf(beta,x)));
rng(300,'twister');
x = linspace(-1,1,200)';
beta = [10;2];
beta0=[3;3];
mu = mymodelfun(beta,x);
n = 50;
z = binornd(n,mu);
y = z./n;
%ML Approach
mynegloglik = #(beta) -sum(log(binopdf(z,n,mymodelfun(beta,x))));
opts = optimset('fminsearch');
opts.MaxFunEvals = Inf;
opts.MaxIter = 10000;
betaHatML = fminsearch(mynegloglik,beta0,opts)
neglogLH_MLApproach = mynegloglik(betaHatML);
%GLS Approach
wfun = #(xx) n./(xx.*(1-xx));
nlm = fitnlm(x,y,mymodelfun,beta0,'Weights',wfun)
neglogLH_GLSApproach = - nlm.LogLikelihood;
Source:
[1] https://uk.mathworks.com/help/stats/examples/nonlinear-logistic-regression.html
This answer (now) only details which code is used. Please see Tom Lane's answer below for a substantive answer.
Basically, fitnlm.m is a call to NonLinearModel.fit.
When opening NonLinearModel.m, one gets in line 1209:
model.LogLikelihood = getlogLikelihood(model);
getlogLikelihood is itself described between lines 1234-1251.
For instance:
function L = getlogLikelihood(model)
(...)
L = -(model.DFE + model.NumObservations*log(2*pi) + (...) )/2;
(...)
Please also not that this notably impacts ModelCriterion.AIC and ModelCriterion.BIC, as they are computed using model.LogLikelihood ("thinking" it is the logLikelihood).
To get the corresponding formula for BIC/AIC/..., type:
edit classreg.regr.modelutils.modelcriterion
this is Tom from MathWorks. Take another look at the formula quoted:
L = -(model.DFE + model.NumObservations*log(2*pi) + (...) )/2;
Remember the normal distribution has a factor (1/sqrt(2*pi)), so taking logs of that gives us -log(2*pi)/2. So the minus sign comes from that and it is part of the log likelihood. The property value is not the negative log likelihood.
One reason for the difference in the two log likelihood values is that the "ML approach" value is computing something based on the discrete probabilities from the binomial distribution. Those are all between 0 and 1, and they add up to 1. The "GLS approach" is computing something based on the probability density of the continuous normal distribution. In this example, the standard deviation of the residuals is about 0.0462. That leads to density values that are much higher than 1 at the peak. So the two things are not really comparable. You would need to convert the normal values to probabilities on the same discrete intervals that correspond to individual outcomes from the binomial distribution.
i am solving a mathematical problem and i can't continue do to the error.
I tried all constant with sin^2(x) yet its the same.
clear
clc
t = 1:0.5:10;
theta = linspace(0,pi,19);
x = 2*sin(theta)
y = sin^2*(theta)*(t/4)
Error using sin
Not enough input arguments.
Error in lab2t114 (line 9)
y = sin^2*(theta)*(t/4)
sin is a function so it should be called as sin(value) which in this case is sin(theta) It may help to consider writing everything in intermediate steps:
temp = sin(theta);
y = temp.^2 ...
Once this is done you can always insert lines from previous calculations into the next line, inserting parentheses to ensure order of operations doesn't mess things up. Note in this case you don't really need the parentheses.
y = (sin(theta)).^2;
Finally, Matlab has matrix wise and element wise operations. The element wise operations start with a period '.' In Matlab you can look at, for example, help .* (element wise multiplication) and help * matrix wise calculation. For a scalar, like 2 in your example, this distinction doesn't matter. However for calculating y you need element-wise operations since theta and t are vectors (and in this case you are not looking to do matrix multiplication - I think ...)
t = 1:0.5:10;
theta = linspace(0,pi,19);
x = 2*sin(theta) %times scalar so no .* needed
sin_theta = sin(theta);
sin_theta_squared = sin_theta.^2; %element wise squaring needed since sin_theta is a vector
t_4 = t/4; %divide by scalar, this doesn't need a period
y = sin_theta_squared.*t_4; %element wise multiplication since both variables are arrays
OR
y = sin(theta).^2.*(t/4);
Also note these intermediate variables are largely for learning purposes. It is best not to write actual code like this since, in this case, the last line is a lot cleaner.
EDIT: Brief note, if you fix the sin(theta) error but not the .^ or .* errors, you would get some error like "Error using * Inner matrix dimensions must agree." - this is generally an indication that you forgot to use the element-wise operators
Can anybody help me with this assignment please?
I am new to matlab, and passing this year depends on this assignment, i don't have much time to explore matlab and i already wasted alot of time trying to do this assignment in my way.
I have already wrote the equations on the paper, but transfering the equations into matlab codes is really hard for me.
All i have for now is:
syms h
l = (0.75-h.^2)/(3*sqrt((5*h.^2)/4)); %h is h_max
V_default = (h.^2/2)*l;
dv = diff(V_default); %it's max. when the derivative is max.
h1 = solve( dv ==0);
h_max = (h1>0);
l_max = (0.75-h_max.^2)/(3*sqrt((h_max/2).^2+(h_max.^2)));
V_max = ((h_max.^2)./(2.*l_max));
but it keep give me error "Error using ./
Matrix dimensions must agree.
Error in triangle (line 9)
V_max = ((h_max.^2)./(2.*l_max)); "
Not really helping with the assignment here, but with the Matlab syntax. In the following line:
l_max = (0.75-h_max.^2)/(3*sqrt((h_max/2).^2+(h_max.^2)));
you're using / that is a matrix divide. You might want to use ./ which will divide the terms element by element. If I do this
l_max = (0.75-h_max.^2) ./ (3*sqrt((h_max/2).^2+(h_max.^2)));
then your code doesn't return any error. But I have no idea if it's the correct solution of your assignment, I'll leave that to you!
In line 5, the result h1 is a vector of two values but the variable itself remains symbolic, from the Symbolic Math Toolbox. MATLAB treats such variables slightly different. For that reason, the line h_max = (h1>0) doesn't really do what you expect. As I think from this point, you are interested in one value h_max, I would convert h1 to a regular MATLAB variable and change your code to the following:
h1 = double(solve( dv ==0)); % converts symbolic to regular vectors
h_max = h1(h1>0); % filters out all negative and zero values
l_max = (0.75-h_max.^2)/(3*sqrt((h_max/2).^2+(h_max.^2)));
V_max = ((h_max.^2)./(2.*l_max));
EDIT.
If you still have error, it means solve( ...) returns more than 1 positive values. In this case, as suggested, use dotted operations, such as ./ but the results in l_max and V_max will not be a single value but vectors of the same size as h_max. Which means you don't have one max Volume.
I do not know what this error means or how to fix it. I am trying to perform an image rotation in a separate space of coordinates. When defining the reference space of the matrix to be at zero, I am getting the error that integers can only be comibined with integers of the same class or scalar doubles. the line is
WZcentered = WZ - [x0;yo]*ones(1,Ncols);
WZ is classified as a 400x299x3 unit 8, in the workspace. It is an image. x0 and y0 are set to 0 when the function is called. How can I fix this issue/what exactly is happening here?
Also, when I do the same thing yet make WZ to be equal to double(WZ) I get the error that 'matrix dimensions must agree.' I am not sure what the double function does however. Here is the whole code.
function [out_flag, WZout, x_final, y_final] = adopted_moveWZ(WZ, x0, y0);
%Initial Test of plot
[Nrows,Ncols]=size(WZ);
if Nrows ~= 2
if Ncols ==2
WZ=transpose(WZ); %take transpose
[Nrows,Ncols]=size(WZ); %reset the number of rows and columns
else
fprintf('ERROR: Input file should have 2-vectors for the input points.\n');
end
end
plot(WZ(1,:),WZ(2,:),'.')
title('These are the original points in the image');
pause(2.0)
%WZorig = WZ;
%centering
WZcentered = WZ - ([x0;y0] * ones(1,Ncols));
FigScale=400;
axis([-FigScale 2*FigScale -FigScale 2*FigScale])
disp('Hit any key to start the animation');
pause;
SceneCenter = zeros(Nrows,Ncols);
WZnew = WZcentered;
for ii=0:20
%rotate
R = [cos(pi/ii) -sin(pi/ii) 0; sin(pi/ii) cos(pi/ii) 0; 0 0 1];
WZnew = R * WZnew;
plot(WZnew(1,:),WZnew(2,:),'.')
%place WZnew at a different place in the scene
SceneCenter = (ii*[30;40])*ones(1,Ncols);
plot(SceneCenter(1,:) + WZnew(1,:), SceneCenter(2,:) + WZnew(2,:),'.')
axis([-FigScale 2*FigScale -FigScale 2*FigScale])
pause(1.0);
end
%Set final values for output at end of program
x_final = SceneCenter(1,1);
y_final = SceneCenter(2,1);
PPout = PPnew + SceneCenter;
This happens due to WZ and ([x0;y0] * ones(1,Ncols)) being of different data types. You might think MATLAB is loosely typed, and hence should do the right thing when you have a floating point type operated with an integer type, but this rule breaks every once in a while. A simpler example to demonstrate this is here:
X = uint8(magic(5))
Y = zeros(5)
X - Y
This breaks with the same error that you are reporting. One way to fix this is to force cast one of the operands to the other, typically up-casted to make sure the math works. When you do this, both the numbers you are working on are floating point (double precision), and so they are represented in the same byte formatting sequence in memory. This way, the '-' sign is valid, in the same way that you can say 3 apples + 4 apples = 7 apples, but 3 oranges (uint8) + 4 apples (double) = ?. The double(X) makes it clear that you really mean to use double precision arithmetic, and hence fixes the error. This is how it looks now:
double(X) - Y
After having identified this, the new error is 'matrix dimensions do not match'. This means exactly what it says. WZ is a 400x299x3 matrix, and the right hand side matrix is 2xnCols. Now can you subtract a 2D matrix from a 3D matrix of different sizes meaningfully?
Depending on what your code is really intending to do, you can pad the RHS matrix, or find out other ways to make the sizes equal.
All of this is why MATLAB includes routines to do image rotation, namely http://www.mathworks.com/help/images/ref/imrotate.html . This is part of the Image Processing Toolbox, though.
I am having a hard time understanding what should be a simple concept. I have constructed a vector in MATLAB that is real and symmetric. When I take the FFT in MATLAB, the result has a significant imaginary component, even though the symmetry rules of the Fourier transform say that the FT of a real symmetric function should also be real and symmetric. My example code:
N = 1 + 2^8;
k = linspace(-1,1,N);
V = exp(-abs(k));
Vf1 = fft(fftshift(V));
Vf2 = fft(ifftshift(V));
Vf3 = ifft(fftshift(V));
Vf4 = ifft(ifftshift(V));
Vf5 = fft(V);
Vf6 = ifft(V);
disp([isreal(Vf1) isreal(Vf2) isreal(Vf3) isreal(Vf4) isreal(Vf5) isreal(Vf6)])
Result:
0 0 0 0 0 0
No combinations of (i)fft or (i)fftshift result in a real symmetric vector. I've tried with both even and odd N (N = 2^8 vs. N = 1+2^8).
I did try looking at k+flip(k) and there are some residuals on the order of eps(1), but the residuals are also symmetric and the imaginary part of the FFT is not coming out as fuzz on the order of eps(1), but rather with magnitude comparable to the real part.
What blindingly obvious thing am I missing?
Blindingly obvious thing I was missing:
The FFT is not an integral over all space, so it assumes a periodic signal. Above, I am duplicating the last point in the period when I choose an even N, and so there is no way to shift it around to put the zero frequency at the beginning without fractional indexing, which does not exist.
A word about my choice of k. It is not arbitrary. The actual problem I am trying to solve is to generate a model FTIR interferogram which I will then FFT to get a spectrum. k is the distance that the interferometer travels which gets transformed to frequency in wavenumbers. In the real problem there will be various scaling factors so that the generating function V will yield physically meaningful numbers.
It's
Vf = fftshift(fft(ifftshift(V)));
That is, you need ifftshift in time-domain so that samples are interpreted as those of a symmetric function, and then fftshift in frequency-domain to again make symmetry apparent.
This only works for N odd. For N even, the concept of a symmetric function does not make sense: there is no way to shift the signal so that it is symmetric with respect to the origin (the origin would need to be "between two samples", which is impossible).
For your example V, the above code gives Vf real and symmetric. The following figure has been generated with semilogy(Vf), so that small as well as large values can be seen. (Of course, you could modify the horizontal axis so that the graph is centered at 0 frequency as it should; but anyway the graph is seen to be symmetric.)
#Yvon is absolutely right with his comment about symmetry. Your input signal looks symmetrical, but it isn't because symmetry is related to origin 0.
Using linspace in Matlab for constructing signals is mostly a bad choice.
Trying to repair the results with fftshift is a bad idea too.
Use instead:
k = 2*(0:N-1)/N - 1;
and you will get the result you expect.
However the imaginary part of the transformed values will not be perfectly zero.
There is some numerical noise.
>> max(abs(imag(Vf5)))
ans =
2.5535e-15
Answer to Yvon's question:
Why? >> N = 1+2^4 N = 17 >> x=linspace(-1,1,N) x = -1.0000 -0.8750 -0.7500 -0.6250 -0.5000 -0.3750 -0.2500 -0.1250 0 0.1250 0.2500 0.3750 0.5000 0.6250 0.7500 0.8750 1.0000 >> y=2*(0:N-1)/N-1 y = -1.0000 -0.8824 -0.7647 -0.6471 -0.5294 -0.4118 -0.2941 -0.1765 -0.0588 0.0588 0.1765 0.2941 0.4118 0.5294 0.6471 0.7647 0.8824 – Yvon 1
Your example is not a symmetric (even) function, but an antisymmetric (odd) function. However, this makes no difference.
For a antisymmetric function of length N the following statement is true:
f[i] == -f[-i] == -f[N-i]
The index i runs from 0 to N-1.
Let us see was happens with i=2. Remember, count starts with 0 and ends with 16.
x[2] = -0.75
-x[N-2] == -x[17-2] == -x[15] = (-1) 0.875 = -0.875
x[2] != -x[N-2]
y[2] = -0.7647
-y[N-2] == -y[15] = (-1) 0.7647
y[2] == y[N-2]
The problem is, that the origin of Matlab vectors start at 1.
Modulo (periodic) vectors start with origin 0.
This difference leads to many misunderstandings.
Another way of explanation why linspace(-1,+1,N) is not correct:
Imagine you have a vector which holds a single period of a periodic function,
for instance a Cosinus function. This single period is one of a infinite number of periods.
The first value of your Cosinus vector must not be same as the last value of your vector.
However,that is exactly what linspace(-1,+1,N) does.
Doing so, results in a sequence where the last value of period 1 is the same value as the first sample of the following period 2. That is not what you want.
To avoid this mistake use t = 2*(0:N-1)/N - 1. The distance t[i+1]-t[i] is 2/N and the last value has to be t[N-1] = 1 - 2/N and not 1.
Answer to Yvon's second comment
Whatever you put in an input vector of a DFT/FFT, by theory it is interpreted as a periodic function.
But that is not the point.
DFT performs an integration.
fft(m) = Sum_(k=0)^(N-1) (x(k) exp(-i 2 pi m k/N )
The first value x(k=0) describes the amplitude of the first integration interval of length 1/N. The second value x(k=1) describes the amplitude of the second integration interval of length 1/N. And so on.
The very last integration interval of the symmetric function ends with same value as the first sample. This means, the starting point of the last integration interval is k=N-1 = 1-1/N. Your input vector holds the starting points of the integration intervals.
Therefore, the last point of symmetry k=N is a point of the function, but it is not a starting point of an integration interval and so it is not a member of the input vector.
You have a problem when implementing the concept "symmetry". A purely real, even (or "symmetric") function has a Fourier transform function that is also real and even. "Even" is the symmetry with respect to the y-axis, or the t=0 line.
When implementing a signal in Matlab, however, you always start from t=0. That is, there is no way to "define" the signal starting from before the origin of time.
Searching the Internet for a while lead me to this -
Correct use of fftshift and ifftshift at input to fft and ifft.
As Luis has pointed out, you need to perform ifftshift before feeding the signal into fft. The reason has never been documented in Matlab, but only in that thread. For historical reasons, outputs AND inputs of fft and ifft are swapped. That is, instead of ordered from -N/2 to N/2-1 (the natural order), the signal in time or frequency domain is ordered from 0 to N/2-1 and then -N/2 to -1. That means, the correct way to code is fft( ifftshift(V) ), but most people ignore this at most times. Why it's got silently ignored rather than raising huge problems is that most concerns have been put on the amplitude of signal, not phase. Since circular shifting does not affect amplitude spectrum, this is not a problem (even for the Matlab guys who have written the documentations).
To check the amplitude equality -
Vf2 = fft(ifftshift(V));
Vf5 = fft(V);
Va2 = abs(fftshift(Vf2));
Va5 = abs(fftshift(Vf5));
>> min(abs(Va2-Va5)<1e-10)
ans =
1
To see how badly wrong in phase -
Vp2 = angle(fftshift(Vf2));
Vp5 = angle(fftshift(Vf5));
Anyway, as I wrote in the comment, after copy&pasting your code into a fresh and clean Matlab, it gives 0 1 0 1 0 0.
To your question about N=even and N=odd, my opinion is when N=even, the signal is not symmetric, since there are unequal number of points on either side of the time origin.
Just add the following line after "k = linspace(-1,1,N);"
k(end)=[];
it will remove the last element of the array. This is defined to be symmetric array.
also consider that isreal(complex(1,0)) is false!!!
The isreal function just checks for the memory storage format. so 1+0i is not real in the above example.
You have define your function in order to check for real numbers (like this)
myisreal=#(x) all((abs(imag(x))<1e-6*abs(real(x)))|(abs(x)<1e-8));
Finally your source code should become something like this:
N = 1 + 2^8;
k = linspace(-1,1,N);
k(end)=[];
V = exp(-abs(k));
Vf1 = fft(fftshift(V));
Vf2 = fft(ifftshift(V));
Vf3 = ifft(fftshift(V));
Vf4 = ifft(ifftshift(V));
Vf5 = fft(V);
Vf6 = ifft(V);
myisreal=#(x) all((abs(imag(x))<1e-6*abs(real(x)))|(abs(x)<1e-8));
disp([myisreal(Vf1) myisreal(Vf2) myisreal(Vf3) myisreal(Vf4) myisreal(Vf5) myisreal(Vf6)]);