0

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

Dadep
  • 2,796
  • 5
  • 27
  • 40
  • 1
    I don't really understand with your exemple how you can get `2` comparing the delay between `y` and `x`... ? if you do `+2` to each index of `y` you do not get `x` – Dadep Nov 20 '17 at 18:25
  • no it's not... if you consider vector x, it has 1 in third place.. I want a function that consider every one in x vector(in real signal I have more of them) and calculate the distance from first 1 that happened after 1 in y(for example here it will happen 4 steps later which is in seventh place in y) then we should have different of these distance for large signal and I want minimum of them –  Nov 20 '17 at 18:28

1 Answers1

2

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
gnovice
  • 125,304
  • 15
  • 256
  • 359
  • thanks a lot for your reply. it seems that finddelay([0 y], [0 x]) will give me a correct result for y to x, but again if i use this as finddelay([0 x], [0 y]) it will give me -2 (but i want 4) –  Nov 20 '17 at 18:38
  • what should i do since i work with large number of these vectors and i cant check them individualy –  Nov 20 '17 at 18:40
  • x=[0 0 1 2 2 2 0 0 0 0 1 2 2 2 0 0 1 2 2 2 0 0 0 0 1 2 2 2]; y=[1 2 2 2 0 0 1 2 2 2 0 0 0 1 2 2 2 0 0 0 0 0 0 1 2 2 2 0]; for this from x to y i want 3 and from y to x 1 –  Nov 20 '17 at 18:45
  • @FaribaJangjoo: I'm not sure what the best approach is. I thought maybe something based on `conv`, but that didn't work for all the test cases. You could take a look at what `finddelay` is actually doing with `type finddelay`. Maybe that would help. – gnovice Nov 20 '17 at 19:49
  • 2
    I'm not sure it's a bug. I think it's because the inconsistence of `x` and `y` at the end of the vectors. If you delay `y` by 2, the two last elements is [1 2], while in x it's [ 0 0]. So Matlab gives a delay of -4, such that the vectors will be equal after the delay. Try: `x = [0 0 1 2 2 2 0 0 1 2]; finddelay(y, x)`, and you will get 4 – Adiel Nov 20 '17 at 21:14