% STD_GETTRIALSIND - return the index of the trials that comply with the
% defined values from trialinfo
%
% Usage:
% >> trialindsx = std_gettrialsind('testnewstudyfile.mat', 'type', { 'C' 'X' 'Y' }, ...
% 'load', [0 1 2 3 4 5 6], 'uncertainty1',[1 2])
% >> trialindsx = std_gettrialsind('testnewstudyfile.mat', 'load', [0 1 2 3 4 5 6])
% >> [trialindsx cont] = std_gettrialsind('testnewstudyfile.mat', 'load', [0 1 2 3 4 5 6], ...
% 'duration', '0<100', 'rt', '')
%
% Inputs:
% filename - Filename of the study file, the structure contained in that
% file or, the trialinfo structure for that specific subject
% Beware of the value type: cell or string is categorical string variables,
% numerical array is categorical numerical variables, empty string or string
% containing "<" character is for continuous variables. For continuous variables,
% a range may be entered. Enter empty for the whole value range.
%
% varargin - Pairs of inputs ,varname(string),varvalues . (see Usage)
%
% Optional inputs:
% ['var'] - [cell or array] ['var'] is the name of one independent
% variable followed by a value or a list of value for this
% variable. To obtain values for a continuous variable,
% use '' for all the values or a range '0<100' to get values
% within a given range (see example below).
%
% Outputs:
% trialind - trial indices
% cont - optional continuous variable value for these indices
%
% Example:
% >> trialindsx = std_gettrialsind('testnewstudyfile.mat', 'type', { 'C' 'X' 'Y' }, ...
% 'load', [0 1 2 3 4 5 6], 'uncertainty1',[1 2])
% >> trialindsx = std_gettrialsind('testnewstudyfile.mat', 'load', [0 1 2 3 4 5 6])
% >> [trialindsx cont] = std_gettrialsind('testnewstudyfile.mat', 'load', [0 1 2 3 4 5 6], ...
% 'duration', '0<100', 'rt', '')
% Authors: Arnaud Delorme
% Ramon Martinez-Cancino
%
% Copyright (C) 2015 Ramon Martinez-Cancino, UCSD, INC, SCCN
%
% This file is part of EEGLAB, see http://www.eeglab.org
% for the documentation and details.
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are met:
%
% 1. Redistributions of source code must retain the above copyright notice,
% this list of conditions and the following disclaimer.
%
% 2. Redistributions in binary form must reproduce the above copyright notice,
% this list of conditions and the following disclaimer in the documentation
% and/or other materials provided with the distribution.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
% THE POSSIBILITY OF SUCH DAMAGE.
function [trialindsx, eventvals] = std_gettrialsind(filename,varargin)
trialindsx = [];
eventvals = [];
if nargin < 1
help std_gettrialsind;
return;
end
% Input stuff
try
if length(varargin) == 1
varargin = varargin{:}; % Call from std_readfile or other func
end
varsin = varargin;
if ~isempty( varargin )
for i = 1:2:numel(varsin)
queryvars.(varsin{i}) = varsin{i+1};
end
else
queryvars = [];
end
catch
disp('std_gettrialsind() error: calling convention {''key'', value, ... } error'); return;
end
% Checking if first entry is string or struct
if isstruct(filename)
if isfield(filename,'trialinfo')
trialinfo = filename.trialinfo;
else
trialinfo = filename;
%warning('std_gettrialsind: First input assumed as trialinfo structure');
end
else
% Loading file
trialinfo = load(filename,'-mat', 'trialinfo');
trialinfo = trialinfo.trialinfo;
end
% --- Query ---
varnames = fieldnames(queryvars);
hits = zeros(length(trialinfo),length(varnames));
for iVar = 1 : length(varnames)
dattrials = {trialinfo.(varnames{iVar})};
indvarvals = queryvars.(varnames{iVar});
% case of continuous variable
if ischar(indvarvals) && (isempty(indvarvals) || any(indvarvals == '<'))
if ischar(dattrials{1})
error(sprintf('Type error - excepting string numerical for field %s in data file', varnames{iVar}));
end
if isempty(indvarvals)
hits(:,iVar) = ~cellfun(@isempty, dattrials);
else % test for range
indGreater = find(indvarvals == '<');
if length(indGreater) ~= 1, error('Undefined range for continuous var'); end
if any(indvarvals == '='), error('<= or =< not allowed for continuous var'); end
lowerBound = str2num(indvarvals(1:indGreater-1));
upperBound = str2num(indvarvals(indGreater+1:end));
hits(:,iVar) = cellfun(@(x)(~isempty(x)&&x>lowerBound&&x<upperBound), dattrials);
end
dattrials(~hits(:,iVar)) = { NaN };
eventvals(end+1,:) = [ dattrials{:} ];
else
% case of categorical variable
if ischar(dattrials{1})
if ischar(indvarvals)
indvarvals = {indvarvals};
end
if ~iscell(indvarvals)
error(sprintf('Type error - excepting numerical values for field %s', varnames{iVar}));
end
for iVal = 1:length(indvarvals) % programmed for speed - AD
hits(strmatch(indvarvals{iVal}, dattrials, 'exact'),iVar) = 1;
% older version not compatible with old Matlab
% hits(:,iVar) = hits(:,iVar) || strncmp(indvarvals{iVal}, dattrials, 100)';
end
else
if iscell(indvarvals)
error(sprintf('Type error - excepting string values for field %s', varnames{iVar}));
end
excl = find(cellfun(@isempty, dattrials));
if ~(isempty(excl))
[dattrials{excl}] = deal(nan);
end
dattrials = [ dattrials{:} ];
for iVal = 1:length(indvarvals) % programmed for speed - AD
hits(:,iVar) = hits(:,iVar) | [ dattrials == indvarvals(iVal) ]';
end
end
end
end
% Retrieving overlapped values
hits = sum(hits,2);
trialindsx = find(hits == length(varnames));
if ~isempty(eventvals)
eventvals = eventvals(:,trialindsx);
end