Finding islands of zeros in a sequence
Solution 1:
These are the steps I would take to solve your problem in a vectorized way, starting with a given vector sig
:
-
First, threshold the vector to get a vector
tsig
of zeros and ones (zeroes where the absolute value of the signal drops close enough to zero, ones elsewhere):tsig = (abs(sig) >= eps); %# Using eps as the threshold
-
Next, find the starting indices, ending indices, and duration of each string of zeroes using the functions DIFF and FIND:
dsig = diff([1 tsig 1]); startIndex = find(dsig < 0); endIndex = find(dsig > 0)-1; duration = endIndex-startIndex+1;
-
Then, find the strings of zeroes with a duration greater than or equal to some value (such as 3, from your example):
stringIndex = (duration >= 3); startIndex = startIndex(stringIndex); endIndex = endIndex(stringIndex);
-
Finally, use the method from my answer to the linked question to generate your final set of indices:
indices = zeros(1,max(endIndex)+1); indices(startIndex) = 1; indices(endIndex+1) = indices(endIndex+1)-1; indices = find(cumsum(indices));
Solution 2:
You can solve this as a string search task, by finding strings of zeros of length thresh
(STRFIND function is very fast)
startIndex = strfind(sig, zeros(1,thresh));
Note that longer substrings will get marked in multiple locations but will eventually be joined once we add in-between locations from intervals start at startIndex
to end at start+thresh-1
.
indices = unique( bsxfun(@plus, startIndex', 0:thresh-1) )';
Note that you can always swap this last step with the CUMSUM/FIND solution by @gnovice from the linked question.
Solution 3:
function indice=sigvec(sig,thresh)
%extend sig head and tail to avoid 0 head and 0 tail
exsig=[1,sig,1];
%convolution sig with extend sig
cvexsig=conv(exsig,ones(1,thresh));
tempsig=double(cvexsig==0);
indice=find(conv(tempsig,ones(1,thresh)))-thresh;