How to apply a function over a matrix and simultaneously pass parameters? - matlab

I have a matrix e.g. as follows:
N = magic(100);
I want to apply a function on each column and save its output in another matrix.
Here is my function
function z = nikfoo(y, lambda, p)
m = length(y);
D = diff(speye(m), 2);
w = ones(m, 1);
for it = 1:10
W = spdiags(w, 0, m, m);
C = chol(W + lambda * D' * D);
z = C \ (C' \ (w .* y));
w = p * (y > z) + (1 - p) * (y < z);
end
At first I tried to make a matrix the same size as my data
% I take the size of my matrix
[a, b] = size(N);
% make the same size matrix with zeros
corrNiki = zeros(a,b);
then I try to do it as follows
% I set the lambda as 1000 and p as 0.1
for i = 1:b
corrNiki(i) = nikfoo(N(i),1000,0.1);
end
So now I have these questions
how can I pass this function with the fixed lammda and p and save the results in corrNiki?
how can I also pass different values to the Lamda in a range and in P in a range and then save their outputs ?
for example
Lammda 1000 and P0.1 is saved in data1
Lammda 2000 and P0.01 is saved in data2
.
.
.

Related

Octave error: can't perform indexing operations for <unknown type> type

I have an octave/Matlab function like this.
function [z] = baseline_als(y, lam, p, niter)
L = size(y);
D = sparse(diff(eye(L), 2));
w = ones(L);
for i = 1:niter
W = sparse.spdiags(w, 0, L, L); %error comes here
Z = W + lam * dot(D,transpose(D));
% z = spsolve(Z, w*y);
z= Z\(w*y);
w = p * (y > z) + (1-p) * (y < z);
end % End of For loop
end % End of function
I am calling this like this (in other file),
z = baseline_als(X,1000,0.00001,20)
plot(z)
Where X is 1D vector.
I have referred documentation from here. But could not figure out this error. How can I solve this?

Mel-frequency function: error with matrix dimensions

I'm trying to make a prototype audio recognition system by following this link: http://www.ifp.illinois.edu/~minhdo/teaching/speaker_recognition/. It is quite straightforward so there is almost nothing to worry about. But my problem is with the mel-frequency function. Here is the code as provided on the website:
function m = melfb(p, n, fs)
% MELFB Determine matrix for a mel-spaced filterbank
%
% Inputs: p number of filters in filterbank
% n length of fft
% fs sample rate in Hz
%
% Outputs: x a (sparse) matrix containing the filterbank amplitudes
% size(x) = [p, 1+floor(n/2)]
%
% Usage: For example, to compute the mel-scale spectrum of a
% colum-vector signal s, with length n and sample rate fs:
%
% f = fft(s);
% m = melfb(p, n, fs);
% n2 = 1 + floor(n/2);
% z = m * abs(f(1:n2)).^2;
%
% z would contain p samples of the desired mel-scale spectrum
%
% To plot filterbanks e.g.:
%
% plot(linspace(0, (12500/2), 129), melfb(20, 256, 12500)'),
% title('Mel-spaced filterbank'), xlabel('Frequency (Hz)');
f0 = 700 / fs;
fn2 = floor(n/2);
lr = log(1 + 0.5/f0) / (p+1);
% convert to fft bin numbers with 0 for DC term
bl = n * (f0 * (exp([0 1 p p+1] * lr) - 1));
b1 = floor(bl(1)) + 1;
b2 = ceil(bl(2));
b3 = floor(bl(3));
b4 = min(fn2, ceil(bl(4))) - 1;
pf = log(1 + (b1:b4)/n/f0) / lr;
fp = floor(pf);
pm = pf - fp;
r = [fp(b2:b4) 1+fp(1:b3)];
c = [b2:b4 1:b3] + 1;
v = 2 * [1-pm(b2:b4) pm(1:b3)];
m = sparse(r, c, v, p, 1+fn2);
But it gave me an error:
Error using * Inner matrix dimensions must agree.
Error in MFFC (line 17) z = m * abs(f(1:n2)).^2;
When I include these 2 lines just before line 17:
size(m)
size(abs(f(1:n2)).^2)
It gave me :
ans =
20 65
ans =
1 65
So should I transpose the second matrix? Or should I interpret this as an row-wise multiplication and modify the code?
Edit: Here is the main function (I simply run MFCC()):
function result = MFFC()
[y Fs] = audioread('s1.wav');
% sound(y,Fs)
Frames = Frame_Blocking(y,128);
Windowed = Windowing(Frames);
spectrum = FFT_After_Windowing(Windowed);
%imagesc(mag2db(abs(spectrum)))
p = 20;
S = size(spectrum);
n = S(2);
f = spectrum;
m = melfb(p, n, Fs);
n2 = 1 + floor(n/2);
size(m)
size(abs(f(1:n2)).^2)
z = m * abs(f(1:n2)).^2;
result = z;
And here are the auxiliary functions:
function f = Frame_Blocking(y,N)
% Parameters: M = 100, N = 256
% Default : M = 100; N = 256;
M = fix(N/3);
Frames = [];
first = 1; last = N;
len = length(y);
while last <= len
Frames = [Frames; y(first:last)'];
first = first + M;
last = last + M;
end;
if last < len
first = first + M;
Frames = [Frames; y(first : len)];
end
f = Frames;
function f = Windowing(Frames)
S = size(Frames);
N = S(2);
M = S(1);
Windowed = zeros(M,N);
nn = 1:N;
wn = 0.54 - 0.46*cos(2*pi/(N-1)*(nn-1));
for ii = 1:M
Windowed(ii,:) = Frames(ii,:).*wn;
end;
f = Windowed;
function f = FFT_After_Windowing(Windowed)
spectrum = fft(Windowed);
f = spectrum;
Transpose s or transpose the resulting f (it's just a matter of convention).
There is nothing wrong with the melfb function you are using, merely with the dimensions of the signal in the example you are trying to run (in the commented lines 14-17).
% f = fft(s);
% m = melfb(p, n, fs);
% n2 = 1 + floor(n/2);
% z = m * abs(f(1:n2)).^2;
The example assumes that you are using a "colum-vector signal s". From the size of your Fourier transformed f (done via fft which respects the input signal dimensions) your input signal s is a row-vector signal.
The part that gives you the error is the actual filtering operation that requires multiplying a p x n2 matrix with a n2 x 1 column-vector (i.e., each filter's response is multiplied pointwise with the Fourier of the input signal). Since your input s is 1 x n, your f will be 1 x n and the final matrix to vector multiplication for z will give an error.
Thanks to gevang's anwer, I was able to find out my mistake. Here is how I modified the code:
function result = MFFC()
[y Fs] = audioread('s2.wav');
% sound(y,Fs)
Frames = Frame_Blocking(y,128);
Windowed = Windowing(Frames);
%spectrum = FFT_After_Windowing(Windowed');
%imagesc(mag2db(abs(spectrum)))
p = 20;
%S = size(spectrum);
%n = S(2);
%f = spectrum;
S1 = size(Windowed);
n = S1(2);
n2 = 1 + floor(n/2);
%z = zeros(S1(1),n2);
z = zeros(20,S1(1));
for ii=1: S1(1)
s = (FFT_After_Windowing(Windowed(ii,:)'));
f = fft(s);
m = melfb(p,n,Fs);
% n2 = 1 + floor(n/2);
z(:,ii) = m * abs(f(1:n2)).^2;
end;
%f = FFT_After_Windowing(Windowed');
%S = size(f);
%n = S(2);
%size(f)
%m = melfb(p, n, Fs);
%n2 = 1 + floor(n/2);
%size(m)
%size(abs(f(1:n2)).^2)
%z = m * abs(f(1:n2)).^2;
result = z;
As you can see, I naively assumed that the function deals with row-wise matrices, but in fact it deals with column vectors (and maybe column-wise matrices). So I iterate through each column of the input matrix and then combine the results.
But I don't think this is efficient and vectorized code. Also I still can't figure out how to do column-wise operations on the input matrix (Windowed - after the windowing step), instead of using a loop.

MATLAB - vectorize iteration over two matrices used in function

I have two matrices X and Y, both of order mxn. I want to create a new matrix Z of order mx1 such that each i th entry in this new matrix is computed by applying a function to ith and ith row of X and Y respectively. In my case m = 100000 and n = 2. I tried using a loop but it takes forever.
for i = 1:m
Z = function(X(1,:),Y(1,:), constant_parameters)
end
Is there an efficient way to vectorize it?
EDIT 1
This is the function
function [peso] = fxPesoTexturaCN(a,b, img, r, L)
ac = num2cell(a);
bc = num2cell(b);
imgint1 = img(sub2ind(size(img),ac{:}));
imgint2 = img(sub2ind(size(img),bc{:}));
peso = (sum((a - b) .^ 2) + (r/L) * (imgint2 - imgint1)) / (2*r^2);
Where img, r, L are constats. a is X(1,:) and b is Y(1,:)
And the call of this function is
peso = bsxfun(#(a,b) fxPesoTexturaCN(a,b,img,r,L), a, b);

how to remove array index out of bound error in matlab

here is my code where i have one error regarding array index out out of bound. plzz help me to rectify it
I = imread('E:\degraded images\village.jpg');
imshow(I)
I = im2double(I);
I = log(1 + I);
M = 2*size(I,1) + 1;
N = 2*size(I,2) + 1;
sigma = 10;
[X, Y] = meshgrid(1:N,1:M);
centerX = ceil(N/2);
centerY = ceil(M/2);
gaussianNumerator = (X - centerX).^2 + (Y - centerY).^2;
H = exp(-gaussianNumerator./(2*sigma.^2));
H = 1 - H;
imshow(H,'InitialMagnification',25)
H = fftshift(H);
If = fft2(I, M, N);
Iout = real(ifft2(H.*If)); ** here the code has error . ??? Error using ==> times Number of array dimensions must match for binary array op.**
H is 2-D while If is 3-D. You can use repmat with H or subset If. I don't know which one is correct for your situation. For instance,
rempat( H, [1, 1, 3 ] ) .* If;
or
H .* If(:,:,ind); % ind is the index of the 2-D array you want to subset

Implement Fitzhugh-Nagumo model via Crank-Nicolson

For a problem, I need to implement the Fitzhugh-Nagumo model with spatial diffusion via Crank-Nicolson's scheme. Now the problem lays withing the spatial diffusion.
(V_{t}) (DV_{xx} + V(V-a)(1-V) - W + I)
(W_{t}) (epsilon(V - b*W )
whereas DV_{xx} is the spatial diffusion.
Using Matlab, the following function can be given to i.e. an ODE45 solver. However it does not yet implement the spatial diffusion...
function dy = FHN( t, Y, D, a, b, eps, I )
V = Y(1);
W = Y(2);
dY = zeros(2,1);
% FHN-model w/o spatial diffusion
Vxx = 0;
dY(0) = D .* Vxx + V .* (V-a) .* (1-V) - W + I;
dY(1) = eps .* (V-b .* W);
The question: How to implement V_{xx} ?
Besides, what matrix shape does V need to be? Normally V is depending only on t, and is thus a [1 by t] vector. Now V is depending on both x as t, thus i would expect it to be a [x by y] vector, correct?
Thank you
It took long, but hey its not a normal everyday problem.
function f = FN( t, Y, dx, xend, D, a, b, eps, I )
% Fitzhug-Nagumo model with spatial diffusion.
% t = Tijd
% X = [V; W]
% dx = stepsize
% xend = Size van x
% Get the column vectors dV and dW from Y
V = Y( 1:xend/dx );
W = Y( xend/dx+1:end );
% Function
Vxx = (V([2:end 1])+V([end 1:end-1])-2*V)/dx^2;
dVdt = D*Vxx + V .* (V-a) .* (1-V) - W + I ;
dWdt = epsilon .* (V-b*W);
f = [dVdt ; dWdt];
Both V as W are column vectors with a size of 1:(xend/dx)
Method of calling:
V = zeros(xend/dx,1);
W = zeros(xend/dx,1);
% Start Boundaries
% V(x, 0) = 0.8 for 4 < x < 5
% V(x, 0) = 0.1 for 3 < x < 4
V( (4/dx+1):(5/dx-1) ) = 0.8;
V( (3/dx+1):(4/dx-1) ) = 0.1;
Y0 = [V; W];
t = 0:0.1:400;
options = '';
[T, Y] = ode45( #FN, t, Y0, options, dx, xend, D, a, b, eps, I );