MonkeyLogic

Behavioral Control in MATLAB

 



Timing scripts

General Task Design
Trial-Specific Functions
Trial Errors
The TrialRecord Structure

NEW! MonkeyLogic User's Forum 



General Task Design

Timing scripts are the lines of code which actually determine when and how things occur during a trial of the task (example).  A timing script is run once for each trial and determines all of the events and contingencies possible during that trial. Timing scripts generally operate independently of the specific stimuli used in a particular trial; they refer to these stimuli only by the column in which they appear in the conditions file. This allows a single timing file to be used across many different conditions which share identical temporal structure, but differ in their specific stimuli.

The particular condition being run is determined by the options selected in the main menu before a timing script is called. The conditions file determines which timing script is executed once a condition has been selected (different conditions can be associated with different timing scripts). 

DMS task

The diagram above shows the basic sequence of a standard two-alternative, forced-choice "delayed-match-to-sample" task (see also Example Task), in which the subject is presented with one visual stimulus and must remember it over a short delay in order to select it from among one or more distractors later. Much more complex tasks are possible in MonkeyLogic; however this very simple one allows a depiction of the basic process of constructing a task's timing script. In this particular implementation, the subject's eye movements will be monitored, and he or she must fixate on a central dot throughout the entire trial. When the choices are presented near the end of the trial, one is selected simply by saccading to it (looking at it).

Task Cycle

This diagram shows the bare-bones steps needed to construct the example delayed-match-to-sample ("DMS") task. The functions used for each step are shown in italics. Toggleobject is the primary function for presenting visual stimuli, turning on TTLs or analog outputs, etc. The eyejoytrack function is used to determine if the eye position (or joystick position, see below for function details) is where it is expected to be. The output of this function therefore determines whether to continue through the task or abort the trial (by setting the "trialerror" to the desired value and issuing a "return" statement).

In addition to these basic elements, event-markers should be used to time-stamp behaviorally-relevant events; these allow post-hoc alignment of neural data with the appropriate triggers. An event-marker is simply a number which corresponds to a descriptive string explaining the time-stamped event.

A timing script should assign a trial error value (using the TrialError function) to reflect the subject's performance on that trial.

At the end of each trial , the value of the variable "rt" is used to update the reaction time bar graph in the control screen. This can be returned from the eyejoytrack function or it can be assigned manually.

Timing scripts can, for the most part, use any valid MATLAB command and should be written as any standard MATLAB script. There are a few important guidelines which must be followed, however:

     Do not declare the script as a function.

     Any return command should appear separately (on its own line).

 



Trial-Specific Functions

A timing script can use almost any valid MATLAB expression, and in addition can use any of these trial-specific functions:

Editable
EventMarker
Eye_Position

EyeJoyTrack
Get_Analog_Data

GetKeyPress
GoodMonkey
Hotkey
Idle
Joystick_Position
Reposition_Object
Set_Object_Path
Set_ITI
ShowCursor
ToggleObject
TrialError
TrialTime
User_Text


TOGGLEOBJECT

This function displays static visual stimuli, presents movies, plays sounds, and delivers analog and TTL stimulation.

Syntax:

[fliptime framenumber] = toggleobject(object_number(s), [parameter, value])

  • object_number is the "TaskObject#" from the conditions file. Multiple objects can be specified within an array so that they all appear or disappear simultaneously.
  • fliptime is the trial-time (in milliseconds) at which the screen "flip" command was issued.
  • framenumber is the video frame number, counted from the beginning of the file, at which the flip occurred.
  • One or more parameter / value pairs can be specified to modify the behavior of toggleobject:
Parameter
Value
Description
'EventMarker'
positive integer
Writes a behavioral event-marker immediately when the screen flip is detected. The time-stamps generated in this way are more accurate with respect to visual stimuli than those that would be generated by a separate call to EventMarker.
'Status'
'on' or 'off'
toggle is default
Manually determine whether the specified objects are to be turned on or off.
'MovieStartFrame'
scalar or vector

Determine the starting frame of a movie to be played. (The default is 1).

The input may be a scalar, to apply to all indicated movies, or a vector of length equal in length to the input argument stimuli. This parameter has no effect on non-movie objects.

'MovieStep'
scalar or vector

Determine the number of steps, in terms of movie frames, to step upon each screen refresh. (The default is +1).

  • If a value is positive, the movie will play forward.
  • If a value is negative, the movie will play in reverse (starting, by default, from the last frame).
  • If a value is 0, a static frame of the movie will be displayed.
  • Fractional (non-integer) values can be provided.
The input may be a scalar, to apply to all indicated movies, or a vector of length equal in length to the input argument stimuli.

This parameter has no effect on non-movie objects.
'StartPosition'
scalar or vector
Determines the starting position of a visual stimulus by indexing into the [xpath ypath] coordinates set for each object using set_object_path. This option can apply to static images and movies.
'PositionStep'
scalar or vector
Works analogously to 'MovieStep' above, but indexes into the path coordinates rather than into the frame sequence. This option can apply to static images and movies.
  • Waveform objects ("snd" and "stm") expire spontaneously when all the data in the waveform vector have been sent. Movies, visual stimuli and TTLs must be turned off manually.
  • For visual stimuli, when the 'eventmarker' option is not used, toggleobject will issue a screen flip and return control asynchronously to the user (i.e., the stimulus object may not yet have appeared on the screen). However, when 'eventmarker' is used, toggleobject will issue a flip and wait for the vertical blank, time-stamp that moment, then return control to the timing script.
  • Movies and translating visual stimuli require a subsequent eyejoytrack or idle command to animate. They will "wrap" to the beginning frame or position if the time specified in these commands exceeds the number of frames / positions (likewise, they will wrap to the last frame or position if MovieStep or PositionStep are negative).

Example:

To turn on two images, stored in TaskObjects 3 and 4, one could do the following:

pic1 = 3;
pic2 = 4;
toggleobject([pic1 pic2], 'eventmarker', 23, 'status', 'on');

Here, both pic1 and pic2 will appear simultaneously (during the same screen flip) because they were specified in one toggleobject command, and the time of that screen flip will be time-stamped with a code 23. The 'status' option is only necessary if there is any uncertainty about the status of one of the objects (e.g., if it were possible that one of them were already on, in which case that object would be toggled off).

This function is also used to turn movies on and off. For example, if a movie object is in TaskObject 2:

mov = 2;
toggleobject(mov);

Note that this command initializes the movie and puts up the first frame. However, the movie will not start playing until either the idle command or the eyejoytrack command is called, as these functions are responsible for "passing time" during a task. So to play the movie for "duration" ms, one would need a sequence such as:

toggleobject(mov);
[ontarget rt] = eyejoytrack('acquirefix', targetobject, radius, duration);
toggleobject(mov);

Here, the movie will play until either duration ms has elapsed, or the subject acquires fixation on targetobject (see eyejoytrack, below, for this function's syntax and options). More than one movie can run simultaneously. A warning message will indicate if there are any skipped frames.

To play the movie backwards at half-speed:

toggleobject(mov, 'MovieStep', -0.5);
[ontarget rt] = eyejoytrack('acquirefix', targetobject, radius, duration);
toggleobject(mov);

If a movie is toggled off, then later toggled back on, it will resume playing from the frame at which it left off, unless the MovieStartFrame has been explicitly specified. Note that manually-set MovieStep and MovieStartFrame parameters of any particular movie object will persist across subsequent presentations of that object in that trial (but not across trials).

The optional output variables fliptime and framenumber can be used to double-check video-timing, if necessary. These outputs are used internally by eyejoytrack to properly determine movie-presentation timing.


EVENTMARKER

This function time-stamps a number corresponding to a behavioral code, to identify the times of behaviorally-relevent events for post-hoc data analysis. This number and its associated time-stamp are saved on the local machine running MonkeyLogic in the BHV file. In addition, this number is sent via a digital output port to another machine (e.g., a neural data acquisition system) if the behavioral codes and codes strobe I/O settings are have been defined in the main menu.

Six event markers are always present within each trial; three code 9s and three code 18s at the beginning and end of every trial, respectively.  These are to allow fail-safe re-alignement of a behavioral file and a separately acquired physiology file in the event of intermittent communication failure between the behavioral and neural data acquisition computers. These two codes, therefore, are reserved and should not be used in the the timing script.

Syntax:

eventmarker(codenumber(s))

  • codenumber is the number or numbers to be time-stamped, representing a behavioral event.
  • codenumbers must be positive integers.
  • If digital outputs have been assigned for "Behavioral Codes" and "Codes Strobe" in the main menu, a copy of these codes will be transmitted along those lines. An adequate number of digital IO lines must have been assigned to the "Behavioral Codes" function (in the IO submenu) to represent each number's magnitude in binary form (e.g., 8 lines for 0-255).
  • To time-stamp the appearance or disappearance of visual stimuli, one should instead use the "eventmarker" option of toggleobject, as this provides a more accurate record of the screen refresh time.

Example:

To time-stamp two values in the behavioral file, here 22 and 48 (and to have them written out the digital ports, if these have been assigned in the main menu):

eventmarker([22 48]);

Reserved Eventmarkers:

code number
description
9
Start Trial
18
End Trial
200
Skipped Movie Frame

EYEJOYTRACK

This function is used to track eye- and joystick position with respect to specified targets (i.e., visual stimuli presented using the toggleobject function), and to track button presses or lever position. In the case of eye and joystick signals, a target can determine a point where the subject must hold fixation or the joystick cursor for a specified length of time, or a target can determine a point to be acquired within the specified amount of time. In the case of buttons or levers, the target is a threshold input level (i.e., an adjustable threshold voltage for analog inputs or a fixed threshold value of 0.5 for digital inputs).

To use this function, one must specify whether the goal for the subject is to hold fixation, hold a joystick target, acquire fixation, acquire a joystick target, hold-touch, or acquire-touch (see table, below). In addition to specifying the goal (i.e., the eyejoytrack subfunction), one must also specify the target (i.e., the TaskObject that is the focus of the action), the threshold (a radius in degrees of visual angle for eye- or joystick signals, or an input level for buttons or levers), and the time required or allowed. Note that eyejoytrack will work regardless of the current visibility of visual target objects (i.e., a visual target does not need to have been turned on using toggleobject); this allows the creation of targets that are invisible, yet are the nevertheless the focus of the desired action (e.g., allowing for memory-guided rather than visually-guided movements).

Subfunction
Action
Target Object
Threshold
Output ("ontarget")
acquirefix returns when the subject's eye-position enters one of the specified targets, or the specified duration has elapsed any visual object the radius around the target object(s) in degrees of visual angle 0 if the eye-position does not enter the specified radius around a target object within the allowed duration, otherwise the ordinal number of the acquired object.
holdfix returns when the subject's eye-position leaves the specified target, or the specified duration has elapsed any visual object the radius around the target object in degrees of visual angle 0 if the eye-position exits the threshold radius around the target object before the specified duration has elapsed, 1 otherwise.
acquiretarget returns when the subject's joystick position enters one of the specified targets, or the specified duration has elapsed any visual object the radius around the target object(s) in degrees of visual angle 0 if the joystick-position does not enter the specified radius around a target object within the allowed duration, otherwise the ordinal number of the acquired object.
holdtarget returns when the subject's joystick position leaves the specified target, or the specified duration has elapsed any visual object the radius around the target object in degrees of visual angle 0 if the joystick-position exits the threshold radius around the target object before the specified duration has elapsed, 1 otherwise.
acquiretouch returns when the button / lever input voltage rises above the specified threshold, or the specified duration has elapsed button(s) / lever(s) the voltage if analog, or 0.5 if digital 0 if the input level does not rise above the threshold within the allowed time, otherwise the ordinal number of the button / lever which first crosses threshold.
holdtouch returns when the button / lever input voltage falls below the specified threshold, or the specified duration has elapsed button(s) / lever(s) the voltage if analog, or 0.5 if digital 0 if the input level falls below the threshold before the specified duration has elapsed, 1 otherwise.

In the case of holding fixation or holding a joystick target, this function will continuously check eye or joystick position throughout the specified interval. If this position falls outside the specified radius before the total specified time has elapsed, the output will return "0" reflecting failure to hold fixation or hold target. If the entire time elapses and the subject has stayed within the specified bounds, the output will be "1." A second output, rt, will reflect the elapsed time (i.e., the fix / target break time, or reaction time).

In the case of acquiring fixation or acquiring a joystick target, this function will continuously check eye or joystick position until the target object has been acquired or until the specified time has elapsed. If the subject acquires fixation or the joystick target before the specified time has elapsed, the output will be non-zero (and a second output-argument, rt, will reflect the elapsed time, i.e., fix / target acquisition time). If, on the other hand, the target object is not acquired during that interval, the output will be zero. Note that for fixation or target acquisition, multiple TaskObjects can be specified as potential targets; here, the output will reflect which target (by ordinal number of its specification) was acquired. In other words, if targets [3 4 5 6 7] are specified, and the subject lands on target #5, the output of eyejoytrack will be "3" because #5 is the third object in the list.

In the case of acquiring "touch" (e.g., button press), eyejoytrack will return a "1" when the button input voltage rises past the given threshold (specified in-place of the "radius" argument, below), and a "0" if this threshold is never reached before the maximum duration expires. Conversely, "holdtouch" will return early with a "0" if the button voltage falls past the specified threshold before the maximum time expires, or "1" at the end of that duration if the voltage stays above the threshold for the entire time.

Note that when transitioning between an "acquire" and a "hold" (i.e., the subject moves into a target which must then be held for a some time), a small amount of idle time (e.g., 50ms) is useful to allow settling of the signal wholly within the target. In other words, given a noisy signal which just begins to cross a threshold, the noise may cause that signal to momentarily drop below the threshold even though there is a clear over-all trajectory beyond it. This transient dip may be regarded as a break-fixation or break-target unless adequate time is allowed for the signal to move further into the target region.

Syntax:

[ontarget rt] = eyejoytrack(fxn, object_number, threshold, duration)
       or
[ontarget rt] = eyejoytrack(fxn1, object1_number, threshold1, fxn2, object2_number, threshold2 , duration)

  • fxn can be:
    • 'acquirefix' or 'holdfix' for tracking eye movements,
    • 'acquiretarget' or 'holdtarget' for tracking joystick position,
    • 'acquiretouch' or 'holdtouch' for tracking buttons / levers.
  • Two functions (fxn1 and fxn2) can be specified (second syntax) to simultaneously track any pair of signals (e.g., eye & joystick or eye & buttons, etc).
  • object_number is the "TaskObject#" from the conditions file, and can be a vector of objects in the case of 'acquiretarget', 'acquirefix', 'holdtouch', or 'holdfix'
  • threshold, for eye- and joystick-signals, is the radius around the object's center, in degrees of visual angle, and is independent of object size. For buttons / levers, the threshold voltage(s) should be specified here instead; specifying an empty matrix ( [] ) sets the thresholds at their default levels (3 volts for analog buttons / levers, and 0.5 for digital buttons).
  • duration is the time (in milliseconds) to either acquire or hold the target.
  • The output variable ontarget will be 1 if the target is successfully acquired (for 'acquirefix', 'acquiretarget', and 'acquiretouch' ) within duration, or successfully held continuously (for 'holdfix', 'holdtarget' and 'holdtouch') for the full duration, 0 otherwise.
  • Multiple target objects can be specified by using a vector of task_objects as the second (or fifth) arguments. In this case, the output ontarget will be a scalar corresponding to the specific target acquired or held (for instance, if you call ontarget = eyejoytrack('acquirefix', [5 3 4 2], r) where r is the target radius, and the subject lands on the third target (here, object #4), ontarget will equal 3).
  • Ontarget will be a 2-element vector representing both eye and joystick success if the second (two-function) syntax is used.
  • If two targets overlap (the radii are larger than half the separation between targets), ontarget will reflect the first of the two in the provided sequence of targets.
  • The output variable rt will be the time (in milliseconds) to aquire the target (when using 'acquirefix' or 'acquiretarget') or to leave it (for 'holdfix' or 'holdtarget'). The last value assigned to "rt" in the timing script will be saved to the behavioral data file and will be used to update the reaction time graph in the control window.

Examples:

To wait for the acquisition of a target by movement of a joystick to within R degrees within a maximum of T time:

ontarget = eyejoytrack('acquiretarget', target, R, T);

If no target is acquired, "ontarget" will be zero. Otherwise, it will be the index into target of the object that was acquired. For example, if target = [3 5 7] and ontarget returns equal to "2", this indicates the subject acquired the second item in the list, TaskObject #5, by moving to within R degrees of its center, in less than T milliseconds.

Alternatively, to require fixation on a fixspot within radius R degrees for a duration of T time:

ontarget = eyejoytrack('holdfix', fixspot, R, T);

Here, "ontarget" will be zero if fixation is broken before time T has elapsed, or one otherwise. Lastly, to do both simultaneously:

ontarget = eyejoytrack('holdfix', fixspot, R1, 'acquiretarget', target, R2, T);

In this case, "ontarget" will be a two-element vector specifying the results of each tracking operation in the order they were specified.

 


EDITABLE

This function declares variables as parameters that are available for modification on-line (i.e., during task execution). To modify variables that have been declared as editable, pause the task (by pressing the [escape] key), and then press [v] as prompted. A menu will appear listing all the variables available for editing and their current values. Click on a value box to edit it.

edit variables

Syntax:

editable('varname1', 'varname2', 'varname3', ... )

or

editable({'varname1' 'varname2' 'varname3' ...})

  • The input can be a string (or cell array of strings) containing the names of the variables to be made modifiable on-line,
  • A variable must be declared as editable before an initial value is assigned to that variable.
  • The "editable" command and all subsequent variable value assignments must each occur independently on separate lines of code.
  • Initial values must be assigned to editable variables by the timing script, and must be explicit; that is, they must be assigned a simple scalar number (they may not consist of expressions involving functions or other variables). These variables can then be used in the definition of other variables, but should not themselves be reassigned other values.
  • If the same variable name is declared editable in more than one timing script, all those timing scripts will share the same value for that variable.
  • Modifications to variables on-line do not permanently alter the timing script. The next time the task is run, these variables will revert to their initial, hard-coded vales.

Examples:

To declare two variables, here called var1 and var2 , as editable:

editable('var1', 'var2');
var1 = initialvalue1;
var2 = initialvalue2;

Suppose one wanted to make a variable used by a separate user function, such as a block-selection function, editable. In the timing script, declare:

editable('var1');
var1 = initialvalue;
TrialRecord.var1 = var1;

Then, in the block-selection function, write:

var1 = initialvalue;
if isfield(TrialRecord, 'var1'),
    var1 = TrialRecord.var1;
end

As shown here, var1 must be given an intial value in the block-select function because that function can be called before the first execution of the timing script. In addition, because the timing script has not yet been run, the field containing the editable variable may not yet exist, so the conditional is necessary. Note that changes to var1 may not take effect in the block-select function (or any similar user functions) until after the subsequent trial.

 


HOTKEY

This function assigns user-specified activities to keyboard events during task execution. In other words, the press of a key during a trial will execute the callback function provided by the user.

hotkey(key, fxn)

  • key is a string containing the keyboard key (letter or otherwise) to be assigned a function.
  • fxn is a string containing the commands to be executed or function to be called.  
  • Any number of keys can be specified, each with a separate call to hotkey.
  • Function keys can be specified as 'F3' or 'F11' etc.
  • No key combination modifiers are recognized (e.g., an "r" is no different from "R" or [ctrl]+"r" etc).
  • Key presses are not recognized during the inter-trial-interval.
  • Arguments for specified functions must be explicit. That is, a variable name included in the callback fxn will not be resolvable in the separate work-space in which that callback is executed.

Example:

To assign a long reward delivery event to the letter "t":

hotkey('t', 'goodmonkey(500);');

This will deliver one half-second worth of reward every time the "t" key is pressed. Note that any argument to the callback function - here "500" - must be explicit, as noted above. And remember that certain hotkeys are predefined and should not be overriden. (See Predefined Hotkeys).


IDLE

This function allows a specified amount of time to elapse without placing requirements on eye- or joystick-position. During this time, eye- and/or joystick position will be shown on the control-display (this feature is what differentiates this function from built-in MATLAB functions such as "pause"). In addition, a second argument can be provided to determine the subject screen's background color during this interval (useful for "time-out" cues, etc.).

idle(duration, [screen_color])

  • duration is in milliseconds
  • screen_color is an optional RGB triplet specifying the screen color.  This will be set back to the initial background color (as set in the main menu) at the end of duration.  

Example:

To allow 1 second to pass during which the screen's background color is red (e.g., for a "time-out"):

idle(1000, [1 0 0]);

 


SHOWCURSOR

This function toggles the subject's joystick cursor on or off.

showcursor(['on' | 'off'])

  • Turns the subject's cursor ON or OFF. (1 or 0 can be substituted for the strings.)
  • The position of the cursor always corresponds to the joystick (not eye) position.      
  • If the joystick is not properly calibrated such that certain joystick positions will place the cursor outside of the screen boundaries, an error will result when the joystick is moved to that position and MonkeyLogic attempts to draw the cursor.

Example:

To turn on the joystick cursor:

showcursor('on');


SET_OBJECT_PATH

This function sets a path through which a video stimulus (static image or movie) is to be translated.

success = set_object_path(object_number, xpath, ypath)

  • object_number is the "TaskObject#" from the conditions file.
  • If the specified object does not have a valid x and y position, success = 0
  • This function does not display the object or start the actual translation; it merely registers a path that will take effect when toggleobject is called for that stimulus.
  • As for movies, the actual translation will occur only while eyejoytrack or idle is running.
  • The [x, y] position of the visual stimulus is changed once per video frame (e.g., for a path to last 500 ms at 100 Hz, the x and y vectors much each contain 50 elements).
  • The toggleobject parameters StartPosition and PositionStep can modify the starting location, speed, and direction of translation.

Example:

To move an object in a counter-clockwise 3-degree circle over 1 second with a video refresh rate of 100 Hz

pic = 1;
radius = 3;
k = 0:2*pi/100:2*pi;
xpath = radius*cos(k);
ypath = radius*sin(k);
set_object_path(pic, xpath, ypath);
toggleobject(pic);
idle(1000);
toggleobject(pic);

Two parameters of toggleobject can by used to modify the starting position, and the direction and number of steps to move along the path at each video frame: 'StartPosition' and 'PositionStep'. For example, to move this picture in a clockwise rather than a counter-clockwise path, and with twice the speed:

toggleobject(pic, 'PositionStep', -2);
idle(1000);
toggleobject(pic);

Here, two rotations will occur because the image is moving twice as fast, but the "idle" time remained 1 second. Note that PositionStep may be fractional, but StartPosition must be a positive integer index into the path vectors. A warning message will indicate if any frames are missed.

If a visual stimulus is toggled off, then later toggled back on, it will resume movement along the path from the point at which it left off, unless the StartPosition has been explicitly specified. In addition, manually-set StartPosition and PositionStep parameters will persist across subsequent presentations of the same object until they are manually changed.


SET_ITI

This function sets the desired duration of the next inter-trial interval.

set_iti(duration)

  • duration is the desired duration of the next inter-trial interval in milliseconds.
  • The desired duration can be reset to the value from the main menu by calling set_iti with duration == -1.

REPOSITION_OBJECT

This function moves a TaskObject to a new screen position. The object can be visible at the time of the move (i.e., activated by toggleobject), or it can be invisible.

success = reposition_object(object_number, new_xpos, new_ypos)

  • object_number is the "TaskObject#" from the conditions file.
  • if the specified object does not have a valid x and y position, success = 0
  • if the specified object is currently on the screen, it will be moved (however, this method is not as fast as specifying two identical objects with different positions in the conditions file, and toggling one off and the other one simultaneously, i.e., this method may leave a blank frame during the move).

Example:

To move TaskObject #3 from where-ever it currently resides to a point in the upper-left quadrant:

success = reposition_object(3, -5, 5);


TRIALTIME

Returns the time (in milliseconds) since the beginning of the trial.

[t, framenumber] = trialtime

  • t is the time in milliseconds since the beginning of the trial.
  • framenumber is the video frame number, counted from the beginning of the file (used internally to display movie frames at the appropriate times, but accessible to users as well).


GETKEYPRESS

Returns the scancode of the first key which is pressed during the specified interval.

scancode = getkeypress(maxtime)

  •  maxtime is maximum time to wait for keypress, in milliseconds.
  • scancode is the hardware scan code for the key pressed. (run "exkeycode" to see which codes correspond to which keys)


GOODMONKEY

Delivers reward by sending analog or TTL pulses to the device specified in the I/O menu. A solenoid for juice delivery is assumed to be the final actuator, but anything that can be activated by 5V signal pulses is acceptable.

goodmonkey(duration, ['Parameter', 'Value'...])

  • duration is the amount of time to keep the solenoid open
  • Additional parameters can be specified in one or more parameter / value pairs:
Parameter Description Expected Value
NumReward
Number of reward pulses to give (default = 1) Positive Scalar
PauseTime
Amount of time between reward pulses, in milliseconds (default = 40) Positive Scalar
TriggerVal
Voltage to deliver when using analog outputs to drive reward-equipment (default = 5V) Positive Scalar

Examples:

To give three pulses of 50 ms reward:

goodmonkey(50, 'NumReward' 3);

To increase the pause-time between these pulses to 100 ms (from the default of 40 ms):

goodmonkey(50, 'NumReward', 3, 'PauseTime', 100);

To set the output voltage to 2.5V (from the default of 5V):

goodmonkey(50, 'TriggerVal', 2.5);

 


EYE_POSITION

Returns the x & y position of the eye-signal.

[x y] = eye_position([screen_update_flag])

  • x & y are the current position of the eye, in degrees of visual angle
  • screen_update_flag is optional, and should be 1 to update the trace on the control screen

 


JOYSTICK_POSITION

Returns the x & y position of the joystick.

[x y] = joystick_position([screen_update_flag])

  • x & y are the current position of the joystick cursor, in degrees of visual angle
  • screen_update_flag is optional, and should be 1 to update the trace on the control screen

 


GET_ANALOG_DATA

Returns one or more data points from an analog-input device.

Syntax:

[analogdata frq] = get_analog_data(signal, duration)

  • signal should be either "eye" for eye-position data, or "joy" for joystick position data, or the name of the signal (e.g., "photodiode").
  • duration is the number of the most recent samples to retrieve (e.g., 500 for most recent 500 ms of data when acquiring at 1 kHz)
  • analogdata is the requested data (duration x 2 array, first column is "x" and second is "y")
  • frq is the sampling frequency

 


TRIALERROR

The TrialError function assigns a "trial error" value for the current trial. A single trial error value ranging from 0 to 6 (or the corresponding string) should be assigned to every trial to describe the subject's performance (i.e., success or lack thereof) on that trial. Trial errors are used in two important ways. First, they can aid behavioral analysis by providing a straightforward way to select those trials meeting a specific behavioral criterion (e.g., to look only at "correct" and "incorrect" trials while ignoring other sorts of errors, such as "break fixation"). Second, they are often necessary to direct the selection of subsequent conditions. If, for example, the "on error" option within the main menu is set to "repeat immediately", any trial that is not correct (i.e., not assigned a zero) will be followed by another trial of the same condition.

If no trial error is assigned by the timing script, a value of 9 is assigned by default.

Syntax:

trialerror(number)
       or
trialerror(string)

  • If a number is assigned, it should be a scalar and range from 0 to 6, inclusive, according to the table below.
  • If a string is assigned, it should be one of the following strings listed in the table below (case insensitive):
0
Correct
1
No Response
2
Late Response
3
Break Fixation
4
No Fixation
5
Early Response
6
Incorrect Response
7
Lever Break
8
Ignored
9
Aborted

A trialerror = 9 will be assigned if no trialerror is assigned by the timing script.
As of the 8/1/08 revision, if the first few letters are unambiguous, one need not specifiy the whole string (e.g., trialerror('early') will work).

 


USER_TEXT

This function displays a line of text to the control screen.

user_text(text)

  • text is the string to be displayed in the control screen.
  • The most recent call to user_text will display to the top of the text box, and subsequent calls will scroll the text in the box downward.
  • The control screen is only redrawn during the inter-trial interval, so calls to user_text will not be displayed until after the trial containing the call has terminated.


The TrialRecord Structure

TrialRecord is a data structure, updated every trial, containing information about a subject's behavior, the blocks and conditions played, and other information potentially relevant to a user's need to control the flow of the task, choose or create stimuli, or display information. Functions that take the TrialRecord structure as input include:

Timing Scripts
Condition-Selection Functions
Block-Selection Functions
Block-Change Functions
User-Plot Functions
User-Generated Image Functions

TrialRecord contains the following fields:

TrialRecord.CurrentTrialNumber The currently executing trial number, consecutively numbered from the start of the session (scalar)
TrialRecord.CurrentTrialWithinBlock The currently executing trial number, consecutively numbered from the start of the current block (scalar)
TrialRecord.CurrentCondition The condition number of the current trial (scalar)
TrialRecord.CurrentBlock The block number of the current trial (scalar)
TrialRecord.CurrentBlockCount The total number of blocks played thus far, including the current one (scalar)
TrialRecord.CurrentConditionStimulusInfo Information about the stimuli used in the current trial (cell array, one cell per TaskObject)
TrialRecord.ConditionsPlayed The list of conditions played since the start of the session (a vector of length (CurrentTrialNumber - 1))
TrialRecord.ConditionsThisBlock The list of conditions which are available for selection from within the current block (vector of variable length)
TrialRecord.BlocksPlayed The list of blocks played since the start of the session (a vector of length (CurrentTrialNumber - 1))
TrialRecord.BlockCount The number of blocks played, as of any given trial thus far (a vector of length (CurrentTrialNumber - 1))
TrialRecord.BlockOrder The order of blocks played thus far, including the current block (vector)
TrialRecord.BlocksSelected The list of blocks available, as selected from the main menu (vector)
TrialRecord.TrialErrors The list of behavioral errors for every trial played so far (a vector of length (CurrentTrialNumber - 1))
TrialRecord.ReactionTimes The list of reaction times for every trial played so far (a vector of length (CurrentTrialNumber - 1))
TrialRecord.LastTrialAnalogData A structure containing the fields EyeSignal and Joystick, with the x- and y-vectors of the last trial's analog signals
TrialRecord.LastTrialCodes A structure containing the fields CodeNumbers and CodeTimes, containing vectors corresponding to each

Changes can be made to the TrialRecord structure by the timing script (e.g., adding a new field and assigning it a value). These changes will be maintained across trials and will be included in the TrialRecord structure as it is passed to other functions (for example, to block-change or block-selection functions, etc). However, any changes to TrialRecord made by those functions will not persist outside those non-timing script functions or across trials within those functions. Adding fields to TrialRecord is a useful way to allow variables used in those other functions to be editable. For example, in the timing script, one might write:

editable('var1');
var1 = 200;
TrialRecord.var1 = var1;

Then, in the separate user function (e.g., block-selection, condition-selection, block-change, or user-generated image (gen) function):

if ~isfield(TrialRecord, 'var1'),
      var1 = initialvalue;
else
      var1 = TrialRecord.var1;
end

The conditional statement is necessary if the user function can be called prior to the first execution of a trial (i.e., the first call to the timing function).

This way, var1 will appear in the "edit variables" menu brought up by pressing [v] when the task is paused, and changes to this variable will be forwarded to all other functions that take "TrialRecord" as an input.

 



This site last updated: May, 2014
© 2008-2014