-
Notifications
You must be signed in to change notification settings - Fork 5
Regressors
The toolbox supports both univariate analysis (e.g. ANOVA) and multivariate pattern analysis. These different types of statistics are specified using a common language for defining different classes of events in an experiment.
Information about events in the experiment must be stored in an events
structure. This is a vector structure that can have any number of
different fields to specify different things about an experiment.
Each element of the events structure gives information about one
event. See Events for details. To run a statistical
analysis, specific information must be extracted from the events
structure using regressor definitions (generally referred to in the
toolbox as reg_defs
or event_bins
).
Information about factors used in statistical tests are stored in regressors. A regressor is a vector, where each element is either an integer (from 1 to N, where N is the number of different conditions) or NaN (to indicate events where that regressor is undefined). For example, if you have two conditions that alternate, and there are ten events, your regressor for those conditions would be:
reg = [1 2 1 2 1 2 1 2 1 2];
This simply labels each event as belonging to one of two different conditions.
The toolbox contains functions for creating regressor vectors from
events structures. Generally, statistical analysis functions call
make_event_index
to create regressors. This function takes a number
of different types of input to create regressors in different ways.
The simplest way to make a regressor is by giving the name of a field
of the events structure; this will simply use that field as the
regressor. The field must contain numeric, logical, or char data. It
will be translated into sequential integers, which label each unique
value of the field. For example:
>> events = struct('condition', {'A' 'B' 'B' 'A' 'A' 'A' 'B'});
>> [index, levels] = make_event_index(events, 'condition')
index =
1
2
2
1
1
1
2
levels =
'A'
'B'
The 'A' and 'B' conditions are translated into 1 and 2 in the output
regressor, here referred to as an "index". The levels
output gives
the original label for each condition.
The above method works well for simple regressor definitions, where
you already have a field on the events structure corresponding to the
factor of interest. However, sometimes it is helpful to define more
complex conditions on the fly, without creating a new field.
make_event_index
also allows one to create regressors using
arbitrary logical expressions.
An event filter is an expression that can operate on any field in the
events struct (as long as the values of the field are all of the same
type), and must produce a logical value for each event. It is
specified as a string, and will be evaluated on each element of the
event structure to determine which events will be included.
inStruct
is used to evaluate event filters. Typically, event fields
used must have the same type for every element of the events
structure, so that the field can be placed in a numeric array or a
cell array of strings. Then the filter is evaluated, giving a logical
array the same length as events; elements that are true specify events
that should be included in the filter. For example, if I want to
include only condition A events:
>> events = struct('condition', {'A' 'B' 'B' 'A' 'A' 'A' 'B'});
>> inStruct(events, 'strcmp(condition, ''A'')')
ans =
1 0 0 1 1 1 0
The expression, 'strcmp(condition, ''A'')'
, is evaluated for each
event. The output of inStruct
is a logical array that is true for
events that matched the expression.
What inStruct
is doing internally is similar to the following:
>> conditions = {events.condition}; % get a cell array of strings with condition labels
>> strcmp(conditions, 'A') % get events for which condition is "A"
ans =
1 0 0 1 1 1 0
Event filters are often used to grab subsets of an events structure,
using filterStruct
. The next section illustrates how to use event
filters to create a regressor.
Say I want to compare condition A and B events, but I only want to include correct events:
>> events = struct('condition', {'A' 'B' 'B' 'A' 'A' 'A' 'B'}, 'correct', {1 1 0 0 1 1 0});
>> disp_events(events)
condition correct
A 1
B 1
B 0
A 0
A 1
A 1
B 0
>> reg_def = {'strcmp(condition, ''A'') & correct==1', 'strcmp(condition, ''B'') & correct==1'};
>> [index, levels] = make_event_index(events, reg_def)
index =
1
2
NaN
NaN
1
1
NaN
levels =
'strcmp(condition, 'A') & correct==1'
'strcmp(condition, 'B') & correct==1'
Here, reg_def
is a cell array, where each cell contains an event
filter. The events for which reg_def{1}
is true correspond to
condition 1, and the events for which reg_def{2}
is true correspond
to condition 2. All the other events are given a NaN, since they
belong to none of the conditions. In this case, the levels
correspond to the filter strings specified by the user. Some
functions include an event_labels
input that allows one to specify
other labels for the different conditions.
Note that, because in the regressor each event only gets one label,
the two event filters must not overlap. If they do,
make_event_index
will throw an error.
The above examples work for most cases where one is working with a
single factor. However, often for statistical tests, one is
interested in the interactions of multiple factors (for example, when
running a two-way ANOVA). For example, I might be interested in a 2X2
design, looking at condition A and B, crossed with whether the trial
was correct or not. To create this regressor, I would simply specify
the list of fields, and make_event_index
will label each combination
of the two fields:
>> events = struct('condition', {'A' 'B' 'B' 'A' 'A' 'A' 'B'}, 'correct', {1 1 0 0 1 1 0});
>> disp_events(events)
condition correct
A 1
B 1
B 0
A 0
A 1
A 1
B 0
>> [index, levels] = make_event_index(events, {'condition' 'correct'})
index =
2
4
3
1
2
2
3
levels =
'A' [0]
'A' [1]
'B' [0]
'B' [1]
make_event_index
automatically finds events corresponding to each
conjunction of the two conditions (A-incorrect, A-correct,
B-incorrect, B-correct). In the regressor, each of these conditions
is given a label from 1-4. The order in which conditions are labeled
is arbitrary, though it's generally sensible (alphabetic order for
factor 1, then for factor 2). To determine the original label for an
event, look at the row of levels corresponding to the number for that
event in index
. levels{:,1}
corresponds to factor 1 (i.e. the
first field specified), and levels{:,2}
corresponds to factor 2.