Receiving MATLAB Error Regarding Function Arguments - matlab

When running my MATLAB script below, I keep getting an error that states:
Error using spa (Line 147)
The value of the window
size must be an integer greater than 2.
Error in "projectName" G = spa(xFunction2, x)
I've tried putting in multiple types of arguments into "spa" (data, windowsize, frequency) but it still yields the same error(s). Help?
n = 1:1024;
%Signal Function
xFunction = sqrt(10)*exp(j*2*pi*0.10*n)+ sqrt(20)*exp(j*2*pi*0.20*n) + sqrt(625);
%Complex Noise Function
zFunction = 0.707*randn(size(n)) + j*0.707*randn(size(n));
%Computing the value of x(n) + sqrt(625)*z
xFunction2 = xFunction + sqrt(625)*zFunction;
G = spa(xFunction2,51);
figure(1);
plot(w, 10*log10(G));

Acording the documentation of spa the first argument is iddata type. In addition, the time serie has to be a column vector.
So, to make it works change G = spa(xFunction2,51); for G = spa(xFunction2(:),51);. To do it the correct way, convert your time serie to iddata:
Ts = 0.1; % what ever is your sampling time.
myiddata = iddata(xFunction2(:),[],Ts);
G = spa(myiddata,51);
In addition, you should use spectrum(G) or bode(G)to plot the result.

Related

mle memory error with custom negative log-likelihood function

I am trying to use 'mle' with a custom negative log-likelihood function, but I get the following error:
Requested 1200000x1200000 (10728.8GB) array exceeds maximum array size preference (15.6GB). This might cause MATLAB to become unresponsive.
The data I am using is a 1x1200000 binary array (which I had to convert to double), and the function has 10 arguments: one for the data, 3 known paramenters, and 6 to be optimized. I tried setting 'OptimFun' to both 'fminsearch' and 'fmincon'. Also, optimizing the parameters using 'fminsearch' and 'fminunc' instead of 'mle' works fine.
The problem happens in the 'checkFunErrs' functions, inside the 'mlecustom.m' file (call at line 173, actuall error at line 705).
With 'fminunc' I could calculate the optimal parameters, but it does not give me confidence intervals. Is there a way to circumvent this? Or am I doing something wrong?
Thanks for the help.
T_1 = 50000;
T_2 = 100000;
npast = 10000;
start = [0 0 0 0 0 0];
func = #(x, data, cens, freq)loglike(data, [x(1) x(2) x(3) x(4) x(5) x(6)],...
T_1, T_2, npast);
params = mle(data, 'nloglf', func, 'Start', start, 'OptimFun', 'fmincon');
% Computes the negative log likehood
function out = loglike(data, params, T_1, T_2, npast)
size = length(data);
if npast == 0
past = 0;
else
past = zeros(1, size);
past(npast+1:end) = movmean(data(npast:end-1),[npast-1, 0]); % Average number of events in the previous n years
end
lambda = params(1) + ...
(params(2)*cos(2*pi*(1:size)/T_1)) + ...
(params(3)*sin(2*pi*(1:size)/T_1)) + ...
(params(4)*cos(2*pi*(1:size)/T_2)) + ...
(params(5)*sin(2*pi*(1:size)/T_2)) + ...
params(6)*past;
out = sum(log(1+exp(lambda))-data.*lambda);
end
Your issue is line 228 (as of MATLAB R2017b) of the in-built mle function, which happens just before the custom function is called:
data = data(:);
The input variable data is converted to a column array without warning. This is typically done to ensure that all further calculations are robust to the orientation of the input vector.
However, this is causing you issues, because your custom function assumes data is a row vector, specifically this line:
out = sum(log(1+exp(lambda))-data.*lambda);
Due to implicit expansion, when the row vector lambda and the column vector data interact, you get a huge square matrix per your error message.
Adding these two lines to make it explicit that both are column vectors resolves the issue, avoids implicit expansion, and applies the calculation element-wise as you intended.
lambda = lambda(:);
data = data(:);
So your function becomes
function out = loglike(data, params, T_1, T_2, npast)
N = length(data);
if npast == 0
past = 0;
else
past = zeros(1,N);
past(npast+1:end) = movmean(data(npast:end-1),[npast-1, 0]); % Average number of events in the previous n years
end
lambda = params(1) + ...
(params(2)*cos(2*pi*(1:N)/T_1)) + ...
(params(3)*sin(2*pi*(1:N)/T_1)) + ...
(params(4)*cos(2*pi*(1:N)/T_2)) + ...
(params(5)*sin(2*pi*(1:N)/T_2)) + ...
params(6)*past;
lambda = lambda(:);
data = data(:);
out = sum(log(1+exp(lambda))-data.*lambda);
end
An alternative would be to re-write your function so that it uses column vectors, but you create new row vectors with the (1:N) steps and the concatenation within the movmean. The suggested approach is arguably "lazier", but also robust to row or column inputs.
Note also I've changed your variable name from size to N, since size is an in-built function which you should avoid shadowing.

Having difficulties in finding error: Matrix dimensions must agree

My aim is to call this function into the pso code for minimization.
actually im calling this code into another program(mfile),here
v=0.1*x0; % initial velocity
for i=1:n
f0(i,1)=ofun(x0(i,:));
end
so what should i do, could anyone plz write me a code, so i can remove this problem. my aim is to minimize error using ITEA code, which im trying to do, im trying to find a that every time code runs, e_t have last updated value, not e_t=0.001 .
I don't have e_t. If I'm going to initialize it, it will remain constant, but I need to change its value in the code.
Second, I'm getting this error
Error using .* Matrix dimensions must agree.
Error in ofun (line 10), f = sum(t'.*abs(e_t)*dt);
function f=ofun(x)
Kp= x(1);
Ki= x(2);
e_t;
d=0.001;
I_ref=-1.1:d:1;
dt = 0.01;
t = 0:dt:1;
e_t= I_ref - (Kp.*e_t +Ki.*sum(t'.*abs(e_t)*dt));
f = sum(t'.*abs(e_t)*dt); % line 10
I want to write code for following equations
error= I_ref - (kp * error + ki*(integration of error));
I want to set I-ref=-1.1-1.1;
Here e_t get's the same size as I_ref
e_t= I_ref - (Kp.*e_t +Ki.*sum(t'.*abs(e_t)*dt));
Then you want to multiply it with t
f = sum(t'.*abs(e_t)*dt);
But t is of a different size as I_ref. t has length 101, I_ref has length 2101.
"Matrix dimensions must agree" is an error message that appears in this case in line 10 because matrix t cannot be multiplied elementwise with the e_t. Whichever matrix is smaller, I would probably add ones to the rest of it so that the result matrix is still able tone populated. Why are you transposing matrix t though? Good luck with your project!
function f=ofun(x)
%Define variables and constants- when you define e_t, why are you not multiplying dt elementwise? Also why do you transpose matrix t?
Kp = x(1); Ki = x(2); d = 0.001; I_ref = [-1.1 : d : 1]; dt = 0.01; t = [0 : dt : 1]; e_t = I_ref - (Kp.*e_t + Ki.*sum(t'.*abs(e_t)*dt));
f = sum(t'.*abs(e_t)*dt);% line 10
end

How do I define parameters in a convolution equation?

I am trying to compute the convolution of a sound signal without using the built in conv function but instead using arrays. x is the input signal and h is are the impulse responses. However, when I run my other main function to call onto my_conv I am getting these errors:
Undefined function or variable 'nx'.**
Error in my_conv (line 6)
ly=nx+nh-1;
Error in main_stereo (line 66)
leftchannel = my_conv(leftimp, mono); % convolution of left ear impulse response and mono
This is my function my_conv:
function [y]=my_conv(x,h)
x=x(:);
h=h(:);
lx=length(x);
lh=length(h);
ly=nx+nh-1;
Y=zeros(nh,ny);
for i =1:nh
Y((1:nx)+(i-1),i)=x;
end
y=Y*h;
What changes should I make to fix these errors and get this code running?
I am trying to immplement the function into this code:
input_filename = 'speech.wav';
stereo_filename = 'stereo2.wav';
imp_filename = 'H0e090a.dat';
len_imp = 128;
fp = fopen(imp_filename, 'r', 'ieee-be');
data = fread(fp, 2*len_imp, 'short');
fclose(fp);
[mono,Fs] = audioread(input_filename);
if (Fs~=44100)
end
len_mono = length(mono);
leftimp = data(1:2:2*len_imp);
rightimp = data(2:2:2*len_imp);
leftchannel = my_conv(leftimp, mono);
rightchannel = my_conv(rightimp, mono);
leftchannel = reshape(leftchannel , length(leftchannel ), 1);
rightchannel = reshape(rightchannel, length(rightchannel), 1);
norml = max(abs([leftchannel; rightchannel]))*1.05;
audiowrite(stereo_filename, [leftchannel rightchannel]/norml, Fs);
As pointed out by #SardarUsama in comments, the error
Undefined function or variable 'nx'.
Error in my_conv (line 6) ly=nx+nh-1;
tells you that the variable nx has not been defined before before its usage on the line ly=nx+nh-1. Given the naming of the variables and their usage, it looks like what you intended to do was:
nx = length(x);
nh = length(h);
ny = nx+nh-1;
After making these modifications and solving the first error, you are likely going to get another error telling you that
error: my_conv: operator *: nonconformant arguments
This error is due to an inversion in the specified size of the Y matrix. This can be fixed by initializing Y with Y = zeros(ny, nh);. The resulting my_conv function follows:
function [y]=my_conv(x,h)
nx=length(x);
nh=length(h);
ny=nx+nh-1;
Y=zeros(ny,nh);
for i =1:nh
Y((1:nx)+(i-1),i)=x;
end
y=Y*h;
Note that storing every possible shifts of one of the input vectors in the matrix Y to compute the convolution as a matrix multiplication is not very memory efficient (requiring O(NM) storage). A more memory efficient implementation would compute each element of the output vector directly:
function [y]=my_conv(x,h)
nx=length(x);
nh=length(h);
if (nx < nh)
y = my_conv(h,x);
else
ny=nx+nh-1;
y = zeros(1,ny);
for i =1:ny
idh = [max(i-(ny-nh),1):min(i,nh)]
idx = [min(i,nx):-1:max(nx-(ny-i),1)]
y(i) = sum(x(idx).*h(idh));
end
end
An alternate implementation which can be more computationally efficient for large arrays would make use of the convolution theorem and use the Fast Fourier Transform (FFT):
function [y]=my_conv2(x,h)
nx=length(x);
nh=length(h);
ny=nx+nh-1;
if (size(x,1)>size(x,2))
x = transpose(x);
end
if (size(h,1)>size(h,2))
h = transpose(h);
end
Xf = fft([x zeros(size(x,1),ny-nx)]);
Hf = fft([h zeros(size(h,1),ny-nh)]);
y = ifft(Xf .* Hf);

Fitting model to data in matlab

i have some experimental data and a theoretical model which i would like to try and fit. i have made a function file with the model - the code is shown below
function [ Q,P ] = RodFit(k,C )
% Function file for the theoretical scattering from a Rod
% R = radius, L = length
R = 10; % radius in Å
L = 1000; % length in Å
Q = 0.001:0.0001:0.5;
fun = #(x) ( (2.*besselj(1,Q.*R.*sin(x)))./...
(Q.*R.*sin(x)).*...
(sin(Q.*L.*cos(x)./2))./...
(Q.*L.*cos(x)./2)...
).^2.*sin(x);
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
end
with Q being the x-values and P being the y-values. I can call the function fine from the matlab command line and it works fine e.g. [Q,P] = RodFit(1,0.001) gives me a result i can plot using plot(Q,P)
But i cannot figure how to best find the fit to some experimental data. Ideally, i would like to use the optimization toolbox and lsqcurvefit since i would then also be able to optimize the R and L parameters. but i do not know how to pass (x,y) data to lsqcurvefit. i have attempted it with the code below but it does not work
File = 30; % the specific observation you want to fit the model to
ydata = DataFiles{1,File}.data(:,2)';
% RAdius = linspace(10,1000,length(ydata));
% LEngth = linspace(100,10000,length(ydata));
Multiplier = linspace(1e-3,1e3,length(ydata));
Constant = linspace(0,1,length(ydata));
xdata = [Multiplier; Constant]; % RAdius; LEngth;
L = lsqcurvefit(#RodFit,[1;0],xdata,ydata);
it gives me the error message:
Error using *
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
Error in lsqcurvefit (line 199)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot continue.
i have tried i) making all vectors/matrices the same length and ii) tried using .* instead. nothing works and i am giving the same error message
Any kind of help would be greatly appreciated, whether it is suggestion regading what method is should use, suggestions to my code or something third.
EDIT TO ANSWER Osmoses:
A really good point but i do not think that is the problem. just checked the size of the all the vectors/matrices and they should be alright
>> size(Q)
ans =
1 1780
>> size(P)
ans =
1 1780
>> size(xdata)
ans =
2 1780
>> size([1;0.001]) - the initial guess/start point for xdata (x0)
ans =
2 1
>> size(ydata)
ans =
1 1780
UPDATE
I think i have identified the problem. the function RodFit works fine when i specify the input directly e.g. [Q,P] = RodFit(1,0.001);.
however, if i define x0 as x0 = [1,0.001] i cannot pass x0 to the function
>> x0 = [1;0.001]
x0 =
1.0000
0.0010
>> RodFit(x0);
Error using *
Inner matrix dimensions must agree.
Error in RodFit (line 15)
P = (integral(fun,0,pi/2,'ArrayValued',true))*k+C;
The same happens if i use x0 = [1,0.001]
clearly, matlab is interpreting x0 as input for k only and attempts to multiplay a vector of length(ydata) and a vector of length(x0) which obviously fails.
So my problem is that i need to code so that lsqcurvefit understands that the first column of xdata and x0 is the k variable and the second column of xdata and x0 is the C variable. According to the documentation - Passing Matrix Arguments - i should be able to pass x0 as a matrix to the solver. The solver should then also pass the xdata in the same format as x0.
Have you tried (that's sometimes the mistake) looking at the orientation of your input data (e.g. if xdata & ydata are both row/column vectors?). Other than that your code looks like it should work.
I have been able to solve some of the problems. One mistake in my code was that the objective function did not use of vector a variables but instead took in two variables - k and C. changing the code to accept a vector solved this problem
function [ Q,P ] = RodFit(X)
% Function file for the theoretical scattering from a Rod
% R = radius, L = length
% Q = 0.001:0.0001:0.5;
Q = linspace(0.11198,4.46904,1780);
fun = #(x) ( (2.*besselj(1,Q.*R.*sin(x)))./...
(Q.*R.*sin(x)).*...
(sin(Q.*L.*cos(x)./2))./...
(Q.*L.*cos(x)./2)...
).^2.*sin(x);
P = (integral(fun,0,pi/2,'ArrayValued',true))*X(1)+X(2);
with the code above, i can define x0 as x0 = [1 0.001];, and pass that into RodFit and get a result. i can also pass xdata into the function and get a result e.g. [Q,P] = RodFit(xdata(2,:));
Notice i have changed the orientation of all vectors so that they are now row-vectors and xdata has size size(xdata) = 1780 2
so i thought i had solved the problem completely but i still run into problems when i run lsqcurvefit. i get the error message
Error using RodFit
Too many input arguments.
Error in lsqcurvefit (line 199)
initVals.F = feval(funfcn_x_xdata{3},xCurrent,XDATA,varargin{:});
Caused by:
Failure in initial user-supplied objective function evaluation. LSQCURVEFIT cannot continue.
i have no idea why - does anyone have any idea about why Rodfit recieves to many input arguments when i call lsqcurvefit but not when i run the function manual using xdata?

correct function handle for integral2 in matlab

I created a function in matlab that returns a vector like
function w = W_1D(x,pos,h)
w=zeros(1,length(x));
if (h~=0)
xmpos = x-pos;
inds1 = (-h <= xmpos) & (xmpos < 0);
w(inds1) = xmpos(inds1)./h + 1;
inds2 = (0 <= xmpos) & (xmpos <= h);
w(inds2) = -xmpos(inds2)./h + 1;
else
error('h shouldn't be 0')
end
end
Thus, in the end, there is a vector w of size length(x).
Now i created a second function like
function f = W_2D(x,y,pos_1,pos_2,h)
w_x = W_1D(x,pos_1,h);
w_y = W_1D(y,pos_2,h);
f = w_x'*w_y;
end
where length(x)=length(y). Thus, the function W_2D obviously returns a matrix.
But when I now try to evaluate the integral over a rectangular domain like e.g.
V = integral2(#(x,y) W_2D(x,y,2,3,h),0,10,0,10);
matlab returns some errors:
Error using integral2Calc>integral2t/tensor (line 242)
Integrand output size does not match the input size.
Error in integral2Calc>integral2t (line 56)
[Qsub,esub] = tensor(thetaL,thetaR,phiB,phiT);
Error in integral2Calc (line 10)
[q,errbnd] = integral2t(fun,xmin,xmax,ymin,ymax,optionstruct);
Error in integral2 (line 107)
Q = integral2Calc(fun,xmin,xmax,yminfun,ymaxfun,opstruct);
I also tried to vary something in the W_2D-function: instead of f = w_x'*w_y;
I tried f = w_x.'*w_y;
or w_y = transpose(w_y); f = kron(w_x,w_y);, but there is always this error with the Integrand output size-stuff.
Can anyone explain, where my fault is?
EDIT: After Werner's hint with the keyboard debugging method, I can tell you the following.
The first step returns w_x of type <1x154 double>, w_y is <1x192 double>, x and y are both <14x14 double>. In the next step, f appears with a value of <154x192 double>. Then everything disappears, except x and y and the matlab-function integral2Calc.m appears in the editor and it jumps to the Function Call Stack integral2t/tensor and after some more steps, the error occurs here
Z = FUN(X,Y); NFE = NFE + 1;
if FIRSTFUNEVAL
if ~isfloat(Z)
error(message('MATLAB:integral2:UnsupportedClass',class(Z)));
end
% Check that FUN is properly vectorized. This is important here
% because we (otherwise) always pass in square matrices, which
% reduces the probability of the user generating an error by
% using matrix functions instead of elementwise functions.
Z1 = FUN(X(VTSTIDX),Y(VTSTIDX)); NFE = NFE + 1;
if ~isequal(size(Z),size(X)) || ~isequal(size(Z1),size(VTSTIDX))
% Example:
% integral2(#(x,y)1,0,1,0,1)
error(message('MATLAB:integral2:funSizeMismatch'));
end
Hope that information is detailed enough...I have no idea what happenes, because my example is exact as it is given on the mathworks site about integral2, isn't it?
Maybe I should precise a bit more, what I wanna do: since W_2D gives me a surface w(x,y) of a compactly supported 2-dimensional hat-function, stored in a matrix w, I want to calculate the volume between the (x,y)-plane and the surface z=w(x,y)...
EDIT2: I still do not understand how to handle the problem, that integral2 creates matrices as inputs for my W_1D-functions, which are called in W_2D and intended to have a <1xn double>-valued input and return a <1xn double> output, but at least I can simply use the following to solve the integration over the tensor product by using two one-dimensional integral-calls, that is
V = integral(#(x)integral(#(y)W_1D(y,3,h),0,10).*W_1D(x,2,h),0,10);
This first function is quite wrong. You are not indexing the array positions while you are doing w = x inside for.
Besides, if that would work, you are returning a line vector, that is, size 1xlength(x) and when you do w_x'*w_y you are doing length(x)x1 times 1xlength(y), which would give you a matrix length(x)*length(y).
Consider correcting your function:
function w = W_1D(x,pos)
w = zeros(length(x),1); % Allocate w as column vector, so that the product gives a scalar (as I suppose that it is what you want.
for ii=1:length(x) % Here, so that is indexes w and x elements as you need
w(ii)=x(ii) - pos; % I changed your code to something that makes sense, but I don't know if that is what you want to do, you have to adapt it to work correctly.
end
end
You may also want to debug your functions, consider adding keyboard before your operations and check what they are returning using dbstep. I.e:
function f = W_2D(x,y,pos_1,pos_2)
w_x = W_1D(x,pos_1);
w_y = W_1D(y,pos_2);
keyboard
f = w_x'*w_y;
end
Execution will stop at keyboard, then you can check w_x size, w_y size, and do dbstep to go after f = w_x'*w_y and see what it returned. After you finish debug, you can do dbcont so that it will continue execution.
This answer is a draft as it is quite difficult to help you with the information you have provided. But I think you can start working the things out with this. If you have more doubts feel free to ask.