find variables in a matrix with multiple conditions

Hello everyone,
I have an array of elements, lets say A = 1000x1 wich contains only 0,1, 2 and 3 only. I need to find (storee in variables) and plot
  • where the 0 is repeated four or more time in a row (eg. 1 0 0 0 0 0 0 1 0 0 1 2 3). In this examaple, the only sequence to be retained is formed by the six zeros.
  • where there are 2 or 3's repeated for three or more time in a row (eg. 1 0 1 0 1 1 2 3 3 3). In this example the only sequence to be retained is 2 3 3 3
please find the original matrix in the attachments.
for the following example I would like to have this kind of plot:
where the zero's condition is satisfied the plot goes up (let's say plus 1), no condition satisfied the plot stays in the base line (let's say 0), and finally when the 2 and 3's condition is satisfied the plot goes down (let's say at ,minus 1).
Thanks in advance for you help. This community is really amazing

 Accepted Answer

I have written a function to check for the criteria you have mentioned.
You can also check out this FEX submission for the same - RunLength
%Random input
A = [1 0 0 0 0 0 2 3 1 0 0 0 0 0 0 0 2 3 3 3 0 3 1 2 2 2 2 1 1 1 3 3 3];
%Corresponding outputs
out1 = convert(A,0,4);
out2 = convert(A,[2 3],3);
% +1 for 0
% -1 for [2 3]
out = 1*out1+(-1)*out2;
vec = 1:numel(A);
%plot using stairs to get the square wave form
stairs(vec,out)
grid on
ylim([-2 2])
xticks(vec)
%% Function to check for groups of consecutive apperances above a threshold
function out = convert(in,val,thresh)
%% in - input array (expected to be a vector)
%% val - values to check for as a part of a cluster (expected to be a vector)
%% thresh - threshold for elements in a cluster (expected to be a scalar)
%% out - output (row vector) = 1 for the elements of groups that satisfy the criteria, 0 otherwise
%Check for input
if ~isvector(in)
error('Input array must be a vector');
end
%Check for values
if ~isvector(val)
error('Values must be a vector');
end
%Check for threshold
if ~isscalar(thresh)
error('Threshold must be a scalar');
end
%Convert the input to a row vector
in = reshape(in,1,[]);
%Lazy way of preallocating output
out = 0*in;
%Check for values present in the input
idx=ismember(in,val);
%Starting index of a cluster
ij1=strfind([0 idx 0],[0 1]);
%Ending index of a cluster
ij2=strfind([0 idx 0],[1 0])-1;
%Cluster with members more than a threshold
temp=find((ij2-ij1+1)>=thresh);
%Set the corresponding output as 1
for k=1:numel(temp)
out(ij1(temp(k)):ij2(temp(k)))=1;
end
end

7 Comments

Thanks for your help. Your answer seems pretty smart. I'm gonna check it ina few hours and let you know.
Enzo
Enzo on 9 Oct 2023
Edited: Enzo on 9 Oct 2023
hello @Dyuman Joshi, I have just checked. sorry for being late. It is not working properly. It has a very nice visualization but the final results is not consistent with my desired outcome.
when I change the threshold values, it gives me weird results. It seems like the output1 and 2 are related, thus, when yiu change the treshold it badly affects the entire outcome.
I will opload right now the actual matrix where you can chek yourself.
@Dyuman Joshi please check the attachments a.mat file and try to play around with the treshold values
Ah, okay. That's due to the stairs function.
As you wanted the output in rectangle wave-form, I thought stairs would work. It does, but not completely (see below). The rest of the code is working properly.
Alternatives - You could try using a stem or plot.
Just a note - If you use plot, the output would be in trapezoidal form. If that works for you, then great!
y = load('A.mat');
y = y.spike_train;
%Choosing a small sample
A = y(1:60);
%Corresponding outputs
out1 = convert(A,0,4);
out2 = convert(A,[2 3],3);
% +1 for 0
% -1 for [2 3]
out = 1*out1+(-1)*out2;
vec = 1:numel(A);
figure
%% stem() vs stairs()
stem(vec,out,'b')
grid on
ylim([-2 2])
xticks(vec)
%Using input values as the tick-labels
xticklabels(A)
set(gca,'FontSize',6,'XTickLabelRotation',0)
% Adding Stairs plot for comparison
hold on
stairs(vec,out,'r-')
As you can see, there's a delay in the stairs plot. It drops off an index after a value compared to where it is expected.
%% stem() and plot()
figure
plot(vec,out,'k')
hold on
stem(vec,out,'b')
grid on
ylim([-2 2])
xticks(vec)
%Using input values as the tick-labels
xticklabels(A)
set(gca,'FontSize',6,'XTickLabelRotation',0)
%% Function to check for groups of consecutive apperances above a threshold
function out = convert(in,val,thresh)
%% in - input array (expected to be a vector)
%% val - values to check for as a part of a cluster (expected to be a vector)
%% thresh - threshold for elements in a cluster (expected to be a scalar)
%% out - output (row vector) = 1 for the elements of groups that satisfy the criteria, 0 otherwise
%Check for input
if ~isvector(in)
error('Input array must be a vector');
end
%Check for values
if ~isvector(val)
error('Values must be a vector');
end
%Check for threshold
if ~isscalar(thresh)
error('Threshold must be a scalar');
end
%Convert the input to a row vector
in = reshape(in,1,[]);
%Lazy way of preallocating output
out = 0*in;
%Check for values present in the input
idx=ismember(in,val);
%Starting index of a cluster
ij1=strfind([0 idx 0],[0 1]);
%Ending index of a cluster
ij2=strfind([0 idx 0],[1 0])-1;
%Cluster with members more than a threshold
temp=find((ij2-ij1+1)>=thresh);
%Set the corresponding output as 1
for k=1:numel(temp)
out(ij1(temp(k)):ij2(temp(k)))=1;
end
end
@Enzo, please check out the correction and let me know if this works for you or not.
hi @Dyuman Joshi do not worry. As soon I checked it, i will send you a feedback and accept your answer

Sign in to comment.

More Answers (0)

Products

Release

R2022b

Tags

Asked:

on 6 Oct 2023

Commented:

on 10 Oct 2023

Community Treasure Hunt

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

Start Hunting!