Input combination of string and number to a function which only accepts numbers?

I am using EEGLAB on Matlab and would like to cut sections of the EEG between blocks. In EEGLAB the function is pop_select which accepts numbers separated by semicolon, e.g. [0 100; 120 150; 160 170], to select e.g. the period from 0 to 100 ms, etc.
I would like to create this input as an array, input_array, which is fed directly to the function, e.g. pop_select( EEG, 'notime', input_array), since I don't know beforehand which time periods I want to select.
However, the input must be separated by semicolon, which means that input_array contains strings and cannot be converted to a number array. Is there a way to overcome this?

2 commentaires

How exactly does that mean input_array contains strings?
I only see a 3x2 numeric array.
[0 100; 120 150; 160 170]
ans = 3×2
0 100 120 150 160 170
When constructing the array I need to insert the semicolon as a string. The function pop_select will not accept the input without semicolon separating the time intervals. So ";" is a string, so is "[" and "]" which I have to put at the end and start of the input, respectively.

Connectez-vous pour commenter.

 Réponse acceptée

MATLAB uses semicolons to construct arrays. A semicolon represents the end of a row. Anything following it is placed on the next row.
You can learn more about this in Ch 4 of MATLAB Onramp.

9 commentaires

The problem is I need to pass an entire expression consisting of both strings, "[", "]" and ";" as well as numbers. I cannot pass e.g. [0 100] [125 150] - the numbers in brackets must be separated by a semicolon.
Go through Ch 4. You do not appear to yet understand MATLAB syntax.
Thank you, I will do that, but let me explain the problem a bit better with examples from my script.
EEG.event.type contains event codes formatted as string. '88' and '99' marks the start and end of a block in the EEG session. I start by saving these events in a string array and their time points are converted to seconds as per the EEG sampling rate.
boundaryStart = find(strcmp({EEG.event.type}, '88'));
boundaryEnd = find(strcmp({EEG.event.type}, '99'));
boundaryStart_sec = [EEG.event(boundaryStart).latency]*1/EEG.srate;
boundaryEnd_sec = [EEG.event(boundaryEnd).latency]*1/EEG.srate;
For example:
boundaryStart_sec =
Columns 1 through 10
14.004 74.221 197.12 292.9 388.25 481.98 577.12 675.46 775.76 873.22
Column 11
968.02
and
boundaryEnd_sec =
Columns 1 through 10
40.743 161.16 283.66 380.89 475.19 569.82 665.91 761.84 865.15 960.26
Column 11
1056.1
I want to remove the EEG data between blocks and can do this "by hand" with pop_select:
EEG = pop_select( EEG, 'notime', ...,
[EEG.xmin boundaryStart_sec(2); ...,
boundaryEnd_sec(2) boundaryStart_sec(3); ...,
boundaryEnd_sec(3) boundaryStart_sec(4); ...,
boundaryEnd_sec(4) boundaryStart_sec(5); ...,
boundaryEnd_sec(5) boundaryStart_sec(6); ...,
boundaryEnd_sec(6) boundaryStart_sec(7); ...,
boundaryEnd_sec(7) boundaryStart_sec(8); ...,
boundaryEnd_sec(8) boundaryStart_sec(9); ...,
boundaryEnd_sec(9) boundaryStart_sec(10); ...,
boundaryEnd_sec(10) boundaryStart_sec(11); ...,
boundaryEnd_sec(11) EEG.xmax]);
end
Now I want this input to be automatic since the number of blocks is different for each dataset. pop_select only accepts numbers in brackets separated by ;.
I do this:
str(1) = strcat("[", num2str([EEG.xmin boundaryStart_sec(2)]), "; ");
for k = 2:length(boundaryStart_sec)-1
str(k) = strcat(num2str([boundaryEnd_sec(k) boundaryStart_sec(k+1)]), "; ")
k=k+1;
end
input_str = strjoin(str)
string = str2double(input_str)
But string is NaN since input_str also contains [, ] and ;.
I take full responsibility for the stupidity of this solution, which does not work.
You are thinking about this too literally. Don't create a string. Create a numeric array, which is covered in Ch 4 of MATLAB Onramp.
Test the following in your code to convince yourself it works.
input_array = [ EEG.xmin boundaryStart_sec(2);
boundaryEnd_sec(2) boundaryStart_sec(3);
boundaryEnd_sec(3) boundaryStart_sec(4);
boundaryEnd_sec(4) boundaryStart_sec(5);
boundaryEnd_sec(5) boundaryStart_sec(6);
boundaryEnd_sec(6) boundaryStart_sec(7);
boundaryEnd_sec(7) boundaryStart_sec(8);
boundaryEnd_sec(8) boundaryStart_sec(9);
boundaryEnd_sec(9) boundaryStart_sec(10);
boundaryEnd_sec(10) boundaryStart_sec(11);
boundaryEnd_sec(11) EEG.xmax];
EEG = pop_select( EEG, 'notime', input_array)
And to prove that semicolons are just for creating a new row, you don't even need them if you actually use a linefeed when building your array.
input_array = [ EEG.xmin boundaryStart_sec(2)
boundaryEnd_sec(2) boundaryStart_sec(3)
boundaryEnd_sec(3) boundaryStart_sec(4)
boundaryEnd_sec(4) boundaryStart_sec(5)
boundaryEnd_sec(5) boundaryStart_sec(6)
boundaryEnd_sec(6) boundaryStart_sec(7)
boundaryEnd_sec(7) boundaryStart_sec(8)
boundaryEnd_sec(8) boundaryStart_sec(9)
boundaryEnd_sec(9) boundaryStart_sec(10)
boundaryEnd_sec(10) boundaryStart_sec(11)
boundaryEnd_sec(11) EEG.xmax];
EEG = pop_select( EEG, 'notime', input_array)
Since boundaryEnd_sec and boundaryStart_sec are already vectors, you could do it even simpler doing this:
input_array = [EEG.xmin boundaryEnd_sec(2:end); boundaryStart_sec(2:end) EEG.xmax]';
EEG = pop_select( EEG, 'notime', input_array)
"...pop_select only accepts numbers in brackets separated by ;."
Then why are you converting everything to character?
I believe your pattern is:
% Sample data
boundaryEnd_sec = 1:11
boundaryEnd_sec = 1×11
1 2 3 4 5 6 7 8 9 10 11
boundaryStart_sec = 0.5:10.5
boundaryStart_sec = 1×11
0.5000 1.5000 2.5000 3.5000 4.5000 5.5000 6.5000 7.5000 8.5000 9.5000 10.5000
EEG = struct('xmin', 0, 'xmax', 12);
endings = [EEG.xmin; reshape(boundaryEnd_sec(2:end), [], 1)];
starts = [reshape(boundaryStart_sec(2:end), [], 1); EEG.xmax];
M = [endings, starts]
M = 11×2
0 1.5000 2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 8.0000 8.5000 9.0000 9.5000 10.0000 10.5000
This assumes boundaryEnd_sec and boundaryStart_sec each have at least 2 elements. No string processing necessary. The fact that you're eliminating the first element of both boundaryEnd_sec and boundaryStart_sec feels a little odd; usually I'd expect you'd skip the first element of one and the last element of the other.
Martin Randau
Martin Randau le 15 Juil 2021
Modifié(e) : Martin Randau le 15 Juil 2021
I thank you all very much for the assistance. I've learnt something new today.
This code did the trick:
endings = [EEG.xmin; reshape(boundaryEnd_sec(2:end), [], 1)];
starts = [reshape(boundaryStart_sec(2:end), [], 1); EEG.xmax];
deleteData = [endings, starts];
EEG = pop_select( EEG, 'notime', deleteData);
I eliminate the first two items in start and end because the firls block is a training block not included in the analysis. :)
Incidentally, that produces exactly the same result as this code I shared earlier:
input_array = [EEG.xmin boundaryEnd_sec(2:end); boundaryStart_sec(2:end) EEG.xmax]';
EEG = pop_select( EEG, 'notime', input_array)
Yes, sorry, I forgot to add that both solutions work! Thanks again! :)

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

Community Treasure Hunt

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

Start Hunting!

Translated by