user8490437
user8490437

Reputation:

determine lag between two vector

I want to find the minimum amount of lag between two vector , I mean the minimum distance that something is repeated in vector based on another one for example for

x=[0 0 1 2 2 2 0 0 0 0]
y=[1 2 2 2 0 0 1 2 2 2]

I want to obtain 4 for x to y and obtain 2 for y to x .

I found out a finddelay(x,y) function that works correctly only for x to y (it gives -4 for y to x).

is there any function that only give me lag based on going to the right direction of the vector? I will be so thankful if you'd mind helping me to get this result

Upvotes: 0

Views: 439

Answers (1)

gnovice
gnovice

Reputation: 125874

I think this may be a potential bug in finddelay. Note this excerpt from the documentation (emphasis mine):

X and Y need not be exact delayed copies of each other, as finddelay(X,Y) returns an estimate of the delay via cross-correlation. However this estimated delay has a useful meaning only if there is sufficient correlation between delayed versions of X and Y. Also, if several delays are possible, as in the case of periodic signals, the delay with the smallest absolute value is returned. In the case that both a positive and a negative delay with the same absolute value are possible, the positive delay is returned.

This would seem to imply that finddelay(y, x) should return 2, when it actually returns -4.

EDIT:

This would appear to be an issue related to floating-point errors introduced by xcorr as I describe in my answer to this related question. If you type type finddelay into the Command Window, you can see that finddelay uses xcorr internally. Even when the inputs to xcorr are integer values, the results (which you would expect to be integer values as well) can end up having floating-point errors that cause them to be slightly larger or smaller than an integer value. This can then change the indices where maxima would be located. The solution is to round the output from xcorr when you know your inputs are all integer values.

A better implementation of finddelay for integer values might be something like this, which would actually return the delay with the smallest absolute value:

function delay = finddelay_int(x, y)
  [d, lags] = xcorr(x, y);
  d = round(d);
  lags = -lags(d == max(d));
  [~, index] = min(abs(lags));
  delay = lags(index);
end

However, in your question you are asking for the positive delays to be returned, which won't necessarily be the smallest in absolute value. Here's a different implementation of finddelay that works correctly for integer values and gives preference to positive delays:

function delay = finddelay_pos(x, y)
  [d, lags] = xcorr(x, y);
  d = round(d);
  lags = -lags(d == max(d));
  index = (lags <= 0);
  if all(index)
    delay = lags(1);
  else
    delay = lags(find(index, 1)-1);
  end
end

And here are the various results for your test case:

>> x = [0 0 1 2 2 2 0 0 0 0];
>> y = [1 2 2 2 0 0 1 2 2 2];
>> [finddelay(x, y) finddelay(y, x)]  % The default behavior, which fails to find 
                                      %   the delays with smallest absolute value
ans =

     4    -4

>> [finddelay_int(x, y) finddelay_int(y, x)]  % Correctly finds the delays with the
                                              %   smallest absolute value
ans =

    -2     2

>> [finddelay_pos(x, y) finddelay_pos(y, x)]  % Finds the smallest positive delays

ans =

     4     2

Upvotes: 2

Related Questions