9. using @cortex and @key objects

trialset

With a well-formed @key object, you can retrieve subsets of trials from a @cortex object. For example:

>> c = cortex ('datafile', 1:2);  % create @cortex object
>> k = key ('samplekeyfile.key'); % create @key object
>> ts = trialset (c, k(2));       % retrieve trials that satisfy criteria
                                  % specified in the 2nd key of the @key

The function trialset goes through the @cortex object and checks each trial against the key that was passed. If a trial matches all criteria, its index is added to the ts array. Trial indices in ts are always sorted in ascending order, i.e., by chronological execution. The array of trial indices can in turn be used to perform operations such as:

>> co = c.codes (ts, :);

Where co gets a matrix of event encodes for all trials selected by k(2). Many of the @cortex methods explained below require a key as an argument, and internally call trialset using that key to identify the trials to process.

example of analysis of behavior

A very simple example of behavioral data analysis is measuring performance in terms of percent of correct trials. For example, suppose that a monkey is trained to turn a lever to the left or to the right, depending on the target stimulus presented on the screen. In CORTEX, the trial outcome is encoded in the trial header field "response_error", and a correct trial is conventionally identified by the value 0 (or NO_ERROR). Note that the response_error field is set by calling the set_response_error(error_code) function in the timing file. An incorrect response (e.g., a right-lever turn when a left was expected) is usually marked by a response_error of 6. Not turning the lever either way within the allotted time results in a code XXX, a lost fixation is 3, etc.

In a @cortex object, the response error codes for all trials can be listed by doing:

>> c.res

Thus, a quick-and-dirty way to assess performance would be:

>> correctrials = sum(c.res==0);
>> incorrects = sum(c.res==6);
>> performance = correctrials/(correctrials+incorrects)*100

If you want to restrict the analysis to trials of, say, condition #1 of block #3, you would do:

>> correctrials = sum(c.res==0 & c.con==1 & c.blo==3);
>> incorrects = sum(c.res==6 & c.con==1 & c.blo==3);
>> ...

Use of keys makes this type of job cleaner. First you create a @key object with criteria to select trial subsets:

>> k = key ('behavior.key');
>> k.pri
Content of the @key object:
  =======================================
  sta fin cue con blo res tri typ exp rep
Key #1: correct
 -125 675 [ 25] [ 1] [ 3] [ 0] [ -1] [ -1] [ -1] [ -1]
Key #2: wrong
  -125 675 [ 25] [ 1] [ 3] [ 6] [ -1] [ -1] [ -1] [ -1]

you can then use the function trialset to do a quick trial count:

>> correctrials = length(trialset(c, k(1)));
>> incorrects = length(trialset(c, k(2)));
>> ...

Another way to count trials that "belong together" is to use the function trialcount:

ct = trialcount (c, k);

in the above example, the return vector ct will contain two values, i.e., the number of correct and incorrect trials.

Another common task is to analyze time delays between events, such as reaction times between stimulus presentation and bar release. Suppose for example that encode(27) marks the onset of a target stimulus and that the release of the response bar is immediately followed by encode(4). In principle, then, you could compute trial-by-trial reaction times this way:

>> start  = find(c.codes == 27);
>> finish = find(c.codes ==  4);
>> rts = c.times(finish) - c.times(start);

in practice, however, things are more complicated, and the above code will usually not work. Instead, use the function latency:

>> rts = latency (c, k(1), 27, 4)

Previous <-> Next