From 72ed0e23f73390e21aa20242b29523b7b9531bf4 Mon Sep 17 00:00:00 2001 From: Dominik Bach Date: Mon, 6 May 2024 16:40:46 +0200 Subject: [PATCH 1/2] new function to handle multiple channels at a time --- src/pspm_multi_channel.m | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/pspm_multi_channel.m diff --git a/src/pspm_multi_channel.m b/src/pspm_multi_channel.m new file mode 100644 index 00000000..5ee02f1d --- /dev/null +++ b/src/pspm_multi_channel.m @@ -0,0 +1,74 @@ +function [sts, outchannel] = pspm_multi_channel(fhandle, channels, varargin) +% ● Description +% pspm_multi_channel applies the same pre-processing function to multiple +% channels in the same data file. This works by calling the pre-processing +% function multiple times and so does accelerate processing time. It +% creates the required loop and handles any processing errors. +% ● Format +% [sts, channel_index] = pspm_multi_channel(function, channels, argument1, argument2, ..., options) +% ● Arguments +% fhandle: [char or function handle] Preprocessing function +% channels: [char, vector, cell array] Channel specification +% 1. Eyetracker channels without lateralisation +% specification (_r or _l) will be expanded to include +% both eyes (i.e. 'pupil' will be expanded to +% {'pupil_r', 'pupil_l'}, which work on the last +% channel of this type. +% 2. Any other valid channel identifier of type 'char' +% will work on all channels of this type in the file. +% 3. Any numerical vector or cell array will work on +% the specified channels. +% argument1, ...: all input arguments for the pre-processing function +% options: must always be specified as the last input argument +% ● Output +% sts: Status determining whether the execution was +% successful (sts == 1) or not (sts == -1) +% channel_index: Index of the generated channels. Any unsuccesful +% pre-processing call leads to a NaN index +% ● History +% Written in 2024 by Dominik R Bach (Uni Bonn) +% + +%% 1 Initialise +global settings; +if isempty(settings) + pspm_init; +end +sts = -1; +outchannel = NaN; + +%% 3 Expand channels +if ischar(channels) && ismember(channels, settings.eyetracker_channels) + [sts, eye] = pspm_find_eye(channels); + if sts < 1, return; end + if strcmpi(eye, '') + channels = {[channels, '_r'], [channels, '_l']}; + end +end + +if ischar(channels) + % all pre-processing functions take filename as first argument + fn = varargin{1}; + [sts, infos, data, filestruct] = pspm_load_data(fn, channels); + if sts < 1, return; end + channels = filestruct.posofchannels; +elseif isnumeric(channels) + channels = num2cell(channels); +elseif ~iscell(channels) + warning('ID:invalid_input', 'Channels must be numeric, char or cell.') + return +end + +%% 4 Process channels +options = varargin{end}; +varargin(end) = []; +for i_channel = 1:numel(channels) + options.channel = channels{i}; + [csts(i), outchannel] = feval(fhandle, varargin{:}, options); + if csts(i) == 1 + channel_index(i) = outchannel; + else + channel_index(i) = NaN; + end +end +sts = 1; \ No newline at end of file From 563f0701d8f3dec6a950885d72aa24a521a56d96 Mon Sep 17 00:00:00 2001 From: Dominik Bach Date: Mon, 6 May 2024 18:16:13 +0200 Subject: [PATCH 2/2] expand functionality --- src/pspm_multi_channel.m | 42 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/pspm_multi_channel.m b/src/pspm_multi_channel.m index 5ee02f1d..298cfed1 100644 --- a/src/pspm_multi_channel.m +++ b/src/pspm_multi_channel.m @@ -1,4 +1,4 @@ -function [sts, outchannel] = pspm_multi_channel(fhandle, channels, varargin) +function [sts, channel_index] = pspm_multi_channel(fhandle, channels, varargin) % ● Description % pspm_multi_channel applies the same pre-processing function to multiple % channels in the same data file. This works by calling the pre-processing @@ -8,16 +8,18 @@ % [sts, channel_index] = pspm_multi_channel(function, channels, argument1, argument2, ..., options) % ● Arguments % fhandle: [char or function handle] Preprocessing function -% channels: [char, vector, cell array] Channel specification -% 1. Eyetracker channels without lateralisation +% channels: [char, vector, cell array] Channel specifications: +% 1. 'gaze' will be expanded to {'gaze_x_r', 'gaze_y_r', +% 'gaze_x_l', 'gaze_y_l'} +% 2. Eyetracker channels without lateralisation % specification (_r or _l) will be expanded to include % both eyes (i.e. 'pupil' will be expanded to % {'pupil_r', 'pupil_l'}, which work on the last % channel of this type. -% 2. Any other valid channel identifier of type 'char' -% will work on all channels of this type in the file. -% 3. Any numerical vector or cell array will work on -% the specified channels. +% 3. Any other valid channel identifier of type 'char' +% will be expanded to all channels of this type in the file. +% 4. Any numerical vector or cell array will work on +% the specified channels exactly. % argument1, ...: all input arguments for the pre-processing function % options: must always be specified as the last input argument % ● Output @@ -38,11 +40,15 @@ outchannel = NaN; %% 3 Expand channels -if ischar(channels) && ismember(channels, settings.eyetracker_channels) - [sts, eye] = pspm_find_eye(channels); - if sts < 1, return; end - if strcmpi(eye, '') - channels = {[channels, '_r'], [channels, '_l']}; +if ischar(channels) + if strcmpi(channels, 'gaze') + channels = {'gaze_x_r', 'gaze_y_r', 'gaze_x_l', 'gaze_y_l'}; + elseif ismember(channels, settings.eyetracker_channels) + [sts, eye] = pspm_find_eye(channels); + if sts < 1, return; end + if strcmpi(eye, '') + channels = {[channels, '_r'], [channels, '_l']}; + end end end @@ -51,7 +57,7 @@ fn = varargin{1}; [sts, infos, data, filestruct] = pspm_load_data(fn, channels); if sts < 1, return; end - channels = filestruct.posofchannels; + channels = num2cell(filestruct.posofchannels); elseif isnumeric(channels) channels = num2cell(channels); elseif ~iscell(channels) @@ -63,12 +69,12 @@ options = varargin{end}; varargin(end) = []; for i_channel = 1:numel(channels) - options.channel = channels{i}; - [csts(i), outchannel] = feval(fhandle, varargin{:}, options); - if csts(i) == 1 - channel_index(i) = outchannel; + options.channel = channels{i_channel}; + [csts, outchannel] = feval(fhandle, varargin{:}, options); + if csts == 1 + channel_index(i_channel) = outchannel; else - channel_index(i) = NaN; + channel_index(i_channel) = NaN; end end sts = 1; \ No newline at end of file