MATLAB: Help finding the first minimum value in an array and indexing the value in a new array!!!

arrayfirst minimumindexing arrayloop error

Hi, I am trying to run code that calls in the function below, and I am having problems with the final for loop. Basically, I am trying to take an array (v), find the point at which the first minimum value occurs in the array, and assign that point or timelag to a new array called (x). However, my data doesn't always have a first minimum so I had to create another loop (else) that is supposed to find the first value within array (v) whose difference is less than or equal to 5% of the value before it. Once it finds that value, its supposed to take the point (i) where that value occurs and assign it to a new array (x).
function [tau,v_AMI]=AMI(data, L)
N=length(data);
bins=128; %number of bins used for histogram calculation
%bins=floor(1+log2(N-L)+0.5);
epsilon = eps;
data = data - min(data); % making all the data points positive
data = 1+ floor(data/(max(data)/(bins-epsilon))); %scaling the data
v=zeros(L,1); %create a zero vector
overlap=N+1-L;
increment= 1/overlap;
one = ones(overlap,1); %create a column vector with all elements being one
pA = sparse (data(1:overlap),one,increment);
for lag = 0: L -1
pB = sparse(one, data(1+lag:overlap+lag), increment);
pAB = sparse(data(1:overlap),data(1+lag:overlap+lag),increment);
[A, B, AB]=find(pAB);
v(lag+1)=sum(AB.*log2(AB./(pA(A).*pB(B)'))); %Average Mutual Information
end
v_AMI=v;
%Take time_lag when 1st min(I(time_lag))occurs for values of time_lag near
%this minimum, the coordinate system produced by time delay vector is
%esentially as good as that of the time_lag which is the actual 1st min(I(time_lag))
for i = 1:length(v)-1
if (find((v(i)<v(i+1)) && (v(i)<v(i-1))))==1 %(find(v==min(v),1,'first'))
x(i)=i;
else
myindexes=0.95*v(i);
(find(v(i+1)<=myindexes))==1;
x(i)=i;
end
end
A=sparse(x);
A=find(A);
tau=A(1);
I've tried writing the loop as the commented portion and that didn't seem to work. I've also tried writing the if statement as
if (find((v(i)<v(i+1)) && (v(i)<v(i-1)),1,'first'))
and that may have worked but the second loop didn't. I originally had the 2nd loop written as
if (find(v(i)<=0.95*v(i-1),1,'first')
but had to get creative because it kept giving me an error "must be real numbers or logicals". Which makes sense because you can't have decimals as indices (e.g. v(3.9154)). I also tried running it as
else
myindexes=0.95*v(i);
(find(v(i+1)<=myindexes,1,'first'));
x(i)=i;
end
which actually ran without giving me errors, but its not working appropriately because it calculated tau as 1 for all files.
The code used to call in the function is below:
directory_name = uigetdir(pwd,'Select data directory');
directory_name = ([directory_name '/']);
files = dir([directory_name,'*txt']);
if isempty(files)
msgbox('No raw files in this directory')
end
FileName=[];
for i=1:length(files)
filename=files(i).name;
data = load(filename,'-ascii');
filename=filename(1:end-4);
FileName=[FileName; cellstr(filename)];
L=32; % window size for average mutual information
[tau,v_AMI]=AMI(data, L); %Find the first minimum average mutual information
end
To give you an idea of the data array v, I included a graph of v for one of the files that doesn't have a first minimum value.
How might I fix the loops to run appropriately?

Best Answer

Part of the issue you're having is that your if statement doesn't have an actual condition in it.
if (find((v(i)<v(i+1)) && (v(i)<v(i-1))))==1 %(find(v==min(v),1,'first'))
All of these 'conditions' are going to return specific values, which may or may not make logical sense. Specifically, using the find() produces a non logical result. If you want to make this a proper logic check for the if then you need to adust your statement to be something more like:
if ~isempty(find(v==min(v),1,'first')) % Determines if the result exists
Also, there should always be a minimum value, assuming the array v is not empty or NaN. Even if all of the values are the same, the min() function should return that value.
Because you're only looking for a single value (the first minimum) I don't know that the loop is even necessary (unless v is not an array of doubles). Try something like this?
x = find(v==min(v),1,'first');