How to detect positions in a signal where the distance between two values is less than x?

2 views (last 30 days)
I have a cell array with 864 boolean vectors containing information about when a response was detected. Each vector has 3750000 elements. All elements are logical 0s except where a response was detected. There, the element is a logical 1 - this encodes timing. The array variable is shown below along with one of the vectors it contains. I want to find where the time between responses is 1275 units or less. The total time in the vector is 3750000 (same as the number of samples). I also want to know how long the signal lasts where each incidence of inter-response-interval is 1275 units or less. The end goal is a measurement of number of burst responses and duration of each burst response. I don't really know where to start. Something with the "find" function perhaps?
Name Size Bytes Class Attributes
spkTrain 1x864 11520090624 cell
1×1 cell array
{3750000×1 single}
  1 Comment
Anas Khan
Anas Khan on 18 Dec 2020
Edited: Anas Khan on 18 Dec 2020
If spkT is a vector containing just the times where a signal is detected e.g., [1 21 3456 300000 3750000], what if I start with something like this? Can someone help me complete this? I also included how I am converting spkT into a vector with 1s and 0s that is 3750000 elements long.
whos spkT
Name Size Bytes Class Attributes
spkT 6154x1 49232 double
train = zeros(3750000,1); % Create zeros vector to represent FALSE values
train(spkT) = 1; % Index 1s (TRUEs) into positions where signals occured along 3750000 number line
spkTrains(:,cnt) = train; % Create matrix where columns are channels and rows are signals in each channel
Intervals = diff(spkT) % Should give the time elapsed between subsequent signals
Intervals(1:20)
ans =
16
4
16
13
1
30
40
1
3
1
42
68
57
66
61
1
15
1
1
1
BurstIndices = find(Intervals <= 1275) % Should give indices where the time units between signal at time t and t+1 is <= 1275
BurstIndices(1:10)
ans =
1
2
3
4
5
6
7
8
9
10
Not sure how to finish this from here. Problem with this is that it does not recognize that there are discrete bursts scatterd throughout the time series. I am not sure how to count bursts when I just get the index for individual spikes within all bursts

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 18 Dec 2020
Attach the cell array in a .mat file. And tell us why it had to be a cell array instead of just a normal, regular logical matrix.
In the meantime, the way I'd do it is to use regionprops() to identify the lengths of all the runs of "responses" - how long each run of 1s is. You could also get the lengths of the times between the responses also if that was of interest.
% Find out where the vector is true and how long those runs are.
props1 = regionprops(logicalVector, 'Area');
allResponseLengths = [props1.Area];
% Find out where the vector is false (0) and how long those runs are.
props0 = regionprops(~logicalVector, 'Area');
allZeroLengths = [props0.Area];
  6 Comments
Anas Khan
Anas Khan on 18 Dec 2020
If we say that b = [1 0 1 0 1 0 1 0 1] is a burst because the 1s are only separated by one 0 (1275 in my actual problem), then I want to count how many 1s are in every "b" given a time series that looks like this [b b b b b b b] and I also want to count the total amount of "b"s.
Image Analyst
Image Analyst on 18 Dec 2020
If you have the image Processing Toolbox it's not too hard. First get rid of runs of less than 1275 0s by temporarily filling in with 1s (note that this might "connect" 1 regions separated by less than 1275 but we'll unseparate them later). Then use strfind() to find where all the 1 regions start. The use those locations as a marker against the original train data to pull out the actual burst (and discard any that may have been temporarily connected by a short run of 0s). Then call regionprops() to get all the lengths of the bursts. I'm including a short test case where we'll try to find bursts that occur after a run of at least 2 zeros. But it will work with your longer data. You'll see it correctly identifies the burst at index 8 with a length of 1 and the burst at index 14 with a length of 2.
It's only 10 lines of code though it looks longer because of all the explanatory comments I put in.
%===============================================================================
% Get data:
% s = load('vector.mat')
% Extract from structure and cast to logical.
% train = logical(s.train);
% minSeparation = 1275;
% Test case for minSeparation = 2
train = logical([1 1 0 1 0 0 0 1 0 1 0 0 0 1 1 0 1])
minSeparation = 2;
%===============================================================================
% Algorithm starts here:
% We don't want to count the burst if the train starts with that burst,
% so to prevent that, make the first element false.
train(1) = false;
% First find the zeros.
% Then we'll throw away any runs of less than 1275 in length
zeroMask = bwareaopen(~train, minSeparation)
% The inverse of this will be where runs of 1s start after runs of zeros.
response = reshape(~zeroMask, 1, []) % Reshape into a row vector.
% Find the starting locations
indexes = strfind(response, [0, 1]) + 1 % Adding to to make index be at the 1 instead of the 0
% Count the bursts.
numBursts = length(indexes)
% Make a new vector with 1s at all the starting locations.
marker = false(size(response));
marker(indexes) = true;
% Pull out only those starting locations from train,
% so for example the 101 at locations 8-10 will show up as 2 regions (as original) instead of 1
response = imreconstruct(marker, train)
% Now we can find the areas
props = regionprops(response, 'Area');
allBurstLengths = [props.Area]
You'll see the individual steps because I left off the semicolons. (Put them back in to speed it up once you've satisfied yourself it works).
train =
1×17 logical array
1 1 0 1 0 0 0 1 0 1 0 0 0 1 1 0 1
minSeparation =
2
zeroMask =
1×17 logical array
0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 0
response =
1×17 logical array
1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1
indexes =
8 14
numBursts =
2
response =
1×17 logical array
0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0
allBurstLengths =
1 2

Sign in to comment.

More Answers (1)

Anas Khan
Anas Khan on 19 Dec 2020
Thanks guys, I'll put some work into it to see if I can extract my parameters using either of your approaches.

Products


Release

R2020b

Community Treasure Hunt

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

Start Hunting!