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

15 vues (au cours des 30 derniers jours)
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?
  2 commentaires
Lauren
Lauren le 17 Avr 2019
Wasn't sure if the graph attached properly so here is a picture of it instead.

Connectez-vous pour commenter.

Réponse acceptée

Bob Thompson
Bob Thompson le 17 Avr 2019
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');
  5 commentaires
Lauren
Lauren le 17 Avr 2019
or actually I think a better way to write it is
elseif v(i)-v(i+1)<=0.05*v(i)
x=i+1;
end
so back to the example, 6.2 - 6.0 <= (0.05*6.2) or 0.2<=0.31 so since v(i+1) is no more than a 5% difference from v(i)....I would want to make x=i+1
Bob Thompson
Bob Thompson le 17 Avr 2019
Both of those new statements create logical results, because the ultimate operator is the comparison >= or <=. If we break things down a bit you have three parts 1) v(i+1), 2) () >= (), and 3) 0.05*v(i). By order of operations the inequality is the last operation to happen, so your result must be logical in nature.
When we do something similar with the previous find setup, we have basically the same three portions, but there is a fourth, the find() function itself, that ends up being the final operator, and causes the lack of logical result that you were experiencing.
TL:DR either one of those new setups should work, although I would suggest naming x as a different variable. That way, if you encounter both situations in a loop you can capture both results.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Linear Algebra dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by