MatOFF History Scripts
Introduction
In addition to the standard scripting capabilities (protocol files and metafiles),MatOFF allows an advanced user to introduce MATLAB scripts into the search for event code sequences. These scripts use the History command. They process information about all trials (the entire history of behavior) when deciding whether or not to accept the current trial. The scripting mechanism is ideal for analyzing the time-course of events.We have used it to study learning. History scripting can also be used to add new features toMatOFF, like the ability to detect the onset of an eye movement, or to save behavioral information to a disk file.
Anatomy of a history script
MatOFF maintains a table (history table) for each unit in a file. The table has a list of "classes" and "class values" for each trial in the unit. This allows you to categorize trials in multiple ways. For example, each trial in an experiment could be placed into two classes:
Class 1: movement direction (four possible values: 1=left, 2=right, 3=up, 4=down)
Class 2: successful trial (two possible values: 0=failure, 1=success)
These classes are assigned during a sequence search using a MATLAB script. An appropriate script might look something like this:
% Some of the event codes in this data file are
% movement direction: 71=left, 72=right, 73=up, 74=down
% performance: 95=successful trial
%
class=1; % create a new class that reflects the movement direction.
% find the event code for direction in this trial
direction = allcodes(find( (allcodes >= 71) & (allcodes <= 74) ));
% Use the event code to assign a value to class 1: 1, 2, 3, or 4 for the 4 directions
if ~isempty(direction)
assign_class_value(current_trial,class,direction-70);
end
%
class=2; % create a class that indicates success or failure
if find(allcodes==95)
assign_class_value(current_trial,class,1); % 1 is success
else
assign_class_value(current_trial,class,0); % 0 is fail
end
The classes just created have not added any information beyond that already contained in the event codes for a single trial. With this addition, we use class 2 above to create a new class. This new class is for trials that are successful and have at least two prior trials also successful.
class=3 % create class that uses information from two previous trials
if (current_trial > 2) % cannot test first two trials of the unit
if find_class_value(current_trial,2) & find_class_value(current_trial-1,2) & find_class_value(current_trial-2,2)
assign_class_value(current_trial,class,1); % classify this successful trial based on past two successes
else
assign_class_value(current_trial,class,0); % zero otherwise
end
end
The new class can be used to select trials for rasters, histograms, statistics, etc. Set the special variable accept =1 before exiting the history to accept the trial. If accept=0, the trial will be rejected just like a mis-matched sequence.
if find_class_value(current_trial,3) % accept only trials in class 3
accept=1;
else
accept=0;
end
The ability to accept or reject search sequences based on classes makes this "history scripting" a powerful tool for studying time-varying phenomena.
Variables and support functions available to history scripts
History scripts are written in MATLAB code. The history script file must have a ".m" file extension. A history scriptmust notbe a MATLAB function.If you use the "function" keyword the script will not be able to interact withMatOFF. The default path for a history script is set by the environmental variableHISTORYPATH.
The script will have access to these variables:
ACCEPT / REJECT / ABORT |
|
accept | value set by History script to accept (1), reject (0) current trial, or abort scan (-1) |
CURRENT TRIAL |
|
allcodes | array of every event code in this trial |
center_event | center event code. Returns zero if the centering is on a history class |
center_event_number | value ofCentercommand (position of center code in the search sequence) |
codes | array of event codes in this trial that matched the sequence |
current_trial | trial number of sequence being matched |
last_trial | number of trials in the unit |
mark_event | mark event code |
mark_event_number | value ofMarkcommand (position of mark code in the search sequence) |
ENVIRONMENT |
|
data_file_name | name of the currently open data file |
unit_name | name of the currently open unit |
<<strong>PRINT MESSAGES |
|
DEBUG_M | |
WARNING_M | constant to select a warning message type for issue_message() |
ERROR_M | constant to select an error message type for issue_message() |
History scripts also have access to a series ofsupport functions:
CREATE CLASSES |
|
assign_class_value(trial,class,value) | create a class, add a class value, or change a class value |
DELETE CLASSES |
|
remove_class(trial,class) | remove a trial from a class assignment |
purge_class(class) | remove all assignments for a class (completely remove class) |
READ CLASSES |
|
list_class(class) | return a matrix of all trials assigned to a class and their class values |
list_trial(trial) | return a matrix of all classes and associated values for a single trial |
find_class_value([trials],class) | return the class value(s) for one or more trials in a given class. returns NaN for trials not in the class |
zfind_class_value([trials],class) | return the class value(s) for one or more trials in a given class. returns 0 for trials not in the class |
GET DATA |
|
list_analog(trial) | return a list of all analog values (x and y) and their times |
list_events(trial) | return a list of all events and event times for a trial |
list_history_data | returns the history data array (numeric or character) supplied by theHistory datacommand |
list_spikes(trial) | returns a list of all spike times for a trial |
MESSAGES |
|
issue_message(type,message) | issues a debug, warning, or error message string to the console |
logfile_write(string) | write a string to the log file |
ENVIRONMENT |
|
list_environment() | get a copy of theenvironmental variables |
In addition to the support functions, the script can include any standard MATLAB commands or functions.
Details of support functions
status = assign_class_value(trial,class,value)
Create a class, add a class value, or change a class value.
Inputs | |
trial | Trial for history change |
class | Class to add or amend |
class_value | Value for the class |
Outputs | |
status | 1 = successful run, negative value is an error code |
find_class_value([trials],class)
return the class value(s) for one or more trials in a given class. returns NaN for trials not in the class
Inputs | |
trials | list of trials to look up |
Outputs | |
values | one-to-one match with trials list. NaNs are inserted for trials with no values |
zfind_class_value([trials],class)
Same asfind_class_value()except that zeros are used for trials with no values.
Remove all assignments for a class (completely remove class).
Inputs | |
class | Class to remove |
Outputs | |
status | 1 = successful run, negative value is an error code |
status = remove_class(trial,class)
Remove a trial from a class assignment.
Inputs | |
trial | Trial for history change |
class | Class to remove |
Outputs | |
status | 1 = successful run, negative value is an error code |
Return a list of all analog values (x and y) and their times.
Inputs | |
trial | Trial to look up |
Outputs | |
xy_data | row 1 x1 x2 x3 x4 ... xn x analog values row 2 y1 y2 y3 y4 ... yn y analog values row 3 t1 t2 t3 t4 ... tn time in milliseconds |
return a matrix of all trials assigned to a class and their class values
Inputs | |
class | class to list |
Outputs | |
list | row 1 trial numbers row 2 matching class values |
environment = list_environment()
get a copy of the environment
Inputs | |
none | |
Outputs | |
environment. | structure with the following classes: datapath defaultpath displayunits dumppath editor eogsamplerate eventcodefile formatpath graphicsformat layoutpath makdat makdump metachar1 metachar2 metapath plotpath protocolpath remapfile statpath maxinputtrials dumplabel maxtrialsfound dumptext dumpmode historypath analogstart analogstop |
return a matrix of all event codes and their time stamps for a specified trial
Inputs | |
trial | trial to look up |
Outputs | |
list | row 1 event codes. Every code irrespective of the sequence or globalignore lists. row 2 event times. Trial starts at 0.1, all values stored in milliseconds |
serves as a data link between protocol scripts and history scripts.
Inputs | |
none | |
Outputs | |
row_array | fetch the data left in memory by theHistory datacommand. |
return a list of spike times for this trial. Time 0 is the start of the trial.
Inputs | |
trial | trial to look up |
Outputs | |
list | spike times in milliseconds since the start of the trial |
All classes and class values associated with a trial.
Inputs | |
trial | trial to look up |
Outputs | |
list | row 1 classes that this trial belongs to (if any) row 2 class values associated with each class |
issue_message(message_type,message_string)
Print a debug, warning, or error message.
Inputs | |
message_type | 1=Debug, 2=Warning, 3=Error (use predefined values: DEBUG_M, WARNING_M, ERROR_M) |
string | The message to print. |
success=logfile_write(logstring)
Write a string to the log file, if a log file is open.
Inputs | |
logstring | The string to send to the log file. No new-line character is necessary. |
Outputs | |
success | Returns 0 if no file is open, returns 1 otherwise. |
logfile_write
These are the available history commands:
history on | set history data array to [1] and process the user's history script; use the result to accept or reject trials from analysis |
history off | set history data array to [0] and skip all history processing |
history clear | remove all history data in memory |
history rewrite <all> | save history data to disk |
history file <filename> | identify the file containing the user's history script |
history spot show | display history spot times |
history spot noshow | do not display history spot times |
history spot firstclass | first class to use for history spots |
history spot lastclass | last class to use for history spots |
history data <data> | save data for use by history scripts |
Related Commands | |
sort history <class> | sort trials based on history class values |
validatespikes on/off | use history class values to make a time window for rasters and histograms |
validatespikes start/end <class> | set classes used to mark the start and end of valid spikes for each trial |
validatespikes color <color> | color used to mark spikes NOT INCULDED in the histogram |
dump history | show every trial number and class value for all classes |
center | center value can be a history class. must be class number greater than 99 |
History scripts are written in the MATLAB language and saved as a MATLAB file (".m" extension). They must not be a MATLAB function. The script file name is given toMatOFFusing theHistorycommand. A secondHistorycommand is used to enable the script.
history file myscript.m
history on
When the history is on, each match of a trial sequence calls the history script. The history script can assign a 0 or 1 to the variable "accept." If accept has the value 1, the matched trial is accepted. That is, the trial is treated as it normally would be if no history is enabled. If accept has the value 0, the trial is rejected as if one of the event codes of the trial did not match the search sequence. If the script makes no assignment,MatOFFassigns the value 1 and issues a warning.
Data (history data array) can be sentfrom a protocol file to a history script using theHistory datacommand. The history data array can be a simple numeric array with values separated by spaces:
history data 13 19 21 145 666 18
The history data array can also be sent as one long text string. The user may have to parse the text string.
history data 'unitA rewarded left 101'
If theDump spikescommand is not being used, a string can also be passed using theSetenv dumptextcommand. You can use thelist_environment() function to get a copy of the dumptext string:
env=list_environment();
dumptext=env.dumptext;
Either way a string is passed, this string can be parsed with MATLAB code like this:
[unit_name,remainder]=strtok(list_history_data);
[reward_string,remainder]=strtok(remainder);
[direction,remainder]=strtok(remainder);
stimulus_number=str2num(remainder);
Note thatHistory onsets the history data array to [1] andHistory offsets the history data array to [0].
Just like it is common to run different sequences on the same unit, it is common to run different history scripts on a unit. The user can begin with a very inclusive sequence (with just a few event codes common to all trials) along with a script that builds up a classification system. After that, more restrictive sequences can be used along with scripts that take advantage of the previously-created classes. The classifications (history) exists only in memory unless it is saved to disk using theHistory rewritecommand. The history is added to the other files associated with the currently open file. A history requires two files (extensions .history and .hindex). The next time the unit is opened with theUnitcommand its history will be loaded into memory. The history can be deleted from memory using theHistory clearcommand.Dump historyis used to view the current history in memory.
If multiple units have been recorded simultaneously during the experiment, these units will have a common behavioral history. When saving the history for the current unit,MatOFF> can search for other units that come from the same set of trials.History rewrite allprovides this service.
History classes can be used to place markers on plots using theHistory spotcommand The markers are the same as spot events (seeSpotcommand), however, the marker placements are determined by setting absolute times rather than event codes. The absolute times are stored as history class values. For example, to place a spot exactly 2.5 seconds into trial 3, save this time value into a class:
assign_class_value(3,500,2500); % only integers accepted, so time is stored in milliseconds
Class 500 is used for this class value, so the following commands are needed to tellMatOFFto use this value:
history spot show
history spot firstclass 500
history spot lastclass 501
Since the lastclass is 501, class 501 can also be used to store spot times. Thus, practically any number of spots can be placed in a single trial.
History classes can be used to sort data using theHistory sortcommand. The history script creates a class with class values for each trial.MatOFFwill then use these class values to sort trials for raster display.
History classes can be used to truncate XY analog traces. We have written history scripts to locate the start and end of a saccade, then store the start and stop times as class values. TheXY time classescommand tellsMatOFFto apply these class values when drawing the XY traces.
A fewMatOFFcommands and features will be helpful for rapidly debugging history scripts. Here are some helpful tips.
1. If you modify a script with an editor while runningMatOFF,MatOFFand MATLAB may not notice the change. To make MATLAB aware of the change, issue theMatlabcommand followed by theCmdcommand. This brief shift out of and back intoMatOFFwill alert MATLAB to the change.MatOFFwill not apply this change until some event indicates the unit must be re-scanned. The somewhat obscureScancommand will force a new scan of the trial and update the history.
2.MatOFFhas an integrated system for reporting errors, warnings, and debugging information. The support functionissue_message()provides access to this messaging system. Use it to issue messages and use theErrorLevelandLogcommands to control which messages are issued and where they go. The MATOFF commandsprintf()might be helpful for providing a string toissue_message().
3. UseDump historyto see classes and class values after running a script.
4. Use the MATLAB editor to set breakpoints and single step a script.
5. You can open your own file from the script and leave debugging information there. It is probably best to open the file in append mode at the beginning of the script and close it at the end of the script.
6. Remember to useHistory clearto remove the results of a previous test. To reload a previously saved history, use the unit command. TheUnitcommand will re-read the history file even if the unit name has is not changed.
These examples can be found in the history_scripts subdirectory.
% history_all_events.m Create a text file called event_dump.txt |
% history_sort_time.m for trial=1:last_trial |
% history_spot_events.m events=list_events(current_trial); class_number=spot_first_class; % Accept every trial |
% history_class_dump.m |
% history_validate.m |