last updated 04 August, 2002
VCortex: Cortex for Windows
(beta version 1.0)
User’s Manual
Laboratory of Neuropsychology, NIMH
1. Introduction *
1.2 Getting the latest version of Cortex *
1.3 Technical Support *
1.4. History (you may skip this part) *
2.2 Single-computer Cortex without graphics (\VCWin32\VCSingle.EXE) *
3.1.1 Typical Keithley/Metrabyte DASH-16 settings *
3.1.2 Typical PIO24 or CIO-DIO24 settings *
3.1.3 Typical Computerboard CIO AD-16, CIO-DAS16/F, and CIO-DAS1602/12 settings *
3.2 Graphics Board Setup *
3.3 Data Acquisition Interface Setup *
3.3.1 Spike Flip Flop Circuitry *
3.3.2 Thalamus *
3.3.3 Screw Terminal Interface Diagram for the DASH-16 type boards *
3.4 Sound Card Setup *
3.6 Cortex Software Setup and Program Execution *
3.6.1 Minimum Files Necessary to run Windows VCortex *
3.6.2 Installing VCortex on a computer without any data acquisition boards, or a computer that only has PIO24 type boards *
3.6.3 Installing VCortex on a computer with a CIO-DAS16 type board *
3.6.4 Installing the DirectX Receive Program on the receive computer (Win95/98/2000/XP) *
3.7 Uninstalling Cortex *
4.2. Item files *
4.3. Conditions files *
4.4. Timing files *
4.5. Using the ITEMS, CONDITIONS, and TIMING files in a study *
4.5.1 Deciding on your Experimental Design *
4.6. Customizing Cortex with the Cortex.cfg configuration file *
5.1.1 The File Menu *
5.1.2 The Edit Menu *
5.1.3 The Options Menu *
5.1.4 The Tools Menu *
5.1.5 The Run Menu *
5.1.6 The Clear Menu *
5.1.7 The View Menu *
5.1.8 The Window Menu *
5.1.9 The Help Menu *
5.2 The File Menu Dialog Boxes *
5.2.1 File->Load->Item File *
5.2.2 File->Load->Condition File *
5.2.4 File-> Load ->Saved File *
5.2.5 File-> Load ->LUT File *
5.2.6 File->Load->External Variables File *
5.2.7 File->Load->Blocks File *
5.2.8 File->Save->Item File *
5.2.9 File->Save->Condition File *
5.2.10 File->Save->Saved File *
5.2.11 File->Save->LUT File *
5.2.12 File->Save->External Variables File *
5.2.13 File->Save->Blocks File *
5.3 The Edit Menu Dialog Boxes *
5.3.1 Edit->Individual Item *
5.3.2 Edit->Individual Condition *
5.3.3 Edit->Timing File->Modify *
5.3.4 Edit->Timing File->Delete *
5.3.5 Edit->External Variables->Generic Externs *
5.3.6 Edit->External Variables->Named Subsets *
5.3.7 Edit->Fixspot Item *
5.3.8 Edit->Reference Item *
5.3.9 Edit->LUT *
5.3.10 Edit->Add an Item *
5.4 The Options Menu Dialog Boxes *
5.4.1 Options->Block / Repeat->Sizing *
5.4.2 Options->Block / Repeat->MasterBlock *
5.4.3 Options->Block/Repeat->Individual Blocks *
5.4.4 Options->General Parameters *
5.5 The Tools Menu Dialog Boxes *
5.5.1 Tools->LUT->Set Number of Palettes *
5.5.2 Tools->LUT->Activate *
5.6 The Run Menu Dialog Boxes *
5.6.1 Run->Start *
5.6.2 Run->Resume *
5.6.3 Run->Stop *
5.7 The Clear Menu Dialog Boxes *
5.7.1 Clear->External Variables->All *
5.7.2 Clear->Blocking->CONDstats *
5.7.3 Clear->Blocking->BLOCKstats *
5.7.4 Clear->Blocking->Reset All *
5.7.5 Clear->Histogram/Rasters *
5.8 The View Menu Dialog Boxes *
5.8.1 View->Results of most recent trial->Codes *
5.8.2 View->Results of most recent trial->EOG values *
5.8.3 View->Display an Item *
5.8.4 View->Display a Condition *
5.8.5 View->Status Bar *
5.9 Window Menu Dialog Boxes *
5.10 Quick Start Instructions *
5.10.1 Dual Computer Cortex version (VCSend) *
5.10.2 VCSingle version *
6.2. Data file format *
6.3. Interrupt structure *
7.1.1 The Cortex Image File Format *
7.1.2 Image File Formats Available with DirectX version of Cortex *
7.1.4 Transparency with DirectX receive program *
7.2 Movie File Formats *
7.2.1 Cortex Movie File Format *
7.2.2 Movie File Formats Available with DirectX version of Cortex *
7.3. Color Lookup Table *
7.3.1 What is a Color Lookup Table? *
7.3.2 How Cortex uses Color Lookup Tables *
7.3.3 Using the Cortex LUT Menu Options *
8.2. Components *
8.3. Compiling the executables *
8.4. Adding new functions and external variables to Cortex *
8.4.1 Adding new system functions to Cortex *
8.4.2 Adding library functions *
8.4.3 Adding External Variables to Cortex *
8.4.4 Rebuilding Cortex after adding new functions and variables *
10.2 Image file does not display *
10.3 Movie file does not display *
10.4 Sound does not play *
10.5 Timing file does not compile *
10.6 Spikes are not appearing in the histograms *
10.7 Colors do not look correct for BMP files *
10.8 Display of movies is slower than the refresh rate of the monitor/graphics card *
10.9 EOG data is not being stored to file *
10.10 EPP data is not being stored to file *
10.11 Adjusting the gain of the analog data *
10. 12 Can not see spike codes when viewing data *
10.13 "ERROR: CODE_ISI buffer overflowed x times (data was lost)" in the error file *
A.2 Options->Block/Repeat Menu *
A.3 Functions available for MANUAL operation *
A.4 Technical details on the internal operations of the Cortex code *
Appendix C: Sample Cortex.cfg file *
Appendix D: New Timing File Functions in the Windows version of Cortex *
Copyright notice *
Cortex is a program for running neurophysiological and behavioral experiments on a PC. Although it is still undergoing revisions, the DOS version of Cortex is a working program that we have been using to collect data for more than eight years. The integrity of the data, timing accuracy, etc. has all been validated. Cortex runs behavioral paradigms designed by the user, displays visual stimuli to the subject, collects neurophysiological and behavioral data, monitors and stores eye position data, and shows the results to the user during the experiment. Because Cortex has the capability to display and manipulate any image that has been previously created and saved on disk by the user, the variety of visual stimuli it can present is practically unlimited. The program is oriented toward experiments in vision, but it can be used in a variety of other contexts.
Data acquisition capabilities include (dependent on the available I/O hardware) up to 40 spike inputs (TTL +5v digital inputs), specialized functions for monitoring hand-bar and lever movements (TTL +5v digital inputs), eye-movement monitoring functions (A/D inputs), keyboard, and mouse inputs. Reward triggering for alert-subject experiments is accomplished through TTL +5v digital output. The user retains access to the full-array of possible uses for the I/O equipment on-board (such as D/A output, or specialized digital I/O) with easy-to-use C functions. Up to five data acquisition boards, one of each type, may be accessed by CORTEX.
A separate computer is currently responsible for the graphical display on the subject's monitor. Any VESA compliant graphics card/monitor, which is supported by Microsoft DirectX, may be used. Many of the low-level technical aspects of graphical programming are handled directly by CORTEX; thus the graphical programming environment is relatively simple to use.
CORTEX is designed to simplify combined behavioral and neurophysiological experimentation by directly handling trial randomization and simple staircasing. The user retains complete control of the trial staircasing, if desired, and can generate any staircasing paradigm needed. The user can even change the staircasing design on-line, in any way, based on behavioral responses.
Associated with Cortex are a number of utility programs. Shipped with Cortex, in the \VCWin32 directory, is the DOS program, CORTVIEW.EXE. This program can be used to view the contents of the Cortex output data file. Rather than viewing the results, this program also can be used to pipe the output to a text file. From the Cortex web site, there are links to other Cortex data analysis programs. One program that was written at the Laboratory of Neuropsychology (NIMH) is the Cortex Windows Workbench. This program provides an interactive and graphical look at Cortex data files. Cortex files can also be analyzed using PCOFF, which was developed in the Laboratory of Neurophysiology (NIMH). PCOFF is a comprehensive event code sequence search program that supports graphical display of rasters, histograms, reciprocal interval plots, using a number of different schemes to align data on specific events. The program also does analog signal processing (e.g. integration, averaging, etc.) as well as non-parametric and descriptive statistics. The Laboratory of Neurophysiology recently contributed a program called MatOFF. It is a powerful event search and data plotting program based on their earlier PCOFF program. Matoff runs under Microsoft Windows using MATLAB. Other laboratories at NIH, the University of Verona, MIT, and the Salk Institute have also contributed Matlab routines to help with the analysis and use of Cortex. These Matlab routines can be accessed from links on the Cortex web page.
This document describes the new Windows version of Cortex, VCortex. It was named "VCortex" since the interface was written with Microsoft's Visual C++ product. Rather than supplying a document describing the differences from the DOS version of Cortex, or even assuming a knowledge of the DOS version, this document was intended to stand on its own for VCortex. Of course, there is so much overlap between the two versions, much of the documentation is identical to the DOS version. In fact, the program will still be referred to as "Cortex", instead of "VCortex" in most of this document.
New users of Cortex are encouraged to read this entire manual. Experienced DOS users of Cortex should read Chapters 2, 3, and 5 for the major changes. Additionally, Appendix B contains a list of know bugs, limitations, and differences from the DOS version of Cortex.
1.2 Getting the latest version of Cortex
The latest code, executables, and documentation can be downloaded from the Cortex web site:
http:// www.cortex.salk.edu/
If you are experiencing problems with Cortex which are not covered in the Cortex documentation, please post a message to the Cortex web site's discussion group. The discussion group can be accessed from the "Discussion" page of the Cortex home page (http://www.cortex.salk.edu/discuss.htm).
1.4. History (you may skip this part)
CORTEX has been gone through so many transitions over the decades that it is daunting to list everyone who has contributed to its development. Dr. Robert Desimone, who has overseen and guided the development of CORTEX since he initially ported it from the PDP-11 platform over a decade ago, made a valiant effort to do so several years ago. This is quoted below.
Thomas M. White - the lead programmer for CORTEX from 1989-1997. Re-wrote CORTEX from scratch, implemented the in-line compiler (the CORTEX state system - CSS), real-time multi-threaded data collection system, and support for multiple touch screens, graphics boards, and data acquisition systems. He also wrote the initial procortex, Stats100, and Grast utility programs. He is now devoting his time to earning a MD degree from Cornell University.
Trina M. Norden-Krichmar - took over the role of lead programmer from Tom White in the fall of 1997. She added a Windows DirectX receive program, support for DirectX sound and movies, and support for PCI data acquisition boards. She is currently working on the implementation of a Windows version of the send program, supporting the DOS version, and updating the documentation.
Jessica Olsen - joined the Cortex Team in the summer of 2001. She took Trina's simple Visual C++ Windows version of the Cortex interface, and wrote the MFC code to transform it into the wonderful dialog boxes and menus that you see today. She also has spent a lot of time testing and contributing to the documentation of the Windows version of Cortex.
Others who have contributed substantially to CORTEX include:
Dr. Steve Macknik - wrote the TIGA and MGL graphics modules, as well as the User's manual.
Dr. Andrew Mitz - helped write the technical manual, contributed several user-accessible functions to CSS, and contributed the PCOFF and MatOFF data analysis programs.
Jamie Mazer - contributed the Set module and several user-accessible functions to CSS.
Dr. Earl Miller - overhauled the Grast program for graphical analysis of CORTEX data files, but now has contributed Matlab versions of these analysis tools.
Robert Baumann - developed the CORTEX Windows Suite - a set of tools to facilitate the analysis of CORTEX data files.
Giuseppe Bertini - helped design the Cortex web pages, especially the framed function reference, and contributed Matlab data analysis routines.
David Mechner – wrote the code to support sound in the DOS version of Cortex.
Dr. Robert Desimone wrote the following for the 1997 version of the Cortex User's Manual:
It is currently impossible to list all of the people who have helped in the development of CORTEX, through their suggestions, testing, and bug-reports. The section below acknowledges those who were most helpful in CORTEX's early years.
The remote ancestor of Cortex can be traced to an assembly language program for collecting spike data and controlling an optical bench, written for the PDP-12 by David Bender in Charlie Gross' lab at Princeton during the early 1970's. The PDP-12 was a state-of-the art laboratory computer with 8K of core memory (and a 12-bit word), a bit-mapped graphics display, a real-time programmable clock, and analog and digital interfaces built in. After Dave left Princeton for Buffalo, I assembled the necessary components for a PDP-11 system (which, shockingly!, had no lab interfaces built in) and sketched the requirements for a new spike collection program that could make use of the luxurious 64K of memory (and 2.5 MB hard disk!) that was then available. The core of this program was written in 1980 in Whitesmith's C by a moonlighting mathematician, Phil Thrift, and a high school student who had been programming in C since age 12. When I left Princeton for NIMH, the program branched in its development. One branch continued to be developed at Princeton by Tom Albright, and the other branch developed at NIMH. Jeff Moran at NIMH significantly rewrote the program, then called "Behave", and added modules for controlling the subject's behavior and controlling an external Jupiter Graphics system for presenting stimuli.
As to be expected, a memory size that once seemed luxurious eventually became ridiculously too small. After the introduction of the IBM-AT, Stan Schein and I decided to switch from the PDP-11, in part because of the great difference in price and in part because the C compilers for the AT allowed transparent access to 640K of memory, whereas it was difficult to use more than 64K on the PDP-11. A Pepper SGT graphics card from Number Nine Computer was eventually chosen to replace the Jupiter graphics system. Stan, who moved from NIH to Harvard Medical School, hired Thuan Tran, then a computer science student at MIT to port the program after I had naively (and innocently!) assured Stan that the porting would take at most six weeks, once we understood all of the new hardware. Because the old program was inflexible and filled with kludges to get around memory limitations, Thuan did not actually port it. Although he retained a few design aspects of the original PDP-11 program, he completely rewrote and greatly expanded the program over the course of the next couple of years after graduating from MIT, with direction on the design by Stan and myself and support from Stan's grant (R01-EYO6096).
In 1989, Thuan took a full time job with a computer company but continued to work part-time on the state-system interface to Cortex, on contract to NIMH. At about the same time, I hired Tom White at NIMH, and he significantly rewrote most of Cortex again, in order to make it more user friendly, to greatly upgrade its stimulus display capabilities, and to improve the maintainability of its source code. He also took over the development of GRAST, a histogram display program, and Procortex and STATS100, numerical analysis programs, greatly expanding and rewriting them over the course of the past year. Tom integrated STATS100 with SYSTAT, a commercial statistical program, and wrote a data analysis compiler that users can use to write their own analysis routines, without doing any actual programming. Tom is now at Cornell Medical School in a MD/Ph.D. program, but continues to work on Cortex occasionally, out of the goodness (truly) of his heart. I myself work on Cortex code, in my spare milliseconds, and am reasonably familiar with the workings of most of the modules. Rosalyn Merrill (NIMH), Amir Geva, and Jeff Moran also worked on small pieces of code for either Cortex or GRAST at one time during their development. Most recently, Marcello Gattass, the brother of Ricardo Gattass, has taken over the development of GRAST for the time being. Marcello promises a MS Windows version of GRAST sometime in the future. Steve Wise at NIMH has contributed towards some of the considerable development expense of Cortex. Finally, Cortex has benefited from the suggestions (and, unfortunately, bug-finding) of many of its users, particularly Mark Wessinger, Lin Li, Sidney Lehky, John Duncan, Earl Miller, Jennifer Hart, Driss Boussaoud, Josef Rauschecker, Ricardo Gattass, Leonardo Chelazzi, Andy Mitz, Richard Jeo, Carl Olson, Rebecca Hoag, and Peter DeWeerd.

A Pentium computer (at least 100 MHz) with 32 MB RAM and at least a 1 GB hard drive for data storage is recommended. These specifications are based on the assumption that the computer will have Win95/Win98 installed on it also.
For the DirectX receive program, the computer must contain a DirectX supported graphics card.
Like the send computer, the receive computer should also be a Pentium computer with at least 32 MB RAM. Since graphics are more CPU intensive, if you have two unequal computers, the faster computer with more memory should be the receive computer.
The Windows DirectX receive program must be run from Windows. It can run with Win95, Win98, Win2000, WinXP. WinNT definitely can not be used for the DirectX receive program, since it does not support DirectX 5.0 or higher.
A graphics card with at least 4 MB of onboard video memory is recommended.
Some testing on a CIO-AD16 was also performed successfully. Therefore, it is likely that all of the ISA data acquisition boards originally specified for the DOS computer version of Cortex should also work with the Windows version of Cortex. From Keithley/Metrabyte, there are: DASH-16 (for analog and digital I/O), and the PIO24 or PIO96 (for digital I/O only). From ComputerBoards, there are the clones: CIO-DAS16, CIO-AD16, CIO-DAS1602/12, CIO-DIO24 and CIO-DIO96.
The PCI versions of the data acquisition cards are not supported in this release of VCortex.
When you are buying your data acquisition board, you may also want to order a screw terminal interface. The Metrabyte "Universal Screw Terminal Accessory Board STA-U" works well with the CIO products.
For use with all data acquisition boards, the screw terminal interfaces must be altered (flip-flops must be added) or have another device that performs the latching, in order to collect spike data. The Cortex web page contains the necessary diagrams under the heading "Spike Flip-Flop Circuitry and Thalamus".
Cortex home page http://www.cortex.salk.edu/
ComputerBoards, Inc. http://www.computerboards.com
Keithley/Metrabyte http://www.keithley.com/
Microsoft DirectX http://www.microsoft.com/windows/directx/downloads/default.asp
The VCSingle.exe version is a Windows program, which does not display graphics. The serial communications functions and the analog/digital capabilites are supported. Therefore, this version can be used when graphics are not necessary, or when the graphics are displayed by some other means.
2.2.1 Computer
A Pentium computer (at least 100 MHz) with 32 MB RAM and at least a 1 GB hard drive for data storage is recommended. These specifications are based on the assumption that the computer will have Win95/Win98 installed on it also.
3.1.1 Typical Keithley/Metrabyte DASH-16 settings
4) gain = whatever is convenient
5) analog eye inputs (EOG): analog input channels 3 High and 4 High
6) evoked potentials (EPP): analog input channels 1 High and 2 High
7) bar contact input: digital input 2 and 3
9) spike inputs (2 or more separate spike channels): digital inputs 0 and 1 (for the first two inputs), which are fed by flip-flops (provided by the user’s electronics shop...see Section 3.3 entitled "Data Acquisition Interface Setup"). Typically one uses the "user 1 and 2" lugs on the Metrabyte interface connector board to access the flip-flops.
10) output to clear flip-flops: digital output 0
3.3.1 Spike Flip Flop Circuitry
3.3.3 Screw Terminal Interface Diagram for the DASH-16 type boards
(DASH-16, CIO-DAS16/F, CIO-AD16, and CIO-DAS1602/12)
The dual computer Cortex program has the ability to play sounds. Sound can be used not only as stimuli, but also as an auditory feedback mechanism to assist in training. Up to 256 different sound (.wav) files can be played during an experiment. Additionally, the volume and mix of the sound from the speakers can be changed during the experiment through function calls in the Cortex timing file (see the Timing File Reference Manual for details about the functions).
Any sound card which is supported by DirectX can be installed
in the receive computer. After the sound card is installed in the computer,
the DirectX driver must be installed. Certain problems with the sound initialization
and execution during the use of Cortex are logged to the file "dxrecv.err"
on the receive computer. Please note that the sound (.wav) files must be
present on the receive computer.
3.6 Cortex Software Setup and Program Execution
In all configurations, the first step is to download the
latest VCortex distribution file from the Cortex web site. Using WinZip
or PKUNZIP.EXE, unzip the distribution file. In the instructions below,
it is assumed that the file was unzipped into the C:\VCortex directory.
3.6.1 Minimum Files Necessary to run Windows VCortex
VCSend.exe - the Windows Send program which communicates with a receive computer via a serial connection. (Replaces \remote32\wcsend.exe in the DOS version.)
VCSingle.exe - the Windows Send program which was modified so that it does not communicate with a receive computer. The serial communications and analog/digital capabilities are supported. Therefore, this version can be used when graphics are not necessary, or when the graphics are displayed by some other means. The advantage of this version is that it can be run from your desktop computer to test out timing files, etc. (Replaces \remote32\sgl32.exe in the DOS version.)
DXRecv.exe - the Windows DirectX Receive program. This program should be run from the receive computer.
cdas16.vxd - the device driver for the CIO-DAS16 type boards. If the send computer contains a CIO-DAS16 type board, this device driver programs the board to provide the timing for the Windows Cortex program.
randsd.vxd - the device driver that uses the Windows Virtual Timer Device to provide the timing. This driver is used if the user does not have a CIO-DAS16 type board. It can be used when the user only has the PIO24 type boards, or has no boards at all (i.e., the RANDOM_SPIKE_DEVICE).
cortex.cfg - like the DOS version of Cortex, this is the usual configuration file that Cortex reads in order to determine the user's hardware specifications, graphics specifications, etc. Note that some of the parameters must be set differently than in the DOS version. Refer to Appendix C for an example cortex.cfg file.
css_inc.h, encodes.h - like the DOS version of Cortex, these are the usual files required by Cortex during execution. Note that the css_inc.h file had to be changed so that the keyboard mappings are the Windows equivalents of the DOS key codes. Therefore, this css_inc.h must be the one used, not the old DOS version of the file.
msvcrt.dll, gcl52fw.dll - two DLLs that may be
needed to run the Windows version on your computer. msvcrt.dll provides
the Microsoft user interface computers. gcl52fw.dll provides the serial
communication components.
3.6.2 Installing VCortex on a computer without any data acquisition boards, or a computer that only has PIO24 type boards
device=c:\vcortex\vcwin32\randsd.vxd
(assuming the zip file was unzipped to the c:\vcortex
directory)
SET CORTDIR=C:\VCortex\VCWin32
(assuming that the zip file was unzipped to the c:\vcortex directory)
This line will help VCortex find the css_inc.h file at all times.
device=c:\vcortex\vcwin32\randsd.vxd
device=c:\vcortex\vcwin32\cdas16.vxd
(assuming that the zip file was unzipped to the c:\vcortex directory)
CDAS16=5
(assuming that 5 is the free IRQ# in your computer)
SET CORTDIR=C:\VCortex\VCWin32
(assuming that the zip file was unzipped to the c:\vcortex directory)
This line will help VCortex find the css_inc.h file at all times.
Refer to section 3.6 above, to see the changes to system.ini and autoexec.bat that were required to run VCortex. Comment out or remove these lines from system.ini and autoexec.bat, and then reboot your computer. Cortex files will only exist in directories where you have copied the files. When installing a new version, it is best to just create a new directory. Delete the old directory when the new version works with your experiment. Remember to change the Cortex.cfg file to be appropriate for your setup, and autoexec.bat and system.ini files to reflect the proper paths.
Before Cortex begins running trials, the user must specify the different varieties of experimental conditions that are to be run in the session.
4.1. Setting up the experimental conditions.
To set up the experimental conditions, it is necessary to write at least three ASCII text files "off-line", which you then import into Cortex. These three files can be written using your favorite text editor. Word processing programs cannot be used unless they can output a standard ASCII text file, which some word processing programs have as an option. It is best to work from an already existing set of files (such as the examples and demos provided with Cortex), which you can edit and modify, rather than to try to write the files from scratch the first time.
The three files you must write are items, conditions, and timing (state system) files. For a given experimental session, you can import only a single item and condition file into Cortex, but multiple timing files.
For the items and conditions files, you will note that at the top of each file, there are headings such as ITEM, TYPE, CENTERX, etc. These headings are special keywords that you should not alter. The first and last character of each keyword define the beginning and end of the data field columns located under the keywords. That is, you enter your specifications in the columns situated under each heading word, taking care not to extend any data beyond the first or last character of the heading word. Because "tabs" can mean any number of spaces, depending on your text editor, Cortex cannot interpret tabs in the files. Thus, DO NOT USE TABS. USE ONLY SPACES between values in the items and conditions files. If you use tabs, previous versions of Cortex would read in your file in a jumbled manner and become very confused. The recent versions at least warn you that tabs are present in your file. If you get a warning about tabs, re-edit your file to remove them and then reimport the file. The state system file is free-format, so tabs are fine. The format of the files is given next.
For experiments in vision, you probably have in mind a number of visual stimuli that you want to present to a particular neuron or subject. Before specifying how and when you want the stimuli to be presented, it is first necessary to describe to Cortex the stimuli you want to present. These stimuli are referred to as ITEMS in Cortex.
You must describe each item you want to use in a given experimental session in the ITEMS ASCII file, which you import into Cortex at the start of the session. For example, you might want to compare the responses of a neuron to 20 bars of light that vary in color and orientation. In the items ASCII file, you would describe the 20 items in the format required by Cortex, including the type of visual stimulus (in this case, bars of light), their height, width, orientation, color, and position relative to some reference point on the display screen (to be described later).
An example items file is shown below:
ITEM TYPE FILLED CENTERX CENTERY BITPAN WIN_WIDE WIN_TALL HEIGHT WIDTH ANGLE INNER OUTER -R- -G- -B- C ------FILENAME------
-4 1 1 0.00 0.00 0 1.00 1.00 0.00 0 0 0 x
-3 1 1 0.00 0.00 0 0.30 0.30 0.00 255 255 255 x
-2 1 1 0.00 0.00 0 1.00 1.00 0.00 255 255 255 x
-1 1 1 0.00 0.00 0 1.00 1.00 0.00 255 255 255 x
0 1 0 0.00 0.00 0 3.00 1.00 0.00 50 50 50 x
1 1 0 0.00 0.00 1 3.00 1.00 45.00 100 100 100 x
2 8 0.00 0.00 2 1.8 1.8 230 0 230 x face.ctx
3 1 1 0.00 0.00 1 3.00 1.00 45.00 250 250 250 x
Some of the columns you must fill in within the items file are as follows:
ITEM. The ITEM refers to the item number, which you henceforth use in Cortex as the name or identifier of the stimulus you have created. Some items have negative numbers. These are "special" items that are used internally by cortex. Their meaning is usually as follows, but can be used differently:
-4 Background item
-3 Fixation spot item
-2 Reference field
-1 Reference point
0 Play item
TYPE. Cortex can handle many different kinds of items, which generally fall into two classes. The first class Cortex "knows" how to create itself. This class includes bars, circles, ellipses, annuli, and ASCII characters. Each of these types has an associated code number, which you enter in this column (see below for a list of type codes). In addition, you must enter the appropriate information about the items in the other relevant columns in the file. For example, bars need a length and width, circles need a radius, etc. The second class is bitmaps and movies, which are items that you have created outside of Cortex and saved in a disk file. These also have a "type" number, which you enter in this column. For these bitmap and movie items, you must also give the name of the disk file that holds them in the FILENAME column. For the format of these bitmapped files, see Section 7. All items, regardless of type also need an CENTERX and a CENTERY, which you enter in the appropriate column.
Item type codes:
1 bar
2 circle
3 circular annulus (outer and inner diameter should be entered in the inner and outer columns)
4-6 reserved
7 ascii character
8 bitmap (name of file must be in FILENAME column)
9 ellipse
10 annular ellipse
11 movie (name of file must be in FILENAME column)
FILLED. Objects such as bars, circles and annuli can either be filled or just an outline. If you put a '1' in this column the object will be filled, and if you put a '0' it will be an outline. If a FILLED parameter is not specified, the item will be filled by default.
CENTERX, CENTERY. Each object must have a location on the screen. This sets the x and y axis location, in degrees, from the reference point. The reference point is the location that Cortex defines to be the center of its coordinate system for placing items on the screen. The user can configure this location.
BITPAN. "Bitpannable" means that you plan to pan objects around inside a stationary window on the screen. A '0' in this field means that the object is not bitpannable, and cortex should treat it like any other object. A '1' in this field means that it is bitpannable, that cortex should utilize the window size you specify (see below), and that cortex should replicate the object 4 times, to give you more object to pan around with. A '2' in this field means the same as 1, but Cortex won't replicate it. If you use option 1, there may be sharp transitions in the image at the boundaries of the four replications, but for some purposes, this is OK. Also, you may need to set the bitpan field to 2 if you have an extremely large object. The Sgt. Pepper card will not allow you to import a bitmap larger than the display screen (640 x 480), unless you specify a window around it that is smaller than 640 x 480.
WIN_WIDE, WIN_TALL. When you give a window length and width (in degrees), and the object is bitpannable, Cortex will create a window around your item. This will allow you to pan a large object around inside a smaller window.
HEIGHT, WIDTH, ANGLE. Bars require a length, width and orientation, in degrees.
INNER. Circles and ellipses require an inner diameter.
INNER, OUTER. Annuli require an inner and outer diameter.
C (Color), -R-, -G-, -B-. For items that Cortex knows how to create, such as bars and circles, you must tell Cortex what color they should be. In the color column you may, if you wish, give a letter representing the color name you want. 'R', for example, stands for red. However, these default colors will probably not have the exact red, green, and blue values you want, so you should really list the actual rgb values you want in the file instead of just giving a color name. To give the actual rgb values, use 'X' as the color name in the color column, and then enter the appropriate values in the -R-, -G-, and -B- columns. These values range from 0 (off) to 255 (maximal brightness) for each red, green and blue gun on the CRT.
For items that are stored as bitmaps, the color you list in the items file is ignored. The colors are determined by the color lookup table, which is described in Section 7. The name of a color lookup table file can be entered in a menu within Cortex or listed in the conditions file (see below).
FILENAME. For bitmap and movie items, you must give the filename. The name can include a path, if it is not in the current directory. Note, however, that the length of the name, including the path cannot extend past the ends of the ------FILENAME------ column (i.e., 20 characters total).
The second ASCII file you must import into Cortex is the conditions file. Cortex can interleave trials from a large number of experimental conditions within a single experimental session. Each condition determines what happens on a particular type of trial. In this file, you specify which items are linked together within each condition, and which timing structure is associated with that condition.
An example of a conditions file is as follows:
COND# TEST0 TEST1 TEST2 TEST3 TEST4 TEST5 TEST6 TEST7 TEST8 TEST9 BCKGND TIMING TRIAL_TYPE FIX_ID ---COLOR-PALETTE---
1 2 2 1 2 0 -3 lookup.lut
2 3 6 7 5 4 1 1 0 -3
5
3 4 4 1 2 0 -3 lookup.lut
4 6 7 8 9 1 1 0 -3
5 10 9 3 5 1 1 0 -3
6 12 13 12 13 1 3 0 -3
7 13 12 13 12 1 3 0 -3
COND# The condition number is, as you might expect, the number of each experimental condition. Each line typically defines a condition, but if you need to list more than two items on a given test screen, you can list the additional items on the next line. In the above example, condition number 2 extends across two lines. Depending on the version of Cortex you are using, the maximum number of items per test screen is either 4, 8, or 16.
TEST0, TEST1, etc. For each test screen you list the items that you want to appear together. The item numbers refer to the items listed in the items file. On a single trial, you can have up to ten successive screens worth of images presented. The timing and sequence of the display screens is given in the state system. For example, the state file could be programmed so that in condition 2, TEST0 containing items 3, 6, and 5 will appear together first on the display screen. Then,TEST1 containing items 7 and 5 will appear together, followed by TEST2 containing item 4 alone. You can switch from one display screen to the next in one frame, i.e. 16.6 milliseconds when running at a 60 Hz refresh rate.
The order of the test screens and the order of the items within the test screens are important, if the timing file contains commands to display multiple test screens simultaneously. TEST0 will always be on top, followed by TEST1, then TEST2, etc. (That is, TEST0 will cover up everything below it.) Within the tests, the items are drawn in the order they are listed. That is, if TEST0 lists items 1,2,3,4 (in that order), they will be drawn in the same order (1,2,3,4). Item 1 will be on the bottom, and item 4 will be on the top.
BCKGND. For the background, you list an item that you would like to have as the background on each test screen. Only the color of the item, as specified in the RGB columns in the items file, will be used.
TIMING. In this column, you list which timing file (state system file), you want to run with this condition. The timing files are imported separately, and are referred to by their number.
TRIAL_TYPE. Currently not used, except as the expected_response field in the output data file header.
FIX_ID. In this column, you list which item you want for the fixation stimulus. This is typically item -3, the item number that Cortex uses internally to hold the fixation stimulus. However, you may list any item.
---COLOR-PALETTE---. The color lookup table for images and movies can either be entered from within one of Cortex's menus, or listed on a line in the conditions file. This should be the name of a disk file that holds the lookup table. Each condition can have its own lookup table. Lookup tables can also be loaded by number from the state system, for dynamic changes in color during a trial.
We have neglected the issue of timing -- when and for how long the stimuli remain on the screen. Each experimental condition is associated with a timing file. The same timing file may be used by all conditions or each condition may have its own. The timing file is discussed in the next section.
The timing file is responsible not only for informing Cortex when stimuli should go on and off, but also for any behavioral contingencies such as monitoring for a lever press, checking eye position, giving rewards, etc. The price for this flexibility is that the user must program every aspect of the flow of control, every contingency, every error state, etc.. If you know the C programming language, the state language of CORTEX will seem very familiar; the language is essentially a subset of C, with a few added features.
Each timing file is written as an ASCII file and saved with a file name. After you have written and stored your state systems as disk files, you then import one or more of the files into CORTEX, which sequentially assigns them each a number. These numbers are used as names for the timing structures. In the conditions file, you specify which timing structure is associated with each condition. For example, you may want to use two different timing structures in an experiment. Each will have its own ASCII file, with its own file name, and you will import (from within Cortex) the one timing file as timing structure #1 and the other as timing structure #2. In the conditions file, some conditions may list timing file #1 as the necessary timing structure and other conditions may list timing file #2.
For information on writing the timing file, please refer
to the separate document entitled, "Timing File Reference Manual".
4.5. Using the ITEMS, CONDITIONS, and TIMING files in a study
By modifying different ITEM, CONDITION, and TIMING files,
either alone or in combination, you can create many different experiments.
For example, once you have set up an experiment using a particular set
of ITEM, CONDITION, and TIMING files, you could change the stimuli alone
by importing a different ITEMS file into Cortex. Another way to achieve
the same end would be to import a single large ITEM file that held a large
number of stimuli to use, and then switch the items to use for a particular
experiment by importing a new CONDITIONS file. The new CONDITIONS file
will select new items from the ITEMS File. Alternatively, your primary
interest might be in different experimental paradigms rather than different
stimuli. In this case, you could keep the ITEMS and CONDITIONS files constant,
but import different timing files for different experiments.
4.5.1 Deciding on your Experimental Design
Cortex can interleave trials from a large number of experimental conditions within a single experimental session. Each condition determines what happens on a particular type of trial. For example, in one experimental condition, you may want just a red item presented, and in a different condition you may want just a green item presented. Therefore, you would set up two conditions, each with a single item on the TEST0 screen.
Why use two conditions rather than one in this example? Why not just present the red item on the TEST0 screen and the green item on the TEST1 screen of a single experimental condition? You could do this, but then the order of stimulus presentations would be the same throughout the experiment (i.e. red followed by green). If you want stimulus presentations randomly interleaved, you should assign stimuli to different experimental conditions because Cortex can only randomize the order of presentation of conditions, not the screens within a condition (actually, strictly speaking, ANYTHING can be done within the state system, including randomizing the order of presentation of screens within a condition, but this is tricky stuff). Another reason to use multiple conditions rather than a single condition with multiple screens is that there is a limit to how many screens can be presented sequentially within a single condition. You can only have 10 different screens of images (TEST0 through TEST9) within a single condition, but you can have any number of conditions.
O.K., you might ask, why do you ever need multiple image screens within a single condition? Why don't you just use one condition per screen image? One reason is that screens can be switched in 16 milliseconds (or less, depending on the refresh rate capabilities of the graphics card and monitor), whereas switching between conditions typically may require about a half a second because of various disk operations that must be performed. For some experiments, you may want to switch between certain stimuli rapidly, in which case you should put the stimuli on different screens within the same condition. Another reason is that you may want pairs or groups of stimuli always presented in the same order. Thus, on one condition you may want to have a red bar always followed by a green bar, and on a second condition you may want to have a blue bar followed by a yellow bar. Finally, if there are any behavioral contingencies linked to your conditions, at present these contingencies cannot easily span different conditions (except in some limited circumstances, described later). Consequently, if, for example, you expect a specific behavioral response to a red bar only when it has been preceded by a green bar, these two stimuli should be placed in the appropriate order within the same experimental condition. If you expect a different behavioral response to a red bar preceded by a red bar, you should place these stimuli in the appropriate order in a different condition. Items, incidentally, can be reused in many different conditions.
The concept of conditions is also related to how the data
are stored. Recall that data are stored by trial and condition, with the
data for each trial preceded by a header. Thus, one trial's worth of data
in the data file would contain the data for condition one, the next trial's
worth of data might contain the data for condition five (depending on the
order of presentation), etc.. Within each trial's worth of data, the onset
and offset of TEST0, TEST1, etc can be marked by using the encode() function
in your timing file. Suppose that a red bar item is presented only on the
TEST0 screen of condition 12. To locate the neuronal responses to the red
bar in the data file, you would find all the trial data for condition 12
(the condition number is given in the header for each trial), and then
find the time of occurrence of TEST0 in each of the trials for that condition.
The spikes that fall within TEST0 onset and TEST0 offset represent the
neuronal response to the bar on that trial.
4.6. Customizing Cortex with the Cortex.cfg configuration file
Within your current directory, you should also have a Cortex configuration file, which must be named 'Cortex.cfg'. This file contains information about the type and address of the hardware devices you are using as well as information about the size and location of graphic windows on the user's display (e.g. the histograms, rasters, eye position display, etc). The file is an ASCII file that can be edited both to conform to your current hardware configuration and to customize your display. An example configuration file should have been included with the distribution code.
The MONITOR_TYPE line of the Cortex.cfg file refers to the user's monitor. If this is not set correctly, your screen may go haywire when the program loads. For the Windows version of Cortex, the MONITOR_TYPE must be set to VC.
A second critical piece of information to check is the name and address of the analog/digital I/O board in your system. This is set on the DEVICE line of the Cortex.cfg file, but the device information also is important on the THREADS and MULTI_SPIKE lines.
A third critical piece of information includes the graphics resolution and the pixels/degree that are to be used for the subject's display. These values are set in the GRAPHICS_SPECS line of the Cortex.cfg file. Because you specify all locations to Cortex in terms of degrees of visual angle, Cortex needs to know how many pixels equal one degree. You can calculate this based on the size, resolution, and distance of your monitor from the subject. Cortex assumes that your monitor has the correct aspect ratio, so that pixels are square.
An example Cortex.cfg file can be found in Appendix C.
In this section, a brief overview of the Main Menu will
be given. In subsequent sections, each submenu will be further expanded
to include a description of each dialog box and parameter.
Figure 5.3
The Exit command is one of two ways to exit the program.
(It is the same as Run->Stop) This option will close all windows, and exit
the VCortex program. If you have made changes to any of the loaded components
(items, conditions, LUTs, etc.) via the Edit menu, these changes must be
explicitly saved with the File->Save menu. If the changes are not explicitly
saved, the changes will be lost upon File->Exit.
The timing file menu has the option to modify or delete a loaded timing file (see Figure 5.4). Modify allows you to load a different timing file in the place of an already loaded one. Delete removes a timing file that was already loaded with File->Load->TimingFile.
Figure 5.4
The External Variables option has a sub-menu consisting
of Generic Externs and Named Subsets. (See Figure 5.5) The Generic Externs
option is used to modify the char, int, float, and long external variables,
which have not been given names. The Named Subset option is used to edit
the external variables by name.
Figure 5.5
Figure 5.6
Figure 5.7
The Stop option is used to exit the program. It closes all the windows and exits. (It is the same as File->Exit.) The Resume option is used to re-start a trial in a block that was paused.
Figure 5.8
Figure 5.9
The Blocking option has a pop-up menu consisting of CONDstats, BLOCKstats, and Reset All. (See Figure 5.10) CONDstats clears all condition statistics. BLOCKstats clears all block statistics. Reset All resets all blocking variables that have been set for this trial.
The Clear->Histograms/Rasters option clears all histograms
and rasters. All spike information will be erased by selecting this option
the next time that the Run->Start option is chosen.
Figure 5.11
Figure 5.12
Figure 5.13
Figure 5.14
Figure 5.15
5.2.3 File-> Load ->Timing File
A standard file open dialog box will be presented. (See Figure 5.16) Select the timing file that you would like to load into your program. Unlike the items and conditions files, multiple timing files can be loaded into VCortex memory at the same time. As each timing file is successfully loaded, a message will appear to tell the user that the file was successfully loaded. The message will also provide the number in the Cortex State System (CSS) that it was assigned. This number is important since it is used in the TIMING column of the conditions file. It is also important since it is used to specify the timing file that is to be modified or deleted in the Edit->Timing File menu.
If the timing file was not successfully loaded, it means
that the Cortex compiler found errors in the timing file. A message box
will appear telling the user to check the cortexcc.err and VCortex.err
files for more details. These error files can be found in the directory
from which the timing file was loaded. Since these files are simple text
files, they can be displayed with Notepad, or other word processing programs.
Figure 5.16
Figure 5.17

Figure 5.19
Figure 5.20
Figure 5.21
Figure 5.22
Figure 5.23
Figure 5.24
Figure 5.26
Figure 5.27
Figure 5.28
Figure 5.29
A property sheet is displayed with tabs across the top for type, color, position and window size. The type page is complex because the value of the type combo box affects the display of that page. If you would like to change the item type, select the desired type from the drop-down list. Depending upon the item type, the other parameters on the page will change to match that item type. Note: The changes made to these items only change the copy in local memory and will not be saved to the item file unless you select File->Save->Item File.
Figure 5.30
Annulus (See Figure 5.31)
Figure 5.31
Ascii (See Figure 5.32)
Note: In the items file you may enter values for height and width. These variables are misleading because you are not able to change the size of the character. A standard font is used for all character items. These variables control the size of a square within which the character will appear.
Figure 5.32
Bitmap (See Figure 5.33)
Figure 5.33
Circle (See Figure 5.34)
Figure 5.34
Cross (See Figure 5.35)
Figure 5.35
Ellipse (See Figure 5.36)
Figure 5.36
Movie (See Figure 5.37)
Figure 5.37
Polygon (See Figure 5.38)
Figure 5.38
Rectangle (See Figure 5.39)
Figure 5.39
String (See Figure 5.40)
Figure 5.40
5.3.1.2 Item Color (See Figure 5.41)
Enter the red, green, blue (RGB) values for the item's color. (see Figure 5.41) These values must be from 0 to 255. You can also press the Choose Color button to view and set the colors.
Figure 5.41
In the color dialog box which appears when you use "Choose Color", you can click the mouse on a particular color and the RGB values of that color will be returned to the color property page. You can also choose Define Custom Color to choose colors that are not displayed in this dialog box. (See Figure 5.42)
Figure 5.42
5.3.1.3 Item Position (See Figure 5.43)
Item positions are used to determine where the center of the item will be located on the subject's display. The values are in degrees of visual angle (dva). Item positions assume that the center of the subject's display has the coordinate (0, 0).
X-Position: a positive value moves the item right, and a negative value moves the item left.
Y-Position: a positive value moves the item down, and a negative value moves the item up.
Figure 5.43
Window - As mentioned above, the Window Size can only be set if the Bitpan parameter has been set to Manual. If the Bitpan field is not set to Manual, the height and width boxes will be grayed out. When you give a window length and width (in degrees), and the object is bitpannable, Cortex will create a window around your item. This will allow you to pan a large object around inside a smaller window.
Figure 5.44

The background item number specifies the item to use in the background of the subject's display during the trial. Only the color of the item, as specified in the RGB columns in the items file, will be used
The time sequence number refers to which timing file (state system file), you want to run with this condition. The timing files are imported separately (with File->Load->Timing File), and are referred to by their number.
The fixspot item number is the number of the item that will appear as the fixation point for that condition.
If you want to use a color palette, specify a path and file name in the color palette filename entry field. You can also use the browse button to traverse the file structure for the file you want to use.
The possible choices for the trial type can be selected from the list box. This parameter is currently not used, except as the expected_response field in the output data file header.
Note: The changes you make to these conditions are only
changes to local memory and will not be saved to the condition file unless
you select File->Save->Condition File.
Figure 5.46
Figure 5.47
After the number of the timing file has been entered, a standard file open dialog box is displayed to allow you to specify the new timing file to load into that place. (See Figure 5.48)
Figure 5.48
Figure 5.49


Figure 5.50
5.3.6 Edit->External Variables->Named Subsets
Figure 5.51
If an external variables file has been loaded, a dialog box appears which displays a Name & Alias box that contains all the external variables that are loaded. (See Figure 5.52) By clicking on the down arrow of the listbox, you will be able to scroll through all the named external variables. Once you select the one to be edited, the appropriate entry box will be displayed to let you edit that external variable.
Figure 5.52
The contents of the box depend on the type of the variable. (See Figures 5.53 - 5.57)The types that you are able to edit within this box are int, char, float, long and pchar (string).
Figure 5.53
Figure 5.54
Figure 5.55
Figure 5.56
Figure 5.57
Figure 5.58
Figure 5.59
The LUT Edit dialog box which appears, allows you to change the RGB values for 256 LUT entries. (See Figure 5.60) The LUT Entry # will start at 0. The Red, Green, and Blue values correspond to that entry number. When you are finished editing that LUT entry, you can select Next>> to go to the next LUT entry. If you want to go to a particular LUT entry from this point, you can enter a specific LUT entry number in the LUT Entry # field, and press Update, to display the RGB values for that entry number. The entry number, red value, green value, and blue value must be between 0 and 255. When you are finished with all of the changes for that LUT file, press ‘Exit and Save all Changes’ to store all the new values to memory. If you do not want to save your changes press ‘Exit and Do NOT Save Changes’. Note: The changes you make to this LUT are only changes to local memory, and will not be saved to the LUT file unless you select File->Save->LUT.
Figure 5.60
After selecting ‘Exit and Save all Changes’, you will be reminded that these changes are only made to local memory. (See Figure 5.61)
Figure 5.61
5.4.1 Options->Block / Repeat->Sizing
Length of circular buffer for each block: The circular buffer contains one-character codes representing the result of each block. Since this is a circular buffer, if you do not make this buffer large enough, the contents could be overwritten. For example if you run 20 blocks and the size of this buffer is only 5, it will be overwritten 4 times. The contents of this buffer can be viewed in the status window during the trial beside the heading Bbuf.
Length of circular buffer for each condition: This buffer contains one-character codes representing the result of each trial. Since this is a circular buffer, if you do not make this buffer large enough, the contents could be overwritten. For example if you run 20 trials and the size of this buffer is only 5, it will be overwritten 4 times. The contents of this buffer can be viewed in the status window during the trial beside the heading Cbuf.
Figure 5.62
Maximum number of blocks: Specifies the maximum number of blocks that can be run.
First block number: the first individual block that will be run.
Last block number: the last individual block that will be run.
Block Order: Specifies the order in which the blocks should be run. The choices are as follows:
Random without replacement: Guarantees an even distribution of the number of blocks over the maximum blocks, but randomizes the order of presentation.
Random with replacement: The blocks will be run in completely random order.
At start: Cortex clears statistics when Run->Start is chosen, but not upon Run-> Resume.
When block changes: Cortex clears statistics when a block (correct OR error) has finished.
When repeat all blocks: Cortex clears statistics when
the repeat counter is incremented.
Figure 5.63
Next condition: When this value and next block are non-zero, they override ALL other options. The only restriction is that valid block and condition numbers must be specified. The values start from 1 (not zero).
Max errors: The maximum number of errors that can occur within that block. The default is 10.
On Error: Defines what happens if an error occurs within this block. The choices are:
Retry immediately: Immediately repeat the same individual block, if an error was made. This will also increment the retry counter. If you set Max errors to something other than 0, then the block can be aborted as an error if the same individual block is repeated too many times in a row.
Delayed retry: Retry the individual block at a later time in the master block, if an error was made. If Block Order is Incremental, then the block will be done at the end of the master block.
At start: Cortex clears statistics when Run->Start is chosen, but not upon Run-> Resume.
When block changes: Cortex clears statistics when a block (correct OR error) has finished.
When repeat all blocks: Cortex clears statistics when the repeat counter is incremented.
Figure 5.64
Figure 5.65
A dialog box with two pages is displayed: Options and More. Similar to the Master Block dialog box, the Options page contains the most frequently used Master Block options, while those on the More page contain the more obscure ones. For those of you who are familiar with the DOS version of Cortex, the "More" options would only be visible if the Block->Sizing menu had the "Menu Length" parameter set to FULL.
First Condition and Last Condition: The first and last condition parameters specify the range of conditions that will be run in this block.
Condition Order: Specifies the order in which the conditions inside the block are to be run. The choices are as follows:
Random without replacement: Guarantees an even distribution of the number of conditions over the maximum number of trials, but randomizes order of presentation. Thus, if 25 trials of conditions 1-10, each will be run at least 2 times, but 5 of them will be run 3 times. Cortex figures out the number of times that each condition should be presented over the maximum number of trials. Then, the conditions can be presented in any order. It will only be evenly distributed if you run all of the trials.
Random with replacement: The conditions will be run in completely random order.
Retry immediately: Immediately repeat the same condition, if an error was made. This will also increment the retry counter. If you set Maximum errors to something other than 0, then the block can be aborted as an error if the same condition is repeated too many times in a row.
Delayed retry: Retry the condition at a later time in
the block, if an error was made. If Condition Order is Incremental, then
the condition will be done at the end of block (assuming that the "What
defines when done" variable is set to "==MaxTrials").
Figure 5.66
Max Errors: Specifies the maximum number of errors allowed before the block is considered aborted. For longer trials, you may want to automatically abort if too many error trials occur. If Max Errors value is not zero, then as soon as this many errors occur, the block will be aborted and considered an error. The master block parameters are then queried, and can be specified to have the entire block be repeated. If Clear block buffer when is set to something other than Start or Manual, all of the statistics for that block will be cleared first (so entire block will be re-done). Otherwise, only the portion of the block that is re-done will be used to determine the new correct or error status of block. This only makes a difference in case of Max Retries since that is stored locally and is always reset when a block is re-started. (Max_errors will not be cleared in this latter case, so if the block is aborted because of too many errors, it will still be considered in error unless it is reset, so NO additional trials will be run).
Max Retries: Specifies the maximum number of retries allowed when the On Error variable is set to Immediate Retry. This parameter is always reset any time a block is re-initialized. If it is set to 0, then it has no effect.
Recent Done: Specifies the number of the most recent trials that will be used to measure the subject's progress using either recentOK or recentOKtooLow.
Recent OK: Specifies the number of correct trials required from the block's most recentDone trials before the block will be considered correct
What defines done: This is how you specify when a trial is considered done. Your choices are:
% correct >= MinPctOK AND >= minTrials: This option requires that you set the Min % OK and Minimum Trials variables. Once at least Minimum Trials have occurred, Cortex checks to see whether percent correct is greater than or equal to Min % OK. The percent correct is computed from BLOCKstats. (The number of correct and number of errors are stored in the circular buffer array. When you reset the circular buffer, you also reset these two parameters). If Maximum Trials is low, you may exceed it before the percent correct condition is satisfied. If so, the block is reset, but the BLOCKstats is not. Thus, if you had specified 25 trials of conditions 1-10 and Incremental, you would get an even more lopsided distribution.
>= recentOK of recent Done AND >= minTrials: This option requires that you set recent OK, recent Done, and Minimum Trials. This condition examines the BLOCK circular buffer to get the % correct. (As mentioned above, none of these options looks at the COND circular buffers, or even the COND % correct parameters. These are available for MANUAL selection, however.) The % correct from the circular buffer must be greater than or equal to recent OK. Recent Done must be less than or equal to the size of the circular buffer. Cortex will not let you specify a larger value. The reason that it is used at all instead of just forcing Recent Done to be the same as the circular buffer size is that some blocks might want to access differently sized subsets of the circular buffer, especially for training paradigms. Recent OK is the number of correct trials within recent Done. For example, if you want the trial to continue until the subject gets the most recent 90% of the trials done, you might specify 9 for recentOK and 10 for recentDone (or 18/20,...). Minimum Trials is an optional parameter in case you want min Trials to be greater than recentDone. As with (b), if max Trials is set too low, the block will continue to be re-initialized until the correct (or error) conditions are met.
Percent OK too low: If the block's percent correct becomes this low or lower, the block will be aborted. Allows the block to be aborted if Min % OK is ever less than Percent OK too low after Minimum Trials have passed. One could then opt for a delayed retry of that block (from the MasterBlock menu) if desired
Recent OK too low: If the block's most recent Done trials have this many correct trials or less, the block will be aborted. If this is non-zero, then it behaves like a low percent corrects cutoff based upon the minimum Trials and recent Done params (see above for recent OK). For example, after giving the subject 40 trials to get used to the procedure, you might want the block to be considered correct as soon as the subject gets 18 of the last 20 trials correct. On the other hand, if the subject is getting totally lost, you might want the block to be stopped (i.e. if less than 13 of last 20 were correct if it is a binary choice).
Figure 5.67
This dialog box has five pages: Eye, A2D, Debug, Misc, and More Misc.
5.4.4.1 Eye: (See Figure 5.68)
Storage Rate: The rate at which the analog data lines will be read. This value is a countdown timer that determines when the x and y values of the EOG and EPP values are stored. Since only one analog value is read per millisecond, this value should be set to at least 2 (clock ticks between entries) if only storing EOG data, or be set to at least 4 if storing both EOG and EPP data.
EPP: The number of clock ticks between storage of EPP data.
Dynamic Fixwin size: If this checkbox is selected, the fixation window will be set by the size of the fixspot item on the screen. If this checkbox is not selected, a static fixation window size can be set in the Eye Window Size parameter. For studies in fixating subjects, you need to specify the size of the fixation "window", or fixation criteria. If, in the timing file you wrote that the subject must start to fixate by some time point during the trial, then Cortex will use the window size to decide whether fixation has been achieved (and remains achieved). To open the window all the way up, give it a size of 30 degrees or more.
Eye Window Size: Sets the size of the fixation window.
Y: y-dimension in degrees of visual angle

Cortex cannot actually measure degrees of eye position. It can only measure voltages from the A/D converters. Cortex assumes that the full-scale range of the A/D converter is equivalent to an eye movement from one side of the display screen to the other. If this is not so, you should adjust the eye position gain either using the gain setting on your eye tracking hardware, the gain setting on the analog input board, or let Cortex set the gain programmatically using the value supplied in the Cortex.cfg file as the A2D_GAIN parameter. Refer to the documentation for your particular board for information on how to set this parameter. Typically, you shift your fixation stimuli 5 degrees or so to the left, right, up, and down, and keep adjusting the eye coil hardware gain and offset setting until Cortex shows that the subject's eye position is on it. The size, in degrees, of the "crosshair" on the eye display can be changed by setting the "Max saccade allowed" parameter in the Options->General Parameters->Eye menu, which is a convenient way to measure distance in degrees on the display screen.
EOG offset:
Y: This value will be subtracted from the Y values of the incoming A/D data. The default setting is 0.


Reward Duration: When the reward() function is encountered in a timing while running a trial, a TTL pulse will be sent to the reward solenoid, if wired appropriately. By default, the reward TTL pulse will have a duration of 20 milliseconds. This parameter is used to change this duration.
Don’t unload conditions: By default, Cortex loads the items of the condition at the time that the trial is started. This can be time consuming if the condition contains large bitmaps or movies. Therefore, this parameter can be used to tell Cortex not to unload the conditions between trials.
Include error trials in histogram: By default, trials which are "error trials" do not have their spikes accumulated into the histogram at the end of the trial. (To label a trial as an "error trial", the response_???() functions must be called in the timing file.) You can use this parameter to override this default behavior, and have these spikes included in the histogram.
User graphical display on: Can be used to prevent drawing to occur on the user's screen
Show dynamic play item positions: Play has not been implemented in this release, so this field is not used.
Timer: Used to set the timing. Currently, only 1000 Hz is supported.

KHz resolution of data: The rate at which data is collected. Currently, should be set to Auto.
Current bits per pixel: This parameter tells you what the bits per pixel the subject's display is set to support. This parameter was set in the GRAPHICS_SPECS line of your cortex.cfg file. You are not able to change this variable from this dialog box. Instead, you must exit VCortex, change the color depth parameter in the cortex.cfg file, and then re-start VCortex.
Change bitmap depth on conflict: Currently, not used.
Figure 5.72
5.5.1 Tools->LUT->Set Number of Palettes
Figure 5.73
Figure 5.74
Figure 5.75
After asking you if you are sure you want to use this name, you will have to verify the extension to use. The first file created with that prefix in the given folder will receive extension ".1’. (see Figure 5.76) The next time you use the same prefix for the data file, the extension will be ‘.2’, and so on. You can also change the extension to something else if you do not want to use the given extension. If the prefix and extension are already in use, you will be prompted to choose if the new data should be appended to the file, or if the file should be overwritten. After you select "OK" the trial will run.
Be aware that changing the file path in this file open menu actually changes the current working directory of the program, much like changing the directories from the DOS prompt with "cd". If you are expecting LUT files, etc., to be in the current directory, you must be in that directory, otherwise they will not be found. One workaround is to put the path to the LUT into the conditions file PALETTE_NAME parameter. Another workaround is to actually copy the LUT files into the directory where you will be running VCortex and storing the data. In this case, the VCortex executables do not have to be in the data storage directory, just the LUT files.
Figure 5.76
Figure 5.77
5.7.1 Clear->External Variables->All
Prompts the user before clearing all the blocking statistics and resetting to one empty block.
5.7.5 Clear->Histogram/Rasters
5.8.1 View->Results of most recent trial->Codes
There are a few known bugs and limitations associated with this menu option. First, as mentioned in the Run->Start section, the file dialog box has the ability to change the current directory. Therefore, if you have chosen an output data file path that does not contain encodes.h, this menu option will report that encodes.h is not found. A simple workaround is to copy the encodes.h file into the output data file directory.
Additionally, two bugs are present in this option. The first bug is that once the Codes Window is closed, VCortex crashes if the user tries to open the window again with this menu option. The second bug is that if the Codes Window remains open, and the user runs another trial, the Codes Window will not change the text inside the window unless you resize the window.
Figure 5.78
5.8.2 View->Results of most recent trial->EOG values
Additionally, two bugs are present in this option. The first bug is that once the EOG values window is closed, VCortex crashes if the user tries to open the window again with this menu option. The second bug is that if the EOG values window remains open, and the user runs another trial, the EOG values window will not change the text inside the window unless you resize the window.
Figure 5.79
Figure 5.80
5.8.4 View->Display a Condition
Figure 5.81
If the Cortex executables have been downloaded and installed on your computers (see Chapter 3), these instructions will run you through a brief introduction to the use of Cortex. These instructions assume that you have installed Cortex in a directory named \vcortex.
5.10.1 Dual Computer Cortex version (VCSend)
Although the details of the program will be discussed later, one important detail relevant to the capabilities of Cortex is the manner in which data are stored. Cortex currently keeps all of the raw data (time of occurrence of each spike etc.) for an experimental run in a disk file rather than in memory, except for a one-trial buffer. While this allows both for a virtually unlimited amount of data to be collected and for a simple data-saving module, it would be too time-consuming to sort through the disk file to resynchronize the histograms and rasters to a new time or event on-line during an experiment. Therefore, the synchronization of the on-line rasters and histograms is set and controlled by the state system and cannot be resynchronized during an experiment. You can, of course, do anything you want with the raw data outside of Cortex itself, after the data have been collected.
Each trial's worth of data is preceded in the disk file by a "header" that contains information such as the experimental condition number, the type of behavioral response that was expected of the subject (if any), the type of response the subject actually made, whether the trial was performed correctly, the types of errors that were made, and the sizes of various arrays that follow. One array contains the codes for all events that occurred during the trial, including spikes, stimulus presentations, behavioral responses, etc. A second array contains the times of occurrence of each of the corresponding events. Time is measured from the beginning of the trial, and is represented by a 32 bit long integer. Additional arrays may contain eye movement or evoked potential analog data. The information in the header can be used to quickly sort trials for later data analysis. For example, suppose you want to know the individual firing rates to each of the stimuli presented on each experimental condition, for correctly performed trials only. This can easily be done using a combination of information in the header together with the information in the data arrays.
It is important to note that histograms are not stored in the disk data file. Averaged histograms can be recompiled off-line from the data in the arrays, using other Cortex data analysis programs.
Two Win95/98 device drivers (VxD) were written to provide
the timing for the Windows version of Cortex. The cdas16.vxd, uses the
DAS1602 onboard pacer clock to generate precise 1millisecond timing pulses.
The pacer clock runs continuously. The randsd.vxd is used when there is
no DAS1600-type board to generate the clock pulses. Since there is no pacer
clock available, the Windows Virtual Timer Device (VTD) is used to generate
the timing for the randsd.vxd. At each of these timing pulses, an interrupt
routine is called. Inside the interrupt routine, the data lines are sampled.
The control of behavioral contingencies and the presentation of stimuli
all take place outside of the interrupt routine.
7.1.1 The Cortex Image File Format
The Cortex image file format is a binary file, arranged as successive rows of 8 bit pixel values, (i.e. the first horizontal row of pixel values, followed by the second row, etc). Preceding the image data is a header describing the image file. Byte location 10-11 should contain the pixel depth of the image. At byte location 12-13 in the file you should put the X size (i.e., the number of pixels in width), in bytes. At location 14-15 should be the Y size (i.e., the number of pixels in height). In addition, at byte location 16-17 should be the number of frames, for movie items. Subsequent frames of the movie, or standalone image files should just contain a zero in byte 16. The image data itself should begin at byte location 18 in the file.
This information is summarized as follows:
Byte Locations in File
| 0 - 9 | 10 - 11 | 12 - 13 | 14 -15 | 16 - 17 | 18 to end |
| blank | Pixel Depth | X size | Y size | number of frames | Image data |
To convert the other image format files into Cortex image format files, there are a number of utilities that are provided "as-is".
If the files are stored as TIFF or JPEG: On the Cortex web site (from the Documentation page) there is a link to the Matlab routines. You will need to traverse the directory structure until you get to \pub\cortex\matlab\bj-img-func\. There is a document named "mat-img-functions.doc" that tells how to use these functions to go from TIFF or JPEG into Cortex image format. These routines can change a whole directory of TIFF or JPEG files to CTX files at the same time, and create a single LUT file. This is important, since only one LUT is allowed per condition in Cortex. In the graphics program that is used to create the images, the images should be saved in RGB Color and 8 bits per channel. (In Adobe PhotoShop, these settings can be made in the Image:Mode menu.)
If the files are stored as BMP, HDF, JPEG, PCX, TIFF, or XWD: Follow the links on the Cortex ftp site to \pub\cortex\matlab\salk\saveload. There is a document named "vclimg.doc" which describes how to use these routines. These routines can be used to convert Cortex image files from other formats, or into other formats from Cortex images.
If you do not have Matlab, the only other program is one
for use with TARGA (TGA) files. There is a DOS program called TARGCORT.EXE
up on the Cortex ftp site in the \pub\ cortex\targcort directory which
will convert the images from TARGA->Cortex. (Of course, you can convert
your BMP or other image format files to TGA using a commercial graphics
program, and then use targcort.exe.)
7.1.2 Image File Formats Available with DirectX version of Cortex
The DirectX receive program can currently only load BMP files, in addition to the standard Cortex (CTX) image files. The type of the bitmap file is determined by the file extension. That is, to be processed correctly, BMP files must have the extension .BMP. All other bitmap file extensions are assumed to be the standard Cortex (CTX) bitmap type. Therefore, this naming convention should be transparent if you continue to just use CTX type bitmaps. It is assumed that the CTX files follow the documented format from section 7.1.1.
In the DirectX receive program, .bmp files in 8 bpp will
use the Cortex LUT. (For example, if the LUT is not in the conditions file,
then the image will be displayed in black and white.) It is therefore recommended
to create a default LUT that contains the Windows system palette, for example,
for use in 8 bpp. At greater than 8 bpp, the images will look fine, and
will not need/use the Cortex LUT. There is a utility program, bmp2lut.exe,
which extracts the LUT from a .bmp file. It is available "as-is" from the
Cortex ftp site.
7.1.4 Transparency with DirectX receive program
For the DirectX receive program, transparency works with both .BMP and CTX image files. The background color as specified in the items file is used as the "source key" color. All pixels in the image that are this color (i.e., LUT entry #0), will be transparent when displayed in Cortex. The files \cortex\demos\dx\dxtransp.* show this effect nicely.
7.2.1 Cortex Movie File Format
For animation, such as dynamic motion displays, you may
concatenate any number of (CTX) images in the same disk file, and you can
instruct Cortex to display them sequentially (or any order you like). Each
frame should be organized like the Cortex image file format described above.
That is, each frame should have a header, which sets the x and y size,
the pixel depth, etc.. The number of frames in the movie only needs to
be set in the first frame's header. For the two computer versions of Cortex,
the number of frames field must be (number of frames minus 1, since it
counts the frames as starting from zero.)
7.2.2 Movie File Formats Available with DirectX version of Cortex
The DirectX version of the "receive" program (in two computer Cortex) has the ability to play AVI, MPEG, and QuickTime movies, in addition to the standard Cortex (CTX) image file format based movies. The type of movie file is determined by the file extension. Cortex gets the filename and item TYPE ("11" for movies) from the items file. To be processed correctly: AVI files must have the extension .AVI; MPEG files must have the extension .MPG; and QuickTime files must have the extension .QT or .MOV. All other movie file extensions are assumed to be the standard Cortex (CTX) movie type. Therefore, this naming convention should be transparent if you continue to just use CTX type movies.
When you display a movie in Cortex, it reads all of the frames of the movie into memory. Then, if you want to loop through the movie for a specific period of time, it just uses the memory copy to play over and over again. AVI, MPEG, and QuickTime movies use DirectShow to uncompress/read the movie frames. It takes a long time to load an AVI file (at least 20 seconds to load a 75-frame movie). Therefore, it is definitely better to make the movie as short as possible (i.e. 2 seconds) and then tell Cortex to loop for 10 seconds, if the movie actually contains a repeating cycle inside the movie file.
Since the movies are very slow to load, you might want to use the "dont_unload_conds()" function in your timing file, if the movie is to be used in each trial.
Since it uses the DirectShow component of DirectX to display the movies, Microsoft Internet Explorer version 4.0 or higher must be installed on the receive computer.
Not all video codecs are supported by DirectShow. The list of video media types that are supported with DirectShow can be found at the web site: http://www.microsoft.com/directx/dxm/help/ds/appendixes/media_types.htm
Colors for the (non-CTX) movies look best when you are running at 32 bpp, but it makes the movie slower to load. For 8 bpp, you will need to generate a LUT that will look good with the movie.
Only the video track of the movie file will be played by Cortex. The audio track will be ignored.
7.3.1 What is a Color Lookup Table?
In order to display an image on the screen, the program
must tell the graphics hardware how to color each pixel that makes up the
image. For an "8-bit image", for example, each pixel has a color which
is described by 8-bits of information. 8-bits of information can specify
256 different values. As you know, a computer can display millions of different
colors (i.e. more than 256!). To allow as much customization as possible
for the 256 colors, color lookup tables were invented. All a LUT really
is, is a matrix of red, green, blue values that tell which colors you want
to make up your image. For instance, a LUT file might look like this:
| INDEX | RED | GREEN | BLUE | (resultant color) |
| 0 | 255 | 255 | 255 | white |
| 1 | 0 | 0 | 0 | black |
| 2 | 255 | 0 | 0 | red |
| 3 | 0 | 255 | 0 | green |
| 4 | 0 | 0 | 255 | blue |
| 5 | 160 | 0 | 160 | light purple |
| 6 | 100 | 100 | 100 | gray |
| etc. |
Your image file now uses its 8-bits/pixel to give an index into this matrix. That is, when the pixel should be black, the image file will contain a "1". If it should be green, it will contain a "3", etc. You can probably see how a LUT would be useful if you wanted to change the colors of your image. Let's say you wanted to change all the black in your image into green. Instead of changing anything in your image, you could simply change the LUT so that index[1] contained (0,255,0) instead of (0,0,0).
7.3.2 How Cortex uses Color Lookup Tables
Cortex uses the first 128 of the 256 rows in the lookup table for single-color items such as bars and circles, and the upper 128 rows to hold the color values for bitmapped patterns stored in disk files. Each of the single-color items in a given condition gets one row in the lookup table. The user enters the red, green, and blue values for each of these items in the items file. (Note: The actual row assigned to the item in the lookup table is irrelevant to the user, and therefore is assigned by Cortex using a specific algorithm. To retrieve this information, call the function ITEM_POSlut_index() in your timing file.)
For the bitmapped items, which are necessarily 7 bits "deep", you must fill in the upper 128 rows of the lookup table. This table of values can be created off-line, or internally through the LUT menu. Cortex must be given the name of the file that holds the values, either in the conditions file, or by loading it via the File->Load->LUT File menu option. The file is organized as a series of four successive integers for each of the 128 table locations that will be used. The integers hold the red, green, and blue gun intensities, plus a dummy integer. The user has the option of specifying one "experiment-wide" lookup table that will be applied to all bitmapped items, or of assigning a unique lookup table to each experimental condition. At the appropriate time, the lookup table values are read by Cortex into the graphics card memory. These lookup tables can be full-color tables or gray-scale tables, depending on the needs of the user.
For achromatic sinewave gratings, the user will normally "linearize" the output on the display CRT by adjusting the lookup table values so that equal increments in pixel values will produce equal increments of intensity on the CRT screen. It should be noted that in the current version of the program, if the user wants two or more bitmapped full-color items on the screen at the same time, they must use the same lookup table.
7.3.3 Using the Cortex LUT Menu Options
In the conditions file, there is a column for the "Color Palette". Each condition can only have one color lookup table; so if you have multiple items in that condition, they will all use the same lookup table. Cortex can handle multiple LUTs in memory, but each LUT must be assigned a number. The number of LUTs that can be loaded into Cortex is dependent on the memory available in the computer. Cortex will try to allocate memory for the number of LUTs that you request.
As mentioned above, Cortex uses the bottom 128 values of the color lookup table to store the color of the background, and the colors of any of the "generic" items (such as, bars, circles, etc.) You can override this behavior by loading the LUT starting from index 0. To do this, you must first tell Cortex how many LUTs that you have (using the Tools->Number of Palettes menu). Then, load the LUTs using File->Load->LUT File menu. In the File->Load->LUT File dialog box, you can specify the index at which you would like to start loading the LUT values. If you want the starting index of the LUT to be 0 (instead of the default 128), you can specify this value here, so that the values will be loaded into the VCortex memory starting at index 0. Additionally, you must go into the Options->General Parameters menu and set the "Load CLT from what index?" parameter on the Misc page to 0 instead of 128. (The load_CLT() function has the same effect of loading the CLT at index 0.)
To change a lookup table, once it is loaded, you can use the Edit->LUT menu. The changes made in this menu option will just be held in memory. If you want them to be actually written to disk, you must choose File->Save->LUT File.
Lookup tables are usually created by taking an existing table, and then changing/saving the values to a new file (as outlined in the previous paragraph). A lookup table can also be created with a binary editor (or a C or Matlab program) in which you would write each value of the table. The lookup table is just made up of short integers for the red, green, blue, and a dummy value (just make it zero), for each index of the LUT. (That is, index 0, followed by index 1, etc. ) . The Cortex ftp site has a Matlab routine that will write a Cortex LUT from a given matrix. (See \pub\cortex\matlab\salk\writelut\ on the Cortex ftp site.)
The Cortex program includes over 35,000 lines of source code in about 200 source files. The Windows code has been compiled with Microsoft Visual C++, version 5.0.
The code is compressed into the "Zip" format. Zip files can be uncompressed with commercially available products, such as WinZip and PKunzip. After the VCortex distribution zip file is unzipped into a directory, a listing of the directory should look something like this:
Volume in drive C has no label
Volume Serial Number is 07CE-0A09
Directory of C:\VCortex
. <DIR> 08-02-02 5:17p .
.. <DIR> 08-02-02 5:17p ..
DEMOS <DIR> 08-02-02 5:17p demos
DXSOURCE <DIR> 08-02-02 5:17p dxsource
SOURCE <DIR> 08-02-02 5:17p source
VCWIN32 <DIR> 08-02-02 5:17p vcwin32
WCORTEX <DIR> 08-02-02 5:17p wcortex
0 file(s) 0 bytes
7 dir(s) 641.51 MB free
The following directories hold the source code, executables,
and demos for VCortex:
| \demos | files to demonstrate the functionality of Cortex |
| \dxsource | source code for the DirectX receive program |
| \source | source code for the send components of Cortex |
| \vcwin32 | executables for send programs for Cortex |
| \wcortex | executable for the DirectX receive program |
8.3. Compiling the executables
To build the Windows DXRecv.exe program, the VCSend.exe program, and the VCSingle.exe program, the compiler is Microsoft Visual C/C++ version 5.0. For the DirectX Receive program (DXRecv.exe), you will also need to download and install the Microsoft DirectX SDK from the Microsoft web site (http://www.microsoft.com/directx/developer/downloads/default.asp).
While functions can be written into a state file, it is sometimes more advantageous to incorporate the functions into Cortex itself. For example, to implement the natural log function, it is easier to just use the built-in C log function than to write a complete state file function to calculate logs. Using the built-in C function will also run a lot faster.
8.4.1 Adding new system functions to Cortex
The first step is to create the new function itself. The function can be added to the file _userfns.c. It might be more useful to create a new file for all your new user functions, using _userfns.c as a guide. After entering all the appropriate #include, extern, and #define statements, a typical function entry is added like this:
float CSS_polar2x(CSS_ARGS) /* name always starts with CSS , arguments are always CSS_ARGS */
{
/* Grab the arguments of CSS_polar2x(). They are in the format: type,name,argument# */
CSS_ARG(float,r,0); /* argument #0: type=float, name=r, number=0 (1st) */
CSS_ARG(float,theta,1); /* augument #1: type=float, name=theta, number=1 (2nd) */
double rad_per_deg=.01745329;
/* use the CSS_polar2x() arguments as the arguments of cos().*/
return(r * cos(theta * rad_per_deg));
}
The second step is to add a function declaration to the statefns.h file. For the example above, the entry looks like this:
float CSS_polar2x(CSS_ARGS)
The third step is to add an entry into the SystemFns[] array in the ufnlst.c file. SystemFns[] = {} lists the master program's system functions which are accessible from CSS. Since CSS can't pass arguments directly to the stack, it is necessary to write an interface function for each of the master program's functions that one wishes to access.
Using the example of polar2x:
{ "polar2x", 0, "fff", CSS_polar2x }, the fields specify the following:
This cryptic code identifies variable types for the function
and its parameters. The first "f" is for the function return type (in this
case "f" stands for float). This, and only this, position can also take
the value 'v', for void. The second "f" is for argument #0 (see above),
the third "f" is for argument #1, etc. The syntax string must contain at
least one entry: the return value of the function. "v" is only valid as
a return value. Functions which take no arguments, but return something
(say float) would have a syntax string of "f", NOT "fv". Also, functions
with no arguments take a syntax string of length one, such as "v", NOT
"vv". The other types are:
| c | character |
| i | integer |
| l | long |
| f | float |
| C | pointer to character |
| I | pointer to integer |
| L | pointer to long |
| F | pointer to float |
| 0 | double pointer to character |
| 1 | double pointer to integer |
| 2 | double pointer to long |
| 3 | double pointer to float |
| . | variable length argument list |
| v | void |
| V | pointer to void |
| P | pSysfn (pointer to a system function) |
| Q | pCSSfn - the starting index in the array m.code.a (used in the CSS) |
Example:
void MessageString(int which, pchar message) would be characterized by "viC"
The '.' is used for variable length argument lists, such as:
void printf(pchar fstring, ...) characterized by "vC."
Thus, when '.' is the last entry in a syntax string, that argument is optional, and any number of arguments of any type may follow the last required argument. CSS ensures that the proper number of arguments are popped off the internal stack. Only the last entry in a syntax string may be '.'.
For example, log() is of the form
double log(double);
In order to easily add log to CSS, add the following three lines:
b) In a source code file, such as \ufns\_system.c, add:
void CSS_????(dataEls *args) {
????(...);
}
instead of trying to return a value. For example, the way to map the function free() would be
CSS_1d(free,void,pchar)
CSS_1s(free,void,pchar)
CSS_1v(free,void,pchar)
Notice that the macros that end in "d" and "s" remain the same. Only the one that translates into code needs the "v" suffix.
8.4.3 Adding External Variables to Cortex
In the file \ufns\ufnlst.c, EXTERN_VAR ExternVars[] = { } lists all of the variables intrinsic to the master program which are accessible within CSS. For examples, follow the prototype listed in ufnlst.c. One major caveat: Arrays are treated differently in C depending upon whether they are statically or dynamically defined. The latter include both a pointer (4 bytes) and allocated space for the elements. To conserve space, C compiles static arrays so as to remove the need for the pointer. Thus, one might think of declaring EV("array",pint,&array[0]);. This may not be completely safe (and EV("array",pint,array); is definitely fatal). The best approach is to actually have a separate variable that points to the static array. For example:
int arrayData[10];
pint array = &arrayData[0];
EV("array",pint,array);
As to access of these variables, the fact that they are listed in ExternVars[] makes them globally accessible in CSS, so it is not necessary to have a line like
extern int array;
and in fact, CSS will generate error messages or worse
if this occurs.
8.4.4 Rebuilding Cortex after adding new functions and variables
After new functions or variables have been added, the Cortex executables must be rebuilt. If your new functions are in a new file, you will need to modify the workspace project files in the \source\VCSend and \source\VCSingle directories to include your new source file name before rebuilding. If you used _userfns.c, then project file does not need modification.
The argument-passing scheme may be changed in the future. Therefore, it is essential that the macros be used instead of their translations.
Linking cortexcc.exe generates a slew of error messages. It is supposed to, since the file containing SystemFns[] contains pointers to code. Neither that code, nor the pointers needs to be used by the parser. Therefore, any unresolved externals from that file are OK and expected, and cortexcc.exe will run perfectly correctly. Unresolved externals in the master program are unacceptable and will cause the system to crash.
typedef struct {
unsigned short length; /*not currently used*/
short cond_no; /* the experimental condition numb.*/
unsigned short repeat_no, /*repeat # of entire block structure*/
block_no, /*block no., this condition*/
trial_no; /*trial # for this condition/
unsigned short isi_size, /*size in bytes of this trial's array of times*/
code_size, /*size in bytes of this trial's array of codes*/
eog_size, /*size in bytes of this trial's array of eog values*/
epp_size; /*size in bytes of this trial's array of epp values*/
unsigned char eye_storage_rate /* millisecs between eye samples */
unsigned char kHz_resolution; /*0/1 if 1 msec, 10 if 0.1 msec*/
short expected response;
short response;
short response_error;
} DIR_ENTRY;
All but two of the above values are short integers. The types of response errors are given as an enumerated type in disk.h (see RESPONSE_ERROR). Following the header are the time and code arrays, the epp array, and then the eye movement array. For each event code (such as the occurrence of a spike, the onset of a stimulus, etc.,) there is an associated time. The time is measured in milliseconds from the start of the trial, and is given as a unsigned long integer (i.e. 32 bits). The event codes are listed in histogra.h as an enumerated type (see CODE).
Note: for repeat #, block #, cond. #, etc, all values are base 0 (e.g. the first trial is trial 0).
repeat_no. The repeat # for the entire block structure. The user sets up how many conditions per block and how many trials per block. When all of the blocks have been run once, the repeat number is incremented.
trial_no. Trial number for this condition.
block_no. Conditions can be assigned to blocks. For each block, the user specifies the number of trials and conditions to run before moving on to the next block. This is the block in which this condition is located.
expected_response. This field gets set during the trial from the value under the TRIAL_TYPE heading of the conditions file. See DISK.H for a list of the TRIAL_TYPEs.
response. This field gets the value that you pass into one of the response_???() functions. For example, if you called response_correct(15), then "response" would contain the value 15.
response_error. This field gets the value that
one of the response_???() functions return. For example, response_correct()
returns NO_ERROR, which is 0.
Each data item occurs sequentially in the file.
The following header data items each occupy two bytes (one integer) in the data file, except for eye_storage_rate and kHz_resolution, which each occupy one byte.
DATA MEANING
0 length (not used)
1 condition number
0 repeat_no,
0 block number /*block no, this condition*/
0 trial_no
2560 size of array of time codes (e.g. 2560 bytes, 4 bytes per code)
1280 size of array of event codes (e.g. 1280 bytes, 2 bytes per code)
500 size of array of eog values (e.g., 500 bytes, 2 bytes per value)
500 size of array of evoked potential values (e.g., 500 bytes, 2 bytes per value)
4 milliseconds between eye samples - e.g. 4 = 250 Hz (BYTE)
0 time resolution of interrupt routine (1 kHz) (BYTE)
1 code for expected response
2 code for actual response
0 first time code (see associated event codes below)
100 second time code
500 third time code
etc.
The following data items each occupy 2 bytes (short integer)
18 first event code
24 second event code
40 third event code
etc.
The following data items each occupy 2 bytes (short integer)
The following data items each occupy 2 bytes (short integer)
Following these data items would be the header for the next trial's worth of data...and so on until end of file.
1) Check that you have the correct serial cable (see section 2.2.8), connected between the two computers, and it is between the correct COM ports. That is, on some computers there are two COM ports, so make sure that the cable is between COM1 on both (the default).
2) Are the COM ports enabled and OK? Boot up the computers into Windows, and look at the properties of the COM ports in the Control Panel:System:DeviceManager window. Make sure that it says that the ports are operating and there are no conflicts. There should be something in the system BIOS that lets you enable/disable the ports. If you can find out how to boot up into the BIOS/CMOS settings, you can check to make sure that the ports are enabled. (Usually, you have to do something like CTRL-ALT-ENTER, or F2 during reboot, etc., and it will show the CMOS/BIOS settings.)
You can also determine whether GreenLeaf CommLib (the communications library that Cortex uses) can recognize the port, by using the debug commands suggested in their product documentation.
"From a DOS command prompt, start debug.exe:
C>DEBUG
-i2fa
01
-i3fa
01
-q
C>
This procedure will look at the Interrupt ID Register
for COM1 and COM2, respectively. Each command reads the contents of one
of the UART registers for COM1 and COM2. The '01' returns mean there is
a UART present. If you see anything other than '01' or 'C1', it means that
CommLib will not recognize the port. 'C1' means the hardware is a 16550
or related UART and the FIFOS were left enabled. Some applications will
experience difficulty detecting a port if a prior process did not disable
the FIFOs."
3) Are the computers capable of a baud rate of 115200? As in 2) above, look in the Port Settings panel. If you can not scroll down and see 115200 listed in the "bits per second" field, then your computer can not handle 115200. You will need to change the COM_PORT line in your cortex.cfg file on the send computer to the highest value possible for your computer. You will also need to start up the receive program, so that the baud rate is supplied as a command line argument. For rvesactx.exe, type: rvesactx @1200 to set its baud rate to 1200. There is no space between the @ and the 1200. For the DirectX receive program, put the @1200 into the shortcut properties at the end of the Target: line, for the shortcut to the dxrecv.exe program that you created on the desktop.
4) Check if there are any .err files generated in the current directories on both computers. These files might give some hints. Make sure that you check the date of the .err file. It is overwritten only if there are errors, so it might contain text that is not even relevant to the current problem. To be sure, you can just delete the .err file on the receive computer. It will be generated again if there are errors during execution.
5) Another possible scenario is that both sides of Cortex start up properly, but the process stops before displaying the menu. That is, the screen freezes without any error message with the text "using font HELVB, FON ...". If this is the case, then it is not a communications problem. Cortex got past the part of the code that does the "serial handshake" between the two computers. It is probably a problem with the initialization of the graphics. Make sure that you have the appropriate graphics driver installed (Scitech or DirectX), and the driver is operating properly. Also check that the resolution that you have specified in the GRAPHICS_SPECS line of your cortex.cfg file on the send computer, will actually work with the driver that you are using.
10.2 Image file does not display
Review section 7.1 of this manual, and make sure you are using an image format that is supported by the version of Cortex that you are using. Remember also that the 3-letter extension of the image file name is important in telling Cortex what image file format to expect.
If you are using the two-computer versions of Cortex, it is imperative that the image file resides on the receive computer in the directory which you have specified in the items file. If you have not specified a directory, Cortex will look for the file in the directory from which you are running the receive program. If Cortex can not find the file, it will report the error "can't calc item size" on the send computer screen.
Another common problem is that images created in other graphics programs do not display properly in Cortex at 8 bpp. To solve this, when using Adobe PhotoShop, for example, to create the .BMP file, make sure to save the BMP files as "Indexed Color" and "8 bits per pixel". When you save the file as a bmp file in PhotoShop, it prompts you to choose between Windows and OS/2 format. Make sure it is Windows format, not OS/2.
10.3 Movie file does not display
Review section 7.2 of this manual, and make sure you are using a movie format that is supported by the version of Cortex that you are using. (That is, only the DirectX receive program will support movie types other than the original Cortex movie format.) Remember also that the 3-letter extension of the movie file name is important in telling Cortex what movie file format to expect. Also remember that not all video codecs are supported by DirectX, so check the list of supported video codecs on the Microsoft web site.
As in 10.3 above, if you are using the two-computer versions of Cortex, it is imperative that the movie file is on the receive computer in the directory which you have specified in the items file. If you have not specified a directory, Cortex will look for the file in the directory from which you are running the receive program. If Cortex can not find the file, it will report the error "can't calc item size" on the send computer screen.
If you are using the original Cortex image format movie, make sure that the number of frames in the movie is specified in the header of the first frame as (number of frames minus 1).
Sound is only supported for the two-computer versions of Cortex. If you are using a two-computer version, then the sound card must be installed and operational in the receive computer. Additionally, the sound (.wav) files must be located on the receive computer in the directory which was specified in the SOUNDload() function call in your timing file. If no directory was specified, then Cortex will look for the sound file in the directory from which the receive program is running.
For the Scitech (MGL) receive program, the sound card must be SoundBlaster compatible. For the DirectX receive program, the sound card must be supported by Microsoft DirectX.
10.5 Timing file does not compile
Sometimes when you load a timing file into Cortex, it will not compile properly and will produce error messages. The Cortex compiler gives very cryptic error messages, but usually the line numbers will give you a hint as to where to look in your file. For example, you may get error messages that look like this:
PREPPY [encodes.h(107)][warn1]redefining macro "NONDISPLAYABLE ENCODES.
YACC[memory.1(6)][ERR1]@"appear":parse error
The number in parentheses on the YACC line, i.e. (6), points to the line in you timing file that is having a problem. In this case, when I looked in the file, I saw that the word "appear" started on the line without comment (//) symbols. If you cannot see anything wrong with the line specified in parentheses, look at the line above it. If you can not find the error, try compiling your program with a standard C compiler. Of course, a C compiler will generate linker errors since it will not be able to find the Cortex functions, but it should also find syntax errors.
Do not worry about the PREPPY encodes.h(107) error message. It should go away when the errors in your timing file are fixed.
10.6 Spikes are not appearing in the histograms
First, you must determine if you just do not see them on the screen, or that they are not in the data file. Check the data file with one of your Cortex data analysis programs or Cortex Windows Workbench to see if any spikes are being recorded.
If the spikes are in the data file, but are just not showing up on the screen, then it could be the ordering of the function calls in the timing file. That is, one of the response_???() functions and end_trial() must be called *before* update_histogram(); otherwise, the histogram will not be updated properly. (Also, make sure that the function collect_data(ON) is being called to initiate spike collection!)
Another thing to check is whether or not the trials have been labelled as "errors" by the response_???() functions. By default, trials which are "error trials" do not have their spikes accumulated during end_trial(). You can override this default behavior, and can actually have these spikes included in the histogram. There is an option in the Run:Parameters:General menu which is called "Include error trials in histograms". If you set this parameter to "Yes", then the error trials will be accumulated in the histograms, too.
If there are no spikes in the data file, there are a few hardware things to check. First, the spike inputs should be low-going-high. Second, make sure that the spike latch circuitry is really correct. There are some circuit diagrams up on the Cortex web site. Third, make sure that the ribbon cable is attached to the correct data acquisition board connector. (The CIO-DAS16 board is confusing, because there is also a connector on the "face" of the board, besides the one that is at the back of the computer.)
Finally, check the Cortex.cfg file, to make sure that it is set up properly for the data acquisition board that you are using. That is, you must have the correct parameters for the DEVICE, THREAD, and MULTI_SPIKE lines of the Cortex.cfg.
10.7 Colors do not look correct for BMP files
If you want to change the LUT for an image, it is almost mandatory to use CTX files. The other types of images (i.e., .BMP, .JPG, and .PCX) keep their LUT internal to the image file. For non-.CTX file cases, you would need to know the internal structure of the image file and where the individual pixels were located. Even then, it may not work to change the Cortex LUT, and expect the bitmap color to change.
In the DirectX receive program, .bmp files in 8 bpp will
use the Cortex LUT. (For example, if the LUT is not in the conditions file,
then the image will be displayed in black and white.) It is therefore recommended
to create a default LUT which contains the Windows system palette, for
use in 8 bpp. At greater than 8 bpp, the images will look fine, and will
not need/use the Cortex LUT. There is a utility program, bmp2lut.exe, which
extracts the LUT from a .bmp file. It is available "as-is" from the Cortex
ftp site.
10.8 Display of movies is slower than the refresh rate of the monitor/graphics card
The rate at which movies can be displayed depends upon many things. That is, it depends on the refresh rate of the monitor, the refresh rate capabilities of the graphics card, the speed of the CPU, and the size and complexity of the image that you are trying to display. The refresh rate is the number of times per second that the monitor refreshes the screen. However, if the graphics card is not able to process the image within one refresh of the monitor, the image will not be able to be redrawn at the refresh rate of the monitor.
Neither the Scitech receive program nor the DirectX receive program is able to dynamically set the refresh rate for all graphics cards. Therefore, it is usually necessary for you to manually set the refresh rate inside Windows, and within the Scitech Control Panel (if you are using Scitech). Once the refresh rate is set, you must also specify the refresh rate in the GRAPHICS_SPECS line of the Cortex.cfg file on the send computer.
If you are not achieving the speed that is necessary, you will have to either change your hardware or your movies. That is, you will need to get a faster graphics card, monitor, or computer. Or, you will need to alter your movies so that they are smaller in size and use 8 bit-per-pixel color depth.
Once the hardware is set up properly, there are two places in Cortex where the gain of the analog data channels can be set. The first place is in the A2D_GAIN line in the Cortex.cfg. The A2D_GAIN is used to directly program register BASEADDR+11 (see the manual that was shipped with your data acquisition board) to set the gain control. For example, with the CIO-DAS1602/12, if the A2D_GAIN is set to 1, the board should be able to handle +/- 5V.
The second place that can control the gain is in the Options->General Parameters->A2D menu of Cortex. The "EOG gain" field is used in the Cortex code as a multiplier to the EOG values that are read from the board. After the EOG value is read from the board, it is altered by the values for the offset and gain that you set in Options->General Parameters->A2D as follows:
EOGnew_x = (EOG_ENTRY) ((raw_eog -params.eog_xoffset) * params.eog_gain);
There is a similar calculation for EOGnew_y.
The EOG gain from the Options->General Parameters->A2D
menu is NOT applied to the EPP values (just the EOG values). On the other
hand, the A2D_GAIN value is used for all the analog channels, including
the EPP.
#define SPIKE1 1 // optional comments
Two other #defines are reserved, each of which can be used multiple times:
#define DISPLAYABLE_ENCODES
#define NONDISPLAYABLE_ENCODES
Values that have #define lines after the "#define DISPLAYABLE_ENCODES" line will be visible from the View->Results of most recent trial->Codes window, whereas values after "#define NONDISPLAYABLE_ENCODES" will not. This way, one can specify high spike values (like #define SPIKE3 1000), or other user-defined values, and choose whether or not to have them clutter up the Codes window.
10.13 "ERROR: CODE_ISI buffer overflowed x times (data was lost)" in the error file
The CODE_ISI buffer holds both the spikes, and the values generated by calling the encode() function in the timing file. The error message means that more spikes or encodes are being generated than the Cortex output data file has been configured to hold.
The sizes of the CODE_ISI, EPP, and EOG buffers are specified in the DATA_STRUCTS line of the Cortex.cfg file. There are some comments in the cortex.cfg file:
// DATA_STRUCTS <#CODE_ISI_els> <#EPP_els> <#EOG_els> [all as max per trial]
// <#CODE_ISIels>: The max number of encode (CODE and timestamp) elements
// which can be stored per trial.
In the Cortex.cfg file that is shipped with Cortex, the <CODE_ISI_els> is about 4000. In other words, it can only store a total of 4000 spikes and encodes. If Cortex is producing an error that the buffer overflowed, you are going to need to increase the buffer size in the Cortex.cfg file by at least the amount that it reportedly overflowed. The CODE_ISI_els value can be set to about 25000. However, since the buffers are created in a shared memory between the device driver and the application, Cortex will not be able to start up if the buffer sizes are too large.
In any case, before the increasing the size of the buffer, you should look at the Cortex output data file, to determine if it is encodes or spikes that are filling up the buffer. Maybe, in the timing file, there is an encode() statement inside a loop and it is writing out thousands of values into the buffer.
Otherwise, if the buffer is not being filled with encodes, then it is being filled with spikes. If you know that there should not be that many spikes coming into Cortex, then it is most likely a hardware problem. For example, if the spike inputs are not being latched properly, or are not being reset each millisecond, then you will get a huge amount of false spike data. Check that all the spike input wires, the reset, and ground are all wired properly. In particular, make sure that all the lines that are specified in the MULTI_SPIKE line of the Cortex.cfg file are actually wired to a spike source.
The user can create several blocks of conditions, essentially a block of blocks. The default criteria for finishing a block, is that the specified total number of conditions has run. The criterion for finishing the block of blocks is that the desired number of blocks has completed. Additionally, one can set a repeat counter to repeat the entire block of blocks again.
The menus let the user have fine control over the randomization of the conditions and/or blocks. For example, the user can guarantee that the trials are randomly run 10 times, but that the same condition is never repeated more than twice in a row. Similarly, the settings can make it possible for there to be up to N repeats of the same condition in a row. Of course, it is also possible to run the conditions/blocks incrementally.
More complex completion criteria for the individual blocks can also be easily specified. For example, it is possible to run a block until the overall percent correct of its conditions exceeds some threshold. Or, one might only want to look at the most recent 20 (or so) trials and define completion as success on 18 of them.
CORTEX also gives flexibility in the handling of error conditions. Parameters can be set to guarantee that a certain number of correct trials of each condition are run, so the error conditions would have to be repeated. Choices include ignoring error conditions, repeating them immediately, or repeating them later. If a block is considered done based on recent performance or percent correct, then a delayed repeat would effectively increase the likelihood that that condition is selected from the remaining group.
Additionally, it is possible to abort the block if the subject's performance deteriorates too much. One can specify that the block is an error if there are too many error trials (an absolute number), if the percent correct drifts too low, or if the number of recent correct trials drifts too low. The user can opt to repeat a block if it is an error, or just skip on to the next one.
Finally, the user has access to some of the internally stored blocking parameters and functions, which are necessary when designing a Manual staircase design.
A.2 Options->Block/Repeat Menu
Please refer to "Section 5.4 The Options Menu Dialog Boxes", for a description of the blocking parameters.
A.3 Functions available for MANUAL operation
The file Runtrial.c contains code which loops on the variable BLOCKglobal.repeat_counter. There is an infinite while loop which calls BLOCKnext_cond(). When BLOCKglobal.command == BLOCK_DONE, all of the blocks are done, so the while loop as broken, and the repeat_counter is incremented. If an internal error occurs, BLOCKnext_cond() will return 0, and "Invalid cond" will be printed.
BLOCKnext_cond() calls BLOCKwhich_block(), which initializes the Master Block if necessary, and returns the current block number. It also checks to see whether correct/error conditions have been met for the Master Block, in which case it returns BLOCK_DONE. BLOCKnext_cond() checks the results of the last condition. (If it was an error, special processing may be necessary.) It checks to see if Max_errors or Max_retries were met (failure conditions). It checks to see if any of the correct trial conditions were met (but failure takes precedence). If a block was completed (correct or failure), it calls itself recursively to pick the next block/condition. Otherwise, it tries to choose the next condition. If there are no more slots available (i.e. maxTrials exceeded), the block is first reset. Once this is controlled for, the next condition (whether incrementally or randomly selected) is picked.
Therefore, the loop breaks when BLOCKnext_cond() is called only to discover that NEXT_BLOCK (i.e. a block is done), or BLOCK_DONE (i.e. for MasterBlock) conditions are met. Thus, if reset_block_circ_buf is set to at_Start or Manual, any repeat attempts to run an already completed block will result in an instant NEXT_BLOCK result, so the block will not be inadvertently repeated.
// *************************** CORTEX.CFG ************************
// The Windows version of Cortex (VCortex, version 1.0, Aug. 2002),
// uses the cortex.cfg file to configure the system. It has the
// same categories as the DOS version of Cortex. However, many of
// the settings are different in the Windows version, because of
// differences in the user screen layout, etc. Therefore, it is
// NOT recommended to simply use your cortex.cfg file from the DOS
// version. Instead, you should perform a line by line compare with
// this sample file. (Look for comments labelled with the string
// "*WINDOWS*".) TMN 08/2002
//
// This file gives an adequate setup
// N.B. There are many entries which might appear confusing. In general,
// there are defaults for just about everything, so an empty cortex.cfg file
// will still allow CORTEX to run, but in a very pared down way.
// Note that most key words (esp. the first one on a line) are not case
// sensitive.
// For those who wonder why so many defaults are specified here: CORTEX
// is getting so large that its default configuration doesn't run on some
// systems with limited memory. Therefore, the cortex.cfg file lets you
// remove features you don't use, thus freeing needed memory. This is
// especially true of the DATA_STRUCTS line
// TEXT_COLORS: <normal> <bold> <highlighted> <blinking>
// the numbers below specify adequate defaults for Hercules or VGA
// They are not used by the *WINDOWS* version of Cortex.
TEXT_COLORS 0x07 0x0f 0x70 0x87 25
// MONITOR_TYPE: <monitor_type> <font_path> <font_choice>
// monitor_type: MUST BE "VC" for the *WINDOWS* version of Cortex
// font_path: not used by the *WINDOWS* version
// font_choice: not used by the *WINDOWS* version
// Note: The font_path and font_choice parameters are just legacy
// variables from the DOS version. They must remain here for now
// for the *WINDOWS* version, even though they are not used.
MONITOR_TYPE VC helvb.fon "t'helv'h9w5b"
// GRAPHICS_SPECS: <Xdim> <Ydim> <frames_per_sec> <pixels_per_dva>
// <bits_per_pixel> <re-init_on_depth_conflict> [<background_constant>]
// Xdim & Ydim: pixel dimensions of subject's screen
// frames_per_sec: refresh rate of subject's screen
// pixels_per_dva: number of pixels per subject's degree of visual angle
// bits_per_pixel: for subject: e.g. 1,2,4,8,16,24,32
// re-init_on_depth_conflict: allows reset when a new bitmap's depth
// differs from that to which the subject's screen was initialized.
// I don't think that anyone uses this feature.
// background_constant: an optional parameter to allow the user to
// specify whether or not they want the background color to remain constant
// throughout the execution of Cortex. If they omit the parameter, the
// screen will go black at the end of the trials, instead of keeping the
// same color as during the trial. The choices are: CONSTANT or BLACK.
//
//GRAPHICS_SPECS 640 480 72 34.5 34.5 8 NEVER
//GRAPHICS_SPECS 640 480 60 35 35 8 NEVER CONSTANT
GRAPHICS_SPECS 640 480 60 35 35 8 NEVER
// SOUND: <speaker_config> <speaker_geom>
// speaker_config: type of speakers that will be used
// HEADPHONE, MONO, QUAD, STEREO, SURROUND, or DEFAULT (stereo)
// speaker_geom: used to specify the angle of the two stereo
// speakers from each other. Valid values are:
// MIN = 5 degrees
// NARROW = 10 degrees
// WIDE = 20 degrees (default)
// MAX = 180 degrees
// DEFAULT (wide)
// The geometry values are only used if the speaker configuration
// is STEREO. (Since two parameters are required on the SOUND line,
// just put DEFAULT as the speaker_geom parameter when using
// configuration settings other than STEREO.)
//
// Sound is only available in the two computer 32-bit version of Cortex.
// Additionally, the SOUND configuration values are only used by
// the DirectX version of receive, and are ignored by the DOS version.
//
SOUND STEREO WIDE
// PLAY <#play_items> <float max_x> <float max_y> (in dva)
// This line is NOT necessary for most people. In NNIOS, the PLAY item has
// a completely separate bitmap, so you must define ahead of time how large
// it can be. In TIGA, this isn't as necessary.
PLAY 1 7.5 7.5
// THREAD_MANAGER <max_#interrupts> <max_#threads>
// This is only needed by people adding many CSS threads or writing their
// own interrupt and thread routines. The defaults (5,10), are about three
// times as many as are normally used, so the defaults should suffice for
// everyone for quite a while. CORTEX will warn you if there aren't enough.
//THREAD_MANAGER 7 10
//** USER SCREEN MAPPING **
// The User Screen Mapping settings are different in the *WINDOWS*
// verion of Cortex. In the DOS version of Cortex, the entire user
// screen was mapped as a single "window":
// The lower left hand coordinate of the screen is (0,0), and the upper
// right hand corner is (10000,10000) in this mapping. These integer values
// will be mapped to the actual size of the user screen. For example, VGA
// uses 640x480, but Hercules uses 720x348. By using 0->10000 instead of
// pixel coordinates, one cortex.cfg file can be used for all monitor
// configurations. Lower Left is abbreviated <ll>, and Upper Right is <ur>.
//
// In the *WINDOWS* version of Cortex, on the other hand, each area
// of the screen is mapped as a separate window. In other words,
// there is a status window, an EOG window, and a window for each
// histogram. For each of these windows, the lower left corner
// is (0,0). In the settings below, I chose numbers that made the
// drawing in each window look good. If the windows do not look
// good on your screen, you might want to adjust these values.
// HISTOGRAM <htg#> <ll.x> <ll.y> <ur.x> <ur.y>
// There can be up to <#spike_channels> histograms shown on the screen. Each
// Histogram automatically includes areas for this histogram, raster_table,
// and raster line. The raster line dynamically shows the spike inputs. The
// raster_table shows the past history of spike inputs. As usual, the
// <ll.x,y> and <ur.x,y> are in User Screen Mapping coordinates
// Remember that the lower left hand corner is (0,0)
// The values below should look good for the *WINDOWS* version of Cortex.
Histogram 1 0 0 3000 2500
Histogram 2 0 0 3000 2500
//Histogram 3 0 0 3000 2500
//Histogram 4 0 0 3000 2500
// STATUS_RECT <ll.x> <ll.y> <ur.x> <ur.y> <#columns>
// Status_rect defines the region of the user screen in which messages are
// printed from the GMENU system (graphical menu). Cortex automatically
// formats all of the GMENU entries in the order requested so that they look
// pretty. The only thing Cortex needs to know is how many columns you want.
// The number of entries does not have to be an even divisor of #columns: so
// if you have 10 entries and specify 3 columns, they will be 4:4:2
// Using the settings of 0 0 7000 2700 2 look the best to me for the
// *WINDOWS* version.
STATUS_RECT 0 0 7000 2500 2
// GMENU GETS<something> <label_string> <value_length>
// GMENU allows you to pick and choose not only what is shown on the user
// screen, but also determine where it will be shown, and how much space it
// will have to show its message. All of the available functions are shown
// here, although some of them are commented out. Since three columns have
// been specified from STATUS_RECT, the GMENU entries have been divided into
// three groups for visual convenience. This also makes it easier to
// ensure that they are lined up nicely. For example, in the first block,
// "GetData" is the longest entry, so an extra space or two are added to the
// others so that the values returned by those functions all start aligned.
// On the other hand, the GETSmessage? entries do not specify a label string
// so that they can use the entire space for their messages.
// The values below should look good for the *WINDOWS* version of Cortex.
GMENU GETScycle_num "cycle# " 4
GMENU GETSblock_num "block# " 4
GMENU GETScond_num "cond# " 4
GMENU GETStrial_num "trial# " 4
GMENU GETShtg_scale "scale " 4
GMENU GETSbin_width "bwidth " 4
GMENU GETScollect_data "GetData" 4
GMENU GETSsaccade "saccade" 10
//GMENU GETSdynamic_fixwin_size "fixwin " 10
GMENU GETSwindowX "fixwinX" 10
GMENU GETSwindowY "fixwinY" 10
GMENU GETScond_pct_correct "Cpct" 15
GMENU GETScond_circ_buf "Cbuf" 15
GMENU GETSblock_pct_correct "Bpct" 15
GMENU GETSblock_circ_buf "Bbuf" 15
GMENU GETSmessage1 "" 50
GMENU GETSmessage2 "" 50
GMENU GETSmessage3 "" 50
GMENU GETSmessage4 "" 50
GMENU GETSmessage5 "" 50
GMENU GETSfile_name "file " 25
GMENU GETStrial_status "status" 25
//GMENU GETSnothing "" 1
// EOG_MAPPING <minV> <maxV> <ManualDVA?> <.5 Xdva> <.5 Ydva>
// <ll.x> <ll.y> <ur.x> <ur.y> <#eyewins>
// minV and maxV: the minimum and maximum values returned by the a2d board.
// for most people, a 12 bit analog2digital converter is used, so the
// values range from 0->4096. For right now, CORTEX converts these to
// -2048->+2048, but that is not crucial. The minV and maxV are not fully
// implemented pending a decision on how to deal with this issue, so leave
// them alone.
// ManualDVA?: {0,1,2}
// (0) minV/maxV will map to the screen size, as determined from
// <Xdim> <Ydim> and <pixels_per_dva>. Adjust your gains accordingly.
// (1) <Xdva> and <Ydva> (twice values entered) will map to minV/maxV.
// The screen size is read, and pixels_per_dva remains correct. The
// eog_window on the user's screen reflects the size of Xdva and Ydva,
// not the screen size.
// (2) minV/maxV will map to width of the screen size. Exactly like option
// 0, except maps to (x,x) instead of (x,y). Means gains equal?
// <ll.xy><ur.xy>: Defines the location of the eog_window on the user screen
// in User Screen Coordinates.
// <#eyewins>: CORTEX keeps track of the location of every object drawn to
// the screen. There are up to 10 test_screens per condition (TEST0->
// TEST9), each test_screen can have up to 16 objects, and each test_screen
// can be moved around on the screen by SWEEPwin() or other commands.
// CORTEX keeps track of all of the objects' positions dynamically so that
// you can ask ITEM_POSeye_is_here() or other commands to determine whether
// the subject is looking at a particular object. In addition, the user
// may want to keep track of positions on the screen at which there are
// no objects present, such as the positions of objects from the previous
// condition. In order to do this, you need to be able to store and
// access/query other item positions. This is what the eye_wins are for.
// Before you run CORTEX, you must guess how many you will need (default is
// 15). Once in CORTEX, you can set these values manually or using CSS.
// The values below should look good for the *WINDOWS* version of Cortex.
EOG_MAPPING -2048 2048 0 10 10 0 0 5500 4000 10
// EOG_STYLE is new; it's an integer 0-2:
// 0 is regular NIH style for EOG (it's the default)
// 1 is like NIH, but dots are not erased automatically, you must
// use the new clear_eog() function in your CSS file to clear
// things at the start of each trial.
// 2 is lines connecting the points, also requires CSS file to
// call clear_eog() periodically..
// -- JAM 30-Apr-96
EOG_STYLE 0
// DEVICE <char *device> <int addr> [<int reg>]
// device: string of METRABYTE, PIO24, COMPUBOARD, PIO96, NO_DEVICE,
// RANDOM_SPIKE_DEVICE, DASH16
// addr: The base port for the board. Examples are listed below
// reg: Ignored
// CORTEX now uses threads in its interrupt routines in an effort to make
// it easier to add new data aquisition boards and/or interface with other
// devices. Use the DEVICE line to declare which boards you have in your
// system and want to use. If you do not declare a DEVICE, you can not
// use it in a THREAD statement.
// The value returned from DEVICE (base 0) is the value needed if you want
// to use the DEVinp() and DEVoutp() functions from CSS.
// Of couse, you can also just call outp() and inp() directly if you know
// the addresses.
// IMPORTANT for the *WINDOWS* version of Cortex:
// The DEVICE line determines which low level device driver to load
// when running the *WINDOWS* version of Cortex. The DEVICE line
// must accurately match the data acquisition board(s) that you have
// in your computer. If you do not have any boards, you can set the
// DEVICE line to RANDOM_SPIKE_DEVICE, as I have shown below.
// Please note that you must still alter your system.ini file to
// tell Cortex where it can find the device driver files. There is
// more information concerning this issue in the VCortex User's Manual.
DEVICE random_spike_device 0
//DEVICE COMPUBOARD 0x300
//DEVICE DASH16 0x300
//DEVICE METRABYTE 0x300
//DEVICE PIO24 0x320
//DEVICE PIO96 0x310
//DEVICE no_device 0
// THREAD <char *device> <char *thread> <int ms_per_tik>
// <char *device>: same as above {METRABYTE, COMPUBOARD, ...}
// <int ms_per_tik>: How many milliseconds between running of thread.
// <char *thread>: all of the allowed <thread> names are used below
// defaults: Should be run at 1000Hz (ms_per_tik = 1).
// This special function/interrupt does everything that
// is done by read_lines, SPIKEstoreAll, read_eog and EOGstore, all
// in one function, thus being faster because of decreased overhead.
// It is recommended that users use this function instead of the
// other four unless there is some pressing need to do otherwise.
// If the bar_state and reward threads are not specifically specified,
// then CORTEX will use the same board for these as for the default
// threads. bar_state and reward will individually override this
// default. However, if defaults and any of the other threads are
// both specified, both will be run.
//
// ** Less commonly used functions **
// bar_state: not a thread (so ms_per_tik = 0). Tell CORTEX which board
// to use to read the bar_state from get_bar_state() in CSS
// reward: not a thread (so ms_per_tik = 0). Tell CORTEX which "board" to
// issue the reward() from CSS
// read_lines: Should be run at 1000Hz (ms_per_tik = 1). Reads the spike
// data from the specified board into the int DevControl.inputLines
// read_eog: Should be run at 1000Hz (ms_per_tik = 1). Reads the eye
// position using the specified board.
// SPIKEstoreALL: Should be run at 1000Hz, and MUST follow read_lines.
// Assumes that DevControl.inputLines has been updated. Checks the
// first two bits (spike channels) and stores spike codes if occured.
//
// ** Threads whose rates are controlled from CORTEX menus, not here **
// RASTERupdate: is a thread, whose rate is determined by the bin size
// of the on-line histograms. CORTEX uses the value passed to
// start_trial() to initialize the RASTERupdate() thread. However,
// you can tell CORTEX not to run that thread by specifying a negative
// number for the bin size. The histograms will still be computed
// and stored correctly, but the raster line will not be drawn.
// EOGupdate: specifies the rate at which the eyespot on the user screen
// is refreshed. A good rate is 15Hz (every 66ms). If done too fast,
// you can't see it. It is set from the Run:Params:General menu, and
// the default is 66ms.
// EOGstore: is an interrupt whose rate is set in the Run:Params:General
// menu, not here (the value you give it is ignored). The initial
// value is 0, so if you want to store eog data, you must set it to
// a positive number, as well as call put_eye_data_in_buf() from CSS.
//
// You need to specify which threads will be run from the interrupt,
// and at what rate they should be run. Right now, the user has more
// control than s/he should, so the choices may be restricted in the near
// future. If you wonder why non-threads are specified, it is because
// different boards might be used to do that operation.
THREAD RANDOM_SPIKE_DEVICE defaults 1
//THREAD COMPUBOARD defaults 1
//THREAD DASH16 defaults 1
//THREAD METRABYTE bar_state 0
//THREAD METRABYTE reward 0
//THREAD RANDOM_SPIKE_DEVICE read_lines 1
//THREAD RANDOM_SPIKE_DEVICE SPIKEstoreAll 1
//THREAD METRABYTE read_eog 1
//THREAD DASH16 chain_INT08 18
// DATA_STRUCTS <#CODE_ISI_els> <#EPP_els> <#EOG_els> [all as max per trial]
// <#CODE_ISIels>: The max number of encode (CODE and timestamp) elements
// which can be stored per trial.
// <#EPPels>: The max number of EPP (can really be anything: sizeof(char))
// which can be stored per trial.
// <#EOGels>: The max number of eye positions which can be stored
// per trial
// The defaults for all of these used to be 4000:0:2000, and are the defaults
// here as well. However, if you know that you will never use EPPbuf, then
// why bother allocating space you don't need. OR, if you want to store
// more extended EOG tracings, you might need more room.
// In the *WINDOWS* version of Cortex, there is a limit on the size of the
// data that can be stored. This is because the memory is shared between
// the VCortex application and the device driver. Refer to the VCortex
// User's Manual for information.
DATA_STRUCTS 15000 15000 15000
// A2D_CHANNELS is normally 2. If you need to cycle between 4 A2D channels,
// storing the data from channels 1 and 2 into the EPP buffer, and channels
// 3 and 4 into the EOG buffer, than set A2D_CHANNELS to 4
//A2D_CHANNELS 4
// A2D_GAIN is specific for the METRABYTE/COMPUBOARD a/d device. These
// boards have a variable gain stage that can be set under software
// control to 4 possible values (the exact gains depend on the particular
// model of the board -- see your manual for details). The config
// option should be set to -1, 0, 1, 2 or 3. -1 indicates use the
// hardware default.
// -- JAM 24-Apr-96
A2D_GAIN 1
// TOUCH_SCREEN <int ms_per_tik>
// To use a touch screen, uncomment this TOUCH_SCREEN line below
// To emulate the touch screen using the mouse, use a negative number for
// the ms_per_tik value.
// 05/20/98 TMN uncommented TOUCH_SCREEN line so I could test TOUCH1 demo
// with mouse emulation.
//TOUCH_SCREEN -50
// LUT <int num_palettes>
// This command doubles for the LUT:Number menu within CORTEX, allowing one
// to specify the number of palettes to create when launching CORTEX
LUT 0
COM_PORT 1 115200
//COM_PORT 1 19200
///////////////////////////////////////////////////////////////////////////
// MULTI_SPIKE <char *device> <port_offset> <#spikes> <starting_encode_val>
// [<starting_bit>]
///////////////////////////////////////////////////////////////////////////
// This syntax will hopefully replace the SPIKE_CHANNELS and much of the
// THREADS defaults stuff. For the sake of backwards compatibility,
// the other syntaxes will remain, although they will call these functions
// internally. However, if MULTI_SPIKE is specified at all, it will
// supercede anything entered for SPIKE_CHANNELS or THREAD defaults.
//
// CORTEX will ensure that invalid ports are not specified for known devices,
// but will not check for overlap of spike values, or multiple reads from
// a given device's port.
// TMW 10/21/96
//
// Please refer to the documentation that was shipped with the data
// acquisition board when specifying the base address and port offset.
// For example, the port offsets for the Compuboard CIO-AD16 are:
// BASE+0x10(A), BASE+0x11(B), and BASE+0x12(C). The port offsets for
// the Compuboard CIO-DAS1600 series boards are: BASE+0x400(A),
// BASE+0x401(B), and BASE+0x402(C).
// TMN 02/11/99
//
// The optional parameter <starting_bit> gives the user more flexibility in
// specifying which bits correspond to which spikes and encode values. For
// example, if one wants to use the DASH16 to collect 4 spike channels, using
// the predefined spike encodes, one might use the following commands, where
// SPIKE1 = 1, and SPIKE3 = 102:
// MULTI_SPIKE DASH16 0x03 2 SPIKE1 0
// MULTI_SPIKE DASH16 0x03 2 SPIKE3 2
// TMW 11/10/96
///////////////////////////////////////////////////////////////////////////
MULTI_SPIKE RANDOM_SPIKE_DEVICE 0x03 2 1
//MULTI_SPIKE COMPUBOARD 0x03 2 1 // default for DASH16
//MULTI_SPIKE COMPUBOARD 0x03 2 102 2 // spikes 3&4 from DASH16
//MULTI_SPIKE COMPUBOARD 0x10 8 104 // 8 spikes from PIO24 port A
//MULTI_SPIKE COMPUBOARD 0x12 4 112 // 4 spikes from PIO24 port C
//MULTI_SPIKE DASH16 0x03 2 1 // default for DASH16
//MULTI_SPIKE DASH16 0x03 2 102 2 // spikes 3&4 from DASH16
//MULTI_SPIKE PIO24 0x02 4 102 // 4 spikes from PIO24 port C
//MULTI_SPIKE PIO24 0x00 8 1004
// 8 spikes from PIO24 port A
// SPIKE_CHANNELS <#spike_channels>
// Obsolete: If SPIKE_CHANNELS is used, it will map to
// MULTI_SPIKE DASH16 0x03 <#spike_channels> 1
// TMW: 10/21/96
//SPIKE_CHANNELS 2
long get_TIMERms_counter(void);
gets the current TIMERms_counter value, in milliseconds
void set_TIMERms_counter(long value);
sets the current TIMERms_counter value, in milliseconds
long get_TIMER100us_counter(void);
gets the current TIMER100us_counter value
void set_TIMER100us_counter(long value);
sets the current TIMER100us_counter value
int get_EOGdynamic_fixwin_size(void)
gets the current pDevControl->params.dynamic_eyewin_size
void set_EOGdynamic_fixwin_size(int size);
sets pDevControl->params.dynamic_eyewin_size = size;
float get_EOGfixwin_size_x(void)
gets pDevControl->params.window_x
void set_EOGfixwin_size_x(float size)
sets pDevControl->params.window_x = size
float get_EOGfixwin_size_y(void)
gets pDevControl->params.window_y
void set_EOGfixwin_size_y(float size)
sets pDevControl->params.window_y = size
float get_EOGsaccade(void)
gets pDevControl->params.mc
void set_EOGsaccade(float value)
sets pDevControl->params.mc = value
int get_keep_current_conds(void)
gets pDevControl->params.keep_current_conds
void set_keep_current_conds(int value)
sets pDevControl->params.keep_current_conds = value
int get_EOGnew_x(void)
gets pDevControl->EOGnew_x
void set_EOGnew_x(int value)
sets pDevControl->EOGnew_x = value
int get_EOGnew_y(void)
gets pDevControl->EOGnew_y
void set_EOGnew_y(int value)
sets pDevControl->EOGnew_y = value
int get_EOGoffset_x(void)
gets pDevControl->params.eog_xoffset
void set_EOGoffset_x(int value)
sets pDevControl->params.eog_xoffset = value
int get_EOGoffset_y(void)
gets pDevControl->params.eog_yoffset
void set_EOGoffset_y(int value)
sets pDevControl->params.eog_yoffset = value
int get_EOGgain(void)
gets pDevControl->params.eog_gain
void set_EOGgain(int value)
sets pDevControl->params.eog_gain = value
int get_EPPnew_x(void)
gets pDevControl->EPPnew_x
void set_EPPnew_x(int value)
sets pDevControl->EPPnew_x = value
int get_EPPnew_y(void)
gets pDevControl->EPPnew_y
void set_EPPnew_y(int value)
sets pDevControl->EPPnew_y = value
int get_CODEbuf(int index)
gets pDevControl->CODEbuf[index]
void set_CODEbuf(int index, int value)
sets pDevControl->CODEbuf[index] = value
long get_ISIbuf(int index)
gets pDevControl->ISIbuf[index]
void set_ISIbuf(int index, long value)
sets pDevControl->ISIbuf[index] = value
int get_CODE_ISIsize(void)
gets pDevControl->CODE_ISIsize
void set_CODE_ISIsize(int value)
sets pDevControl->CODE_ISIsize = value
int get_CODE_ISImax(void)
gets pDevControl->CODE_ISImax
void set_CODE_ISImax(int value)
sets pDevControl->CODE_ISImax = value
int get_CODE_ISIoverflow(void)
gets pDevControl->CODE_ISIoverflow
void set_CODE_ISIoverflow(int value)
sets pDevControl->CODE_ISIoverflow = value
int get_EOGbuf(int index)
gets pDevControl->EOGbuf[index]
void set_EOGbuf(int index, int value)
sets pDevControl->EOGbuf[index] = value
int get_EOGsize(void)
gets pDevControl->EOGsize
void set_EOGsize(int value)
sets pDevControl->EOGsize = value
int get_EOGmax(void)
gets pDevControl->EOGmax
void set_EOGmax(int value)
sets pDevControl->EOGmax = value
int get_EOGoverflow(void)
gets pDevControl->EOGoverflow
void set_EOGoverflow(int value)
sets pDevControl->EOGoverflow = value
int get_EPPbuf(int index)
gets pDevControl->EPPbuf[index]
void set_EPPbuf(int index, int value)
sets pDevControl->EPPbuf[index] = value
int get_EPPsize(void)
gets pDevControl->EPPsize
void set_EPPsize(int value)
sets pDevControl->EPPsize = value
int get_EPPmax(void)
gets pDevControl->EPPmax
void set_EPPmax(int value)
sets pDevControl->EPPmax = value
int get_EPPoverflow(void)
gets pDevControl->EPPoverflow
void set_EPPoverflow(int value)
set pDevControl->EPPoverflow = value
Some portions of Cortex (and associated utility programs, including Procortex, STATS100, and GRAST) are copyrighted (see History of Cortex section for a list of its authors). The program is "freeware". That is, the program and its source code are provided free of charge and may be copied freely, provided that this notice is attached. However, its use is subject to certain restrictions, and, thus, it is not strictly speaking in the public domain. The primary restriction is that you must not sell Cortex or its utility programs or incorporate it into any program that is sold. Furthermore, the Cortex program itself includes code from the Bison compiler generator, which is copyrighted by the Free Software Foundation (FSF). The FSF requires as part of the license for Bison that no program incorporating Bison code be sold. The Bison license is included in the source distribution for Cortex, along with complete information on obtaining the source code for Bison.
The source code for Cortex is provided freely, and we
encourage users to modify and add to it. Depending on the version of the
code you receive, one or two object modules required for linking the source
code may be commercial products. If you plan to work with the source code,
you should purchase any necessary commercial products directly from the
appropriate vendor. Hopefully, all commercial object modules will have
been eliminated by the time you receive the code, at least for the Cortex
program itself. If you improve the source code, add to it, or write any
supplemental programs for creating stimuli or analyzing data from Cortex,
we ask to be sent copies. If we distribute your code to new users, you
will be acknowledged. The program is provided "as is", and we accept no
liability whatsoever for damages or loss of any kind caused by its use.
Use of the program implies acceptance of all of these conditions.