MATLAB "Index out of bounds" Error - matlab

I have a project to make FIR filter coefficients but when in process of Minimum-Order Lowpass Filter there is error which
I have no idea what that means and which part I need to repair:
function [ output_args ] = FIR_FilterCoeff()
N = 100; % FIR filter order
Fp = 20e3; % 20 kHz passband-edge frequency
Fp = 20e3; % 20 kHz passband-edge frequency
Fs = 96e3; % 96 kHz sampling frequency
Rp = 0.00057565; % Corresponds to 0.01 dB peak-to-peak ripple
Rst = 1e-4; % Corresponds to 80 dB stopband attenuation
NUM = firceqrip (N,Fp/(Fs/2),[Rp Rst],'passedge');
N2= 200; % change filter order to 200
NUM200 = firceqrip(N2,Fp/(Fs/2),[Rp Rst],'passedge');
Fst = 23e3; % transition width = Fst-Fp
NUM_MIN = firgr('minorder',[0,Fp/(Fs/2),Fst(Fs/2),1],[ 1 1 0 0 ],[Rp Rst]);

Your error lies in Fst(Fs/2) on your last line. Fst is a vector of length 1. It has 1 value 23e3. Round brackets, (), in MATLAB directly after a variable are used for indexing variables.
When you type Fst(Fs/2) you are attempting to access the 48000 element in Fst but it does not exist so MATLAB throws an error. I think you may have meant this to be
Fst/(Fs/2)
or (possibly)
Fst*(Fs/2)
The * sign is needed to perform multiplication in MATLAB. It is not good enough to simply use round brackets, (), as they have another purpose, Matrix Indexing.

Related

How to build a bandpass filter in Matlab with the butter function?

I am trying to extract the mu suppression values from my EEG dataset, which doesn't allow using EEGLab. I did most of the steps, but I need to add a bandpass filter and I am not sure how.
The frequency band I would need is 8-13, my sampling rate is 1000 and I was told I would need an order of between 8 and 10.
The MATLAB documentations lists this example:
[A,B,C,D] = butter(10,[500 560]/750);
d = designfilt('bandpassiir','FilterOrder',20, ... 'HalfPowerFrequency1',500,'HalfPowerFrequency2',560, ... 'SampleRate',1500);
However, I am not sure, what parameters I need to use for my case except for sampling rate and filter order. Also, it is not clear to me what is [A,B,C,D]. I would appreciate any input.
I usually go over the individual functions themselves -- you did a little mix-up.
The first input to butter is already the filter order (so you have specified order 10 and tried to specify order 20 in the desginfilt function...).
For the Butterworth-filter, MATLAB recommends to use the zero-pole-gain formulation rather than the standard a-b coefficients. Here is an example:
f_low = 100; % Hz
f_high = 500; % Hz
f_sampling = 10e3; % 10kHz
assert(f_low < f_high)
f_nrm_low = f_low /(f_sampling/2);
f_nrm_high = f_heigh /(f_sampling/2);
% determine filter coefficients:
[z,p,k] = butter(4,[f_nrm_low f_nrm_high],'bandpass');
% convert to zero-pole-gain filter parameter (recommended)
sos = zp2sos(z,p,k);
% apply filter
sig_flt = sosfilt(sos,sig);
I have filled with with standard values from my field of working. 4th order is the overwhelming standard here.
In your case, you would simply go with
f_low = 200; % Hz
f_high = 213; % Hz
f_sampling = 1000; % 1kHz
f_nrm_low = f_low /(f_sampling/2);
f_nrm_high = f_heigh /(f_sampling/2);
% determine filter coefficients:
[z,p,k] = butter(15,[f_nrm_low f_nrm_high],'bandpass');
PS: the type 'bandpath' is not required as the function is aware of this if you specify an array as input ;)

A faster approach to Laplacian of Gaussian

I am currently in the process of optimizing my code to make image processing more efficient. my first problem was due to the vision.VideoFileReader and step where it took a long time to open each frame. I speed up my code by compressing my grayscale image into 3 frames in 1 RGB frame. This way I could load 1 RGB frame using vid.step() and have 3 frames imported ready for processing.
Now my code is running slow on the Laplacian of Gaussian (LoG) filtering. I read that using the function imfilter can be used to perform a LoG but it appears to be the next rate limiting step.
Upon further reading, it appears that imfilter is not the best option for speed. Apperently MATLAB introduced a LoG function but it was introduced in R2016b and I'm unfortunately using R2016a.
Is there a way to speed up imfilter or is there a better function to use to perform a LoG filtering?
Should I call python to speed up the process?
Code:
Hei = gh.Video.reader.info.VideoSize(2);
Wid = gh.Video.reader.info.VideoSize(1);
Log_filter = fspecial('log', filterdot, thresh); % fspecial creat predefined filter.Return a filter.
% 25X25 Gaussian filter with SD =25 is created.
tic
ii = 1;
bkgd = zeros(Hei,Wid,3);
bkgd(:,:,1) = gh.Bkgd;
bkgd(:,:,2) = gh.Bkgd;
bkgd(:,:,3) = gh.Bkgd;
bkgdmod = reshape(bkgd,720,[]);
while ~isDone(gh.Video.reader)
frame = gh.readFrame();
img_temp = double(frame);
img_temp2 = reshape(img_temp,720,[]);
subbk = img_temp2 - bkgdmod;
img_LOG = imfilter(subbk, Log_filter, 'symmetric', 'conv');
img_LOG = imbinarize(img_LOG,.002);
[~, centroids, ~] = gh.Video.blobAnalyser.step(img_LOG);
toc
end
The Laplace of Gaussian is not directly separable into two 1D kernels. Therefore, imfilter will do a full convolution, which is quite expensive. But we can manually separate it out into simpler filters.
The Laplace of Gaussian is defined as the sum of two second-order-derivatives of the Gaussian:
LoG = d²/dx² G + d²/dy² G
The Gaussian itself, and its derivatives, are separable. Therefore, the above can be computed using 4 1D convolutions, which is much cheaper than a single 2D convolution unless the kernel is very small (e.g. if the kernel is 7x7, we need 49 multiplications and additions per pixel for the 2D kernel, or 4*7=28 multiplications and additions per pixel for the 4 1D kernels; this difference grows as the kernel gets larger). The computations would be:
sigma = 3;
cutoff = ceil(3*sigma);
G = fspecial('gaussian',[1,2*cutoff+1],sigma);
d2G = G .* ((-cutoff:cutoff).^2 - sigma^2)/ (sigma^4);
dxx = conv2(d2G,G,img,'same');
dyy = conv2(G,d2G,img,'same');
LoG = dxx + dyy;
If you are really strapped for time, and don't care about precision, you could set cutoff to 2*sigma (for a smaller kernel), but this is not ideal.
An alternative, less precise, is to separate the operation differently:
LoG * f = ( d²/dx² G + d²/dy² G ) * f
= ( d²/dx² 𝛿 * G + d²/dy² 𝛿 * G ) * f
= ( d²/dx^2 𝛿 + d²/dy² 𝛿 ) * G * f
(with * there representing convolution, and 𝛿 the Dirac delta, convolution's equivalent to multiplying by 1). The d²/dx² 𝛿 + d²/dy² 𝛿 operator doesn't really exist in the discrete world, but you can take the finite difference approximation, which leads to the famous 3x3 Laplace kernel:
[ 1 1 1 [ 0 1 0
1 -8 1 or: 1 -4 1
1 1 1 ] 0 1 0 ]
Now we get a rougher approximation, but it's faster to compute (2 1D convolutions, and a convolution with a trivial 3x3 kernel):
sigma = 3;
cutoff = ceil(3*sigma);
G = fspecial('gaussian',[1,2*cutoff+1],sigma);
tmp = conv2(G,G,img,'same');
h = fspecial('laplacian',0);
LoG = conv2(tmp,h,'same'); % or use imfilter

How do I make a clear table between a function and iterations, in MATLAB?

For my computing course, I am asked to determine the length of a function on the interval (0,20), by using the Trapezoidal Rule in MATLAB.
The parabolic curve is given by the following function:
y(x) = 0.1x^2 -2*x + 16
I first calculated the length through the arc length integral, by using the derivative of y: y'(x) = 0.2x - 2
I took the integral of sqrt(1+(0.2x - 2)^2). The answer should approximately be 29,5.
Now, I have the following in MATLAB:
y = #(x) sqrt(1+(0.2*x-2)^2);
x0=input('enter the value of Initial Limit x0'); *which is 0*
xn=input('enter the value of Final Limit xn'); *which is 20*
N=input('enter the total number of areas');
h=((xn-x0)/N);
area=0;
while(x0<xn)
area=area+(h/2)*(y(x0)+y(x0+h));
x0=x0+h;
end
fprintf('mysol for L=%.16f',area);
Now, I am asked to increase the number of used areas N in a sequence of N=200,400,800,1600... until I reach a certain accuracy.
How do I get a neat table in which I see my N vs. my length?
You are very close. Your code only handles the case for 1 value of N. As what Ander alluded to you above, simply wrap this code in a loop. We see that the initial value of N is 200, but you'll need to keep doubling the number until the error of your estimated area and predicted error is less than a certain amount. Be advised that 29.5 is a low precision estimate of the answer and so the value of N will be guided by this area. I would suggest increasing the precision of your value to ensure that you capture the right value of N.
If you consult the indefinite integral on Wolfram Alpha, we get the following expression:
Therefore, we can make an anonymous function in MATLAB and find the definite integral by simply substituting 20 into this function and subtracting with 0.
>> format long g;
>> f = #(x)((x^3 - 30*x^2 - 25*sqrt(x^2 - 20*x + 125)*asinh(2 - x/5) + 325*x - 1250) / (10*sqrt(x^2 -20*x + 125)));
>> est = f(20) - f(0)
est =
29.5788571508919
est contains the true value. Now we can finally modify your code. What you will have to do is when you estimate the area using the trapezoidal rule, you will need to check if the estimated value and the true value has less than some fraction of a tolerance in error. We can try something like 1e-8 where this roughly means that you will have a precision of accuracy to be about 8 digits.
Therefore, set a variable called err to be 0.01, run this in a loop and you'll need to check if the change in error is less than this amount before you quit. You'll also want a table where we can display the number N, the estimated value, the true value and finally the error seen. We can print this off inside the loop at each iteration. Also note that you are changing the value of x0 in your estimation, so you will need to reset x0 each time in the loop:
% Get true value of area
f = #(x)((x^3 - 30*x^2 - 25*sqrt(x^2 - 20*x + 125)*asinh(2 - x/5) + 325*x - 1250) / (10*sqrt(x^2 -20*x + 125)));
est = f(20) - f(0);
% Set the error
err = 1e-8;
% Function setup
y = #(x) sqrt(1+(0.2*x-2)^2);
x0 = 0; % Prior knowledge
xn = 20; % Prior knowledge
N = 200; % Initial value of N
% Print header of table
fprintf('%4s %11s %11s %10s\n', 'N', 'Estimated', 'True', 'Error');
while true % Start loop
x0 = 0; % Reset each time
h=((xn-x0)/N);
area=0;
while(x0<xn)
area=area+(h/2)*(y(x0)+y(x0+h));
x0=x0+h;
end
er = abs(area - est) / est; % Calculate error
% Print table entry
fprintf('%4d %.8f %.8f %.8f\n', N, area, est, er);
% Check for convergence
if er <= err
break;
end
N = N * 2; % Double N for the next iteration
end
When you run this, I get this table:
N Estimated True Error
200 29.57915529 29.57885715 0.00001008
400 29.57893169 29.57885715 0.00000252
800 29.63483340 29.57885715 0.00189244
1600 29.60682664 29.57885715 0.00094559
3200 29.57885832 29.57885715 0.00000004
6400 29.57885744 29.57885715 0.00000001
Therefore, this tells us that with N = 6400, this will give us the required error budget of 1e-8. This should be enough to get you started. Good luck!

Attempted to access sym(67); index out of bounds because numel(sym)=2

I am receiving the following error message:
Attempted to access sym(67); index out of bounds because numel(sym)=2.
I have been working on this for three days. I looked for similar error, but it didn't help. My code is below:
filename='DriveCyclesCP.xlsx';
V=xlsread('DriveCyclesCP.xlsx',2,'C9:C774'); % Get the velocity values, they are in an array V.
N=length(V); % Find out how many readings
mass = 1700 ; % Vehicle mass+ two 70 kg passengers.
area_Cd = 0.75; % Frontal area in square metres
Crr=0.009; %rolling resistance
g=9.8; % gravity acceleration
T=774; %UDDS cycle time duration
V_ave = 21.5; % UDDS avearage speed im m/s
rd=0.3; % Effective tire radius
Qhv =12.22; % E85 low Heating value in kWh/kg
Vd = 2.189; % engine size in L
md=0.801; % mass density of Ethanol
mf =Vd*md; % mf is the fuel mass consumed per cycle
Per = zeros(1,N); % engine power for each point of the drive cycle
a = zeros(1,N); % acceleration
SFC = zeros(1,N); % specific fuel consumption
Wc = zeros (1,N); % mass flow rate
nf = zeros (1,N); %fuel efficiency
Pm = zeros (1,N); % motor power
Pt = zeros (1,N);
Te =zeros (1,N); % Engine Troque
Tt = zeros (1,N);
Tm =zeros (1,N);
we =zeros (1,N); % Engine rot speed
wt = zeros (1,N);
wm =zeros (1,N);
S =zeros (1,8);
int (sym ('C'));
for C=1:N
a(C)=V(C+1)-V(C);
Pt(C)= V(C)*(mass*g*Crr + (0.5*area_Cd*1.202*(V(C))^2) + mass*a(C))/1000;
Per(C)=(mass*g*Crr +0.5*area_Cd*1.202*(V(C))^2 +mass*g*0.03)/1000*0.85;% e
syms Te(C) Tt(C) Tm(C) wt(C) we(C) wm(C) k1 k2
S = solve( Pm(C)==Pt(C) - Per(C), Tt(C)*wt(C)== Pt(C), Tt(C)*wt(C)== Te(C)*we(C) + Tm(C)*wm(C), wt(C)==we(C)/k1, wt(C)==wm(C)/k2, Pm(C)==wm(C) *Tm(C), Per(C)==we(C) *Te(C), Tt == k1*Te + k2*Tm );
end
The problem is on the line
int (sym ('C'));
You have defined sym to be a matrix with 2 entries somewhere (either earlier in the code or in a previous mfile), thus it treats sym as a matrix instead of a function. Thus when Matlab gets to the statement sym('C') it first converts the character 'C' to its ASCII integer representation (this just happens to be the number 67), then it tries to calculate sym(67) which is impossible as sym only has 2 elements.
Thus you have to stop sym from being a matrix (variable) and let it be a function again. There are two ways to solve this, either you can start you file with the statement clear;, this will remove all variables in memory, which might not be what you want; or you can use a function instead of script, as this hides all variables that have been defined previously and prevents this sort of error.
Note the line numel(X) is a way to measure how many elements are in X. Thus numel(sym)=2 means that sym has 2 elements.
P.S. There is an error in the lines (notice that I only taken some of the lines of you code)
N=length(V); % Find out how many readings
for C=1:N
a(C)=V(C+1)-V(C);
end
When C becomes equal to N, then V(C+1) will generate an error.

Matlab firpm fails for large AFR data arrays

Here is a quick & dirty code for trying to create a high precision equalizer:
bandPoints = 355;
for n = 1:bandPoints
x = (n / (bandPoints + 2));
f = (x*x)*(22000-20)+20; % 20...22000
freqs(n) = f;
niqfreqs(n) = f/22050.0;
amps(n) = 0;
end
amps(bandPoints+1) = 0; % firpm needs even numbers
niqfreqs(bandPoints+1) = 1; % firpm needs even numbers
% set some point to have a high amplitude
amps(200) = 1;
fircfs = firpm(101,niqfreqs,amps);
[h,w] = freqz(fircfs,1,512);
plot(w/pi,abs(h));
legend('firpm Design')
but it gives me
Warning:
*** FAILURE TO CONVERGE ***
Probable cause is machine rounding error.
and all FIR coefficients are 0.
If I lower the n parameter from 101 to 91, firpm works without errors, but the frequency response is far from desired. And taking into account, that I want to calculate FIR coefficients for a hardware DSP FIR module, which supports up to 12288 taps, how can I make Matlab calculate the needed coefficients? Is firpm capable of doing this or do I need to use another approach (inverse FFT) in both Matlab and later in my application C++ code?
Oh, it seems MP algorithm really cannot handle this, so I need some other solution:
http://www.eetimes.com/design/embedded/4212775/Designing-very-high-order-FIR-filters-with-zero-stuffing
I guess, I'll have to stick with inverse FFT then.