document version 1.0

last updated 04 August, 2002
 
 


























VCortex: Cortex for Windows

(beta version 1.0)

User’s Manual
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Laboratory of Neuropsychology, NIMH



 
 
 
 

TABLE OF CONTENTS
TABLE OF CONTENTS *

1. Introduction *

1.1. Cortex: A Program for COmputerized Real Time EXperiments. *

1.2 Getting the latest version of Cortex *

1.3 Technical Support *

1.4. History (you may skip this part) *

2. Hardware and Software Requirements * 2.1 Two-computer Cortex (\VCWin32\VCSend.exe) *

2.2 Single-computer Cortex without graphics (\VCWin32\VCSingle.EXE) *

3. Installation * 3.1 Data Acquisition Board Setup *

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. Using Cortex * 4.1. Setting up the experimental conditions. *

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. Running VCortex * 5.1 The Main Menu Structure *

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. Limitations of Cortex due to structure and hardware * 6.1. Data storage *

6.2. Data file format *

6.3. Interrupt structure *

7. Image File Formats and Color Lookup Tables * 7.1. Image File Formats *

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. Source Code * 8.1. Distribution *

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 *

9. Data File Structure * 9.1. Sample data file * 10. Troubleshooting * 10.1 Send/Receive computers cannot communicate: Debugging the serial connection *

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 *

Appendix A. Technical Notes on Blocking * A.1 Overview of the built-in capabilities for general staircasing designs *

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 B. Known Bugs, Limitations, and Differences from DOS Cortex *

Appendix C: Sample Cortex.cfg file *

Appendix D: New Timing File Functions in the Windows version of Cortex *

Copyright notice *

1. Introduction
1.1. Cortex: A Program for COmputerized Real Time EXperiments.

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/

1.3 Technical Support

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.

2. Hardware and Software Requirements
2.1 Two-computer Cortex (\VCWin32\VCSend.exe) 2.1.1 Basic "Send" computer The Cortex "send" computer controls experimental timing, data collection, and sending commands to the graphics ("receive") computer. The "send" computer contains the data acquisition card.

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.

2.1.2 Basic "Receive" computer The Cortex "receive" computer displays the graphics to the subject. There are two versions of the "receive" program: a DOS Scitech Display Doctor (SDD) based version and a Windows DirectX based version. With the VCortex release, only the DirectX version of the receive program has been tested and shipped in the zip file. This is not to say that the Scitech version will not operate with VCortex, but it is not the recommended display program, and will not be discussed in the VCortex User's Manual.

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.

2.1.3 Operating Systems Currently, the Windows send program will only run from Windows 95 or Windows 98.

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.

2.1.4 Graphics cards A good graphics card is only required in the receive computer. It must be supported by DirectX for the Windows DirectX version (see section 2.2.10 below)

A graphics card with at least 4 MB of onboard video memory is recommended.

2.1.5 Data acquisition cards The Windows version of Cortex was written specifically on the CIO-DAS1602/12 data acquisition board. It uses the onboard clock of that board to provide the timing. In the case where a CIO-DAS16 type board is not present, VCortex can also reprogram the Windows internal timer (the Windows Virtual Timer Device) to tick at 1 millisecond intervals. This option is useful in cases where the user does not have any data acquisition board, or has only a PIO24 type board.

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".

2.1.6 Sound cards Any sound card which is supported by DirectX can be installed in the receive computer with the DXRecv.exe program. 2.1.7 Touch screens The touch screen code that was written for the DOS version of Cortex, has not been migrated to the Windows version. Therefore, touch screens are not supported in this version of VCortex. 2.1.8 Serial connection The two computers are connected via a serial cable between COM ports. The serial cable connecting the two computers must be a null modem cable. (Laplink-style cables will work.) Black Box Corporation sells a "Universal Serial cable (DB25F/DB9F to DB25F/DB9F)", and its part number is BC01802, which works well with Cortex. 2.1.9 Monitors A good monitor is only required on the receive computer. Remember that the highest refresh rate that can be achieved is dependent on the graphics card and the monitor. Therefore, when selecting a monitor, make sure that the monitor can handle the refresh rate at the desired resolution and color depth. You will also want to buy a video-splitter (such as a VOPEX splitter from NTI) so that the graphical output can be displayed on a monitor for the subject and a monitor in your setup. 2.1.10 Software In order to use the DirectX receive program, the DirectX 6.0 (or higher) driver must be loaded. The DirectX driver is freely available from the Microsoft web site. If you are interesting in running AVI, MPEG, or QuickTime movies, you must also have Microsoft Internet Explorer version 4.0 or higher, installed on your computer. 2.1.11 Useful Web Sites for Finding the Necessary Hardware and Software BlackBox Corp. http://www.blackbox.com/

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

NTI http://www.networktechinc.com/
 
 

    1. Single-computer Cortex without graphics (\VCWin32\VCSingle.EXE)

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

The single-computer Cortex computer controls experimental timing, data collection, and can send serial commands to another computer. This computer contains the data acquisition card.

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.

2.2.2 Data acquisition cards All of the data acquisition boards originally specified for the two computer version of Cortex should also work with the single version of Cortex. See section 2.1.5 above.
.
3. Installation
3.1 Data Acquisition Board Setup

3.1.1 Typical Keithley/Metrabyte DASH-16 settings

  1. Base Address: 0x300 or 0x310
  2. DMA Channel: By default, the board requires DMA channel #1. If something else is using that DMA channel, there is an onboard jumper that can be switched to use DMA channel #3. Otherwise, use the Windows Control Panel to move the conflicting device to a different setting.
3) should be set for bipolar, 16 analog inputs

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

8) solenoid reward output: digital output 1. Cortex outputs a brief TTL pulse to trigger a solenoid control circuit. By default, the duration of the pulse is 20 ms. It can be configured to different times via the Cortex Run:Parameter:General menu options, or using an external variable (ms_reward_duration) in the timing file.

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.1.2 Typical PIO24 or CIO-DIO24 settings The PIO24 board is shipped with a base address of 0x300. The base address must be changed with onboard jumpers, if this address is already occupied. By default, Cortex uses Port A as 8 lines of input, Port B as 8 lines of output, Port C (0-3) as 4 lines of input, and Port C (4-7) as 4 lines of output. This is configured at startup in Cortex, but you can dynamically change this in your timing file to give a different distribution of inputs and outputs. 3.1.3 Typical Computerboard CIO AD-16, CIO-DAS16/F, and CIO-DAS1602/12 settings The Computerboard CIO AD-16, CIO-DAS16/F and CIO-DAS1602/12 can be considered to be a combination of a DASH-16 board and a PIO24 digital I/O board, with the address space of the PIO24 following that of the DASH-16. Because of the PIO24 on board, it is usually necessary to use the Computerboard with a base address of 0x300 for the DASH-16 component rather than 0x310. If the DASH-16 component has an address of 0x300, the PIO24 component can be set with an address of 0x310, which is a safe address. Otherwise, if you set the base address for the DASH-16 component at 0x310, the address space of the PIO24 is automatically set at 0x320, which apparently can conflict with other devices on the bus. Note: The CIO-DAS1602/12 board is shipped with the analog inputs set to UNIPOLAR. Therefore, the switch on the board must be changed to the BIPOLAR setting in order for Cortex to collect analog data properly. 3.2 Graphics Board Setup Install the graphics card according to the graphics card manufacturer's instructions. Install the Microsoft DirectX driver. This driver should recognize the graphics card, if the driver supports it. 3.3 Data Acquisition Interface Setup

3.3.1 Spike Flip Flop Circuitry

The Dash-16 does not latch digital inputs (for purposes of spike acquisition, neither does the PIO24). This seems to be typical for digital inputs boards for the PC, except possibly for a handshaking line. So if you want to collect neuronal spikes, you must add flip-flops between the TTL pulse of your window discriminator (a +5v digital pulse) and the digital input ports of the board. Otherwise, if your TTL pulse is less than 1 msec long, it may be "gone" by the time the Cortex program gets around to examining the port; if longer than 1 msec, Cortex will read more than one spike for each pulse. A circuit diagram for the flip-flops can be obtained from the Cortex web site. The flip-flops are cleared by digital output #0 (courtesy of the software and the flip-flop circuit). The spike inputs go to user inputs 0 and 1. Behavioral inputs go to digital inputs 2 and 3 (bar up/down = 2, bar left = 2, bar right =3), which naturally are not latched. 3.3.2 Thalamus Although Cortex does not require any interface beyond the screw-terminal box or panel sold by Metrabyte or Compuboard (plus a couple of flip-flops for the spikes), Andy Mitz developed a fabulous general-purpose interface called Thalamus. Thalamus is an interface and interconnect box that goes between the computer I/O boards and the outside world. It contains BNC connectors for up to 8 A/D channels and up to 8 spike inputs. It has input latches for all 8 spike inputs. Four of the 8 A/D inputs can have built-in anti-aliasing filters. Thalamus also has "D" type connectors for digital input and output. There are 8 "touch pad" circuits in the Thalamus unit to aid with touch switches or to condition other switches. There is also a one-shot and driver for delivering rewards. Thalamus was developed by the Laboratory of Neurophysiology, NIMH. Drawings for the Thalamus are available on the Cortex web site and at the Laboratory for Neurophysiology's web site.

3.3.3 Screw Terminal Interface Diagram for the DASH-16 type boards

(DASH-16, CIO-DAS16/F, CIO-AD16, and CIO-DAS1602/12)


 
 

3.4 Sound Card Setup

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

  1. Make a backup copy of your c:\windows\system.ini file. Then, edit your c:\windows\system.ini file as follows. In the [386Enh] section, add the line:

  2. device=c:\vcortex\vcwin32\randsd.vxd

    (assuming the zip file was unzipped to the c:\vcortex directory)
     

  3. Make a backup copy of your c:\autoexec.bat file. Then, edit your c:\autoexec.bat file so that it contains the line:

  4. 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.

  5. Reboot your computer.
  6. Check the cortex.cfg file in the \vcortex\vcwin32 directory on your send computer to make sure that it accurately reflects your devices and settings.
  7. The testing files (items, conditions, timing files) must be located on the send computer. (The associated *.lut files must be located in the specified directory on the send computer. If a path to the .lut file is not specified in the conditions file, Cortex will look for the .lut file in the current directory.)
  8. Create shortcuts on your send computer desktop for the VCSend.exe and VCSingle.exe. Double-click on the shortcut to VCSingle.exe or VCSend.exe, depending on which version you would like to run.
3.6.3 Installing VCortex on a computer with a CIO-DAS16 type board
  1. The CIO-DAS16 vxd requires a reserved IRQ for its interrupt handling. Further, it requires that the IRQ is a number between 2 and 7, inclusive. Check your ControlPanel:System:DeviceManager:Computer:Properties to see which IRQ's are currently being used. If all IRQ's between 2 and 7 are being used by other devices, you will need to reconfigure your system so that one of these IRQ numbers are free. It is usually possible to reconfigure a device (such as a sound card), so that its IRQ is moved to a higher value.
  2. Make a backup copy of your c:\windows\system.ini file. Then, edit your c:\windows\system.ini file as follows.
    1. In the [386Enh] section, add the lines:

    2. device=c:\vcortex\vcwin32\randsd.vxd

      device=c:\vcortex\vcwin32\cdas16.vxd

      (assuming that the zip file was unzipped to the c:\vcortex directory)

    3. add the section:
[CORTEX]

CDAS16=5

(assuming that 5 is the free IRQ# in your computer)

  1. Make a backup copy of your c:\autoexec.bat file. Then, edit your c:\autoexec.bat file so that it contains the line:

  2. 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.

  3. Reboot your computer.
  4. Check the cortex.cfg file in the \vcortex\vcwin32 directory on your send computer to make sure that it accurately reflects your devices and settings.
  5. The testing files (items, conditions, timing files) must be located on the send computer. (The associated *.lut files must be located in the specified directory on the send computer. If a path to the .lut file is not specified in the conditions file, Cortex will look for the .lut file in the current directory.)
  6. Create shortcuts on your send computer desktop for the VCSend.exe and VCSingle.exe. Double-click on the shortcut to VCSingle.exe or VCSend.exe, depending on which version you would like to run
3.6.4 Installing the DirectX Receive Program on the receive computer (Win95/98/2000/XP)
  1. Download and unzip the zip file on the receive computer. Again, I will assume that it is unzipped to the c:\vcortex directory.
  2. In order to use the DirectX receive program (DXRecv.exe), the graphics card in your receive computer must be supported by DirectX, and the DirectX 6.0 (or higher) driver must be loaded. The DirectX driver can be downloaded from the Microsoft web site (http://www.microsoft.com/windows/directx/downloads/default.asp). If you are only interested in running DXRECV.EXE, you only need to download the DirectX driver. (If you are interested in changing and recompiling the DXRECV code, you must download the DirectX SDK. See Section 7.3.)
  3. If you are interesting in running AVI, MPEG, or QuickTime movies in DXRECV.EXE, you must also have Microsoft Internet Explorer version 4.0 or higher, installed on your computer.
  4. Download and unzip the latest VCortex distribution code from the Cortex web page. At a minimum, the \Wcortex directory must reside on the receive computer.
  5. If you have bitmaps associated with your tests, they must also reside on the receive computer, since the bitmap files do not get transmitted over the serial line. (If they are not there, you will get the error "can't calc image size" on the send computer.)
  6. The DirectX receive program (DXRECV.EXE) is a Windows application, which must be run from Windows (not DOS). The easiest way to run it, is to make a shortcut on the desktop of the receive computer to the executable, \WCORTEX\DXRECV.EXE. When you want to run the program, just double-click on the DXRECV.EXE shortcut icon. An hourglass may (or may not) appear for a few seconds. When you start vcsend.exe on the send computer, the receive computer display should turn black.
3.7 Uninstalling Cortex

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.

4. Using Cortex
A fundamental feature of Cortex is that it is organized around "trials". That is, data are collected in discrete trials that last anywhere from a few milliseconds to a few minutes, followed by an "intertrial" interval in which the program does bookkeeping such as storing data from the previous trial and setting up the conditions for the next trial. The duration of the intertrial interval can be increased by the user, but the minimum may be about half a second or so (or longer if you need to read in large images from disk files).

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.

4.2. Item files

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)

  1. regular polygon
  2. ascii string
14 cross
 
 

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).

4.3. Conditions files

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.

4.4. Timing files

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.
 
 
 
 

5. Running VCortex
5.1 The Main Menu Structure After the VCortex programs (VCSend or VCSingle) are started, the following window is displayed (see Figure 5.1). Along the top edge of the VCortex window is the Main Menu. This menu consists of 9 submenus: File, Edit, Options, Tools, Run, Clear, View, Window, and Help.

Figure 5.1 To select a menu option, click the mouse on the desired menu heading, and select an option from a drop-down menu. If you would prefer to use the keyboard, use the Alt key with arrow keys to traverse the menu, or use the Alt key with the underlined letters from the heading to select a particular submenu.

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.
 
 

5.1.1 The File Menu When the File heading is selected, the submenu consists of Load, Save and Exit. The Load pop-up menu consists of Item File, Condition File, Timing File, Saved File, LUT File, External Variables File, and Blocks File (see Figure 5.2). Selecting one of these options loads a file of that type into the program to be used for a trial. These operations can also be invoked without using the menu by using the corresponding shortcut listed on the right side of the dialog box.

Figure 5.2 The Save pop-up menu consists of Item File, Condition File, Saved File, LUT File, and Blocks File (see Figure 5.3). Selecting one of these options saves the file of that type that is currently loaded into the VCortex program memory, to the path specified in the resulting dialog box. If you load a file with the File->Load menu, and then make changes using the Edit menu, you will need to use this Save option in order for your changes to be saved to disk.

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.
 
 

5.1.2 The Edit Menu When the Edit menu is selected, the submenu consists of Individual Item, Individual Condition, Timing File, External Variables, Fixspot Item, Reference Item, LUT, and Add an Item (see Figure 5.4). Any changes that you want to make to the files that are loaded must be done from this menu. Remember that any changes made will have to be saved using File->Save in order for the changes to remain after the program is closed.

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
 
 

5.1.3 The Options Menu From the Options menu you can select Block/Repeat, or General Parameters. (See Figure 5.6) Block/Repeat has a pop-up menu with Sizing, Master Block, and Individual Block. Sizing is used to set the number of blocks and length of the circular buffers. Master Block is used to set block information and number of repeats. Individual Block is used to set number of trials and condition information for each block. The General Parameters option is used to set many of the parameters of the program.

Figure 5.6
 
 

5.1.4 The Tools Menu From the Tools menu, the LUT menu has a pop-up with Set Number of Palettes and Activate. (See Figure 5.7) The Set Number of Palettes option is used to allocate space before you can load a LUT file. The Activate option is used to set which LUT is active on the graphics card of the subject's monitor.

Figure 5.7
 
 

5.1.5 The Run Menu The Run menu consists of Start, Stop and Resume. (See Figure 5.8) The Start option is used to start running the trials, once the necessary files have been loaded and the parameters have been set through the menus. At this point, a dialog box will appear which allows you to specify the output data file name. After the output data file name has been set, the trials will begin. As a shortcut to this option you can press the F5 key to start the trials.

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

5.1.6 The Clear Menu The Clear menu consists of External Variables, Blocking, and Histograms/Rasters. (See Figure 5.9) The External Variables->All option clears all the External Variables.

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.

Figure 5.10

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.
 
 

5.1.7 The View Menu The View menu consists of Results of most recent trial, Display an Item, Display a Condition, and Status Bar. (See Figure 5.11) The "Results of most recent trial" option has a pop-up with Codes and EOG values as sub-options. The Codes option will display a window containing the encodes that occurred during the most recent trial. The EOG values option will display a window containing the EOG values that occurred during the most recent trial. Display an Item can be used to display, on the subject's monitor, an item from the items file that was loaded. Display a Condition can be used to display, on the subject's monitor, a condition from the conditions file that was loaded. The Status Bar option is a simple toggle to specify whether or not the status bar should be present on the VCortex application window.

Figure 5.11
 
 

5.1.8 The Window Menu The Window menu has options for Cascade and Tile. (See Figure 5.12) This adjusts the arrangements of the windows. Cascade aligns the windows on top of each other with only the heading visible. Tile arranges the windows so that they are all maximized in the space provided.

Figure 5.12
 
 

5.1.9 The Help Menu

The Help menu has one option: About VCortex. (See Figure 5.13) This displays the copyright and version information.

Figure 5.13
 
 

5.2 The File Menu Dialog Boxes
 
 

5.2.1 File->Load->Item File

A standard file open dialog box will be presented. (See Figure 5.14) Select the items file that you would like to load for your experiment. Only one items file may be loaded into VCortex memory at a time. If you try to load another items file, it will overwrite the items in memory that were previously loaded.

Figure 5.14
 
 

5.2.2 File->Load->Condition File A standard file open dialog box will be presented. (See Figure 5.15) Select the conditions file that you would like to load into your program. You may only load one condition file. If you try to load another conditions file, it will overwrite the conditions in memory that were previously loaded.

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

5.2.4 File-> Load ->Saved File A standard file open dialog box will be presented. (See Figure 5.17) Select the "saved" file that you would like to load into your program. Saved files include all settings that were loaded into the program at the time it was saved via File->Save->Saved File. The saved file contains the names of the item files, condition files, timing files, the blocking parameters, and the general parameters for the particular experiment. Please note that the external variables file and their settings are not saved to the saved file.

Figure 5.17
 
 

5.2.5 File-> Load ->LUT File A standard file open dialog box will be presented. Select the LUT file that you would like to load into local VCortex memory. Before you can select this option, you must allocate space for the number of LUTs that you want to load in one of two ways. The first way is by setting the LUT parameter in the cortex.cfg file. The second way is by using Tools->LUT->Set number of palettes. If you do not allocate enough space, a dialog box will appear that asks you to allocate space (see Figure 5.18)

Figure 5.18 If enough space is allocated a dialog box will appear, Figure 5.19.

Figure 5.19
 
 

5.2.6 File->Load->External Variables File A standard file open dialog box will be presented. (See Figure 5.20) Select the external variables file that you would like to load into VCortex memory. An external variables file allows you to give a meaningful name and a value to the Cortex external variables. The values of these variables persist between trials. Their values can be changed in the timing file, or through the Edit->External Variables menu option.

Figure 5.20
 
 

5.2.7 File->Load->Blocks File A standard file open dialog box will be presented. (See Figure 5.21) Select the block file that you would like to load into your program. A block file is used to load the blocking parameters that were set up and saved for a particular experiment. Unlike the File->Load->Saved Files option, the blocks file does not contain information about the items, conditions, timing files, or about the general parameters.

Figure 5.21
 
 

5.2.8 File->Save->Item File A standard file save dialog box is presented. (See Figure 5.22) Select the path and filename that you want to use to save the items that are currently loaded in the VCortex memory. It is only necessary to select this option if the items were explicitly changed via the Edit menu.

Figure 5.22
 
 

5.2.9 File->Save->Condition File A standard file save dialog box is presented. (See Figure 5.23) Select the path and filename that you want to use to save the conditions that are currently loaded into VCortex memory. It is only necessary to select this option if the conditions were explicitly changed via the Edit menu.

Figure 5.23
 
 

5.2.10 File->Save->Saved File A standard file save dialog box is presented. (See Figure 5.24) Select the path and filename that you want to use to save all the files and parameters that are currently loaded into VCortex memory.

Figure 5.24
 
 

5.2.11 File->Save->LUT File This menu option presents a dialog box that asks you which LUT you want to save. The range is specified to the left of the edit box in parentheses, and is determined by the number of LUT files that have been allocated with the Tools->Number of Palettes, or with the LUT parameter in the cortex.cfg file. (see Figure 5.25)

Figure 5.25 Once a LUT number has been specified, a dialog box will be displayed that allows you to specify the entry number at which you would like it to begin saving. (See Figure 5.26) The dialog box also contains a field to specify the file name of which to save the LUT file. You can enter the entire path in the box provided, or you may use the Browse button to traverse the file directory.

Figure 5.26
 
 

5.2.12 File->Save->External Variables File A standard file save dialog box is presented. (See Figure 5.27) Select the path and filename that you want to use to save the External Variables file that is loaded into VCortex memory.

Figure 5.27
 
 

5.2.13 File->Save->Blocks File A standard file save dialog box is presented. (See Figure 5.28) Select the path and filename that you want to use to save the block parameters that are loaded into VCortex memory.

Figure 5.28
 
 

5.3 The Edit Menu Dialog Boxes

5.3.1 Edit->Individual Item

This menu option allows the editing of the items that were loaded from the items file. First, you must select the item to be edited. (See Figure 5.29) The range of valid items is given in the dialog box in parentheses. Cortex automatically starts the numbering at –4. –4 is the Background, -3 is the Fixation spot item, -2 is the Reference field, -1 is the Reference point, and 0 is the Play item. All other items loaded by your item file will begin at 1.

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.

        1. Item Type
Annular Ellipse (See Figure 5.30)  

Figure 5.30

Annulus (See Figure 5.31)


 
 
 
 
 
 

Figure 5.31

Ascii (See Figure 5.32)

- Ascii Character: the character that you want to display

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)

- File Name: the name of the bitmap file that will be loaded. You may enter the entire path in the space provided or you can use the Browse button to traverse the directory.

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)

- File Name: the name of the movie file that will be loaded. You may enter the entire path in the space provided or you can use the Browse button to traverse the directory.

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

        1. Window Size (See Figure 5.44)
Bitpan - "Bitpannable" means that you plan to pan objects around inside a stationary window on the screen. If "No" is chosen from the Bitpan listbox, the object will not be bitpannable. If "Manual" is chosen from the Bitpan listbox, this means that the object is bitpannable, that Cortex should utilize the window size you specify. In this case, Cortex will replicate the object 4 times, to give you more object to pan around with. If "Automatic" is chosen from the Bitpan listbox, it means the that the object is bitpannable, but Cortex won't replicate it. Because of this, the window size is simply the size of the object, and cannot be specified. If you use Manual option, 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 Automatic if you have an extremely large object.

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
 
 

5.3.2 Edit->Individual Condition This menu option allows you to edit the conditions that were loaded from the conditions file. (See Figure 5.45) First, you must select the condition to be edited. The range of possible items to select is given in the dialog box in parentheses.

Figure 5.45 After the condition number is entered, and OK is pressed, a dialog box will appear which allows you to edit the conditon. (See Figure 5.46) The entry fields labelled Test0 through Test9 represent the "test screens" (i.e., TEST0 through TEST9 in the conditions file). See Section 4.3 of this manual for more information about test screens. For each test screen, the items that you want to appear together should be on the same line. The maximum for each line is 16 items, and each item number must be separated by a space.

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
 
 

5.3.3 Edit->Timing File->Modify This menu option allows you to load a different timing file in the place of a timing file that has already been loaded. (See Figure 5.47) The possible range of numbers to choose from appears in parentheses, and is the number of timing files that are already loaded. The timing file number is assigned when the timing file is loaded via File->Load->Timing File.

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
 
 

5.3.4 Edit->Timing File->Delete This menu option allows you to remove a timing file that has already been loaded. (See Figure 5.49) Specify the timing file number to be deleted. The range of valid timing file numbers is shown in parentheses. The timing file number is assigned when the timing file is loaded via File->Load->Timing File. When the timing file is deleted with this menu option, any timing files that had been loaded after this file, will move up to fill the empty spaces. For example, if you have five timing files loaded, and you delete timing file #3, the timing files loaded as #4 and #5 would be reassigned timing file numbers 3 and 4.

Figure 5.49
 
 

5.3.5 Edit->External Variables->Generic Externs This menu option allows you to edit the external variables. (See Figure 5.50) Each type external variable has its own page in the dialog box, and the type is specified by the page tab. The types that you can modify are char, int, long, and float. You can select values for variables 0-29 of all four types.

Figure 5.50
 
 

5.3.6 Edit->External Variables->Named Subsets

This menu option is very similar to the Generic Externs option, except the user-defined names of the external variables are displayed. (See Figure 5.51) The user must create an external variables file of a specific format using #SET lines, in order to name the external variables. (See the demo file named \demos\misc\externsw.tim.) The file must then be loaded with the Load->External Variables File menu, before the names will show up in the Edit->External Variables->Named Subsets dialog box. Once the external variables file has been succesfully loaded, you are able to then use these names in your timing files. If you select this menu options without already loading an external variables file, you will be prompted to first load a file.

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
 
 

5.3.7 Edit->Fixspot Item This menu option allows you to edit the item that will be used as the fixation point. This dialog box is the same as the Edit->Individual Item menu option discussed in section 5.3.1. 5.3.8 Edit->Reference Item This menu option allows you to select which item is the reference item. (See Figure 5.58) The range of possible reference items is specified in the dialog box in parentheses. Five of the possible reference points are: 'background (-4)', 'fixspot (-3)', 'Rfield (-2)', 'Rpoint (-1)', and 'Play (0)'. The reference point is the location that Cortex defines to be the center of its coordinate system for placing items on the screen. For some studies in fixating subjects, the fixation spot is the most natural reference point. If you make the fixation point the reference point, then the location of all the stimulus items will necessarily be in retinal coordinates. Alternatively, you might want your items displayed at locations relative to some other point on the screen, such as the center of the receptive field you are studying. If so, choose the 'Rfield' item (item number –2) as the reference point. Note that, unlike other items, the fixation point location is always specified in screen coordinates, i.e. its location is not referred to any reference point other than itself. You are also able to specify any of the items that you loaded from the item file as the reference item.

Figure 5.58
 
 

5.3.9 Edit->LUT This menu option allows you to edit the contents of a lookup table. (See Figure 5.59) First, select which lookup table to edit. The range is specified in the dialog box in parentheses.

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.3.10 Edit->Add an Item This menu option allows you to add an item to the end of the list of items that are loaded into memory. The dialog box is the same as for editing an individual item, so see "Section 5.3.1 Edit->Individual Item" for more details. Note: The added item will not be added to the item file unless you choose File->Save->Item File. 5.4 The Options Menu Dialog Boxes

5.4.1 Options->Block / Repeat->Sizing

In this dialog box, you change the number of blocks, and the lengths of the circular buffers for each block and condition. (See Figure 5.62) All values must be greater than or equal to zero. Number of Blocks: The number of distinct blocks that should be created. The default is one block.

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
 
 

5.4.2 Options->Block / Repeat->MasterBlock This dialog box consists of two pages: Options and More. (See Figure 5.63) 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. 5.4.2.1 Options Number of repeats: The number of times that the blocking structure should be repeated.

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:

Incremental: The blocks to be run will follow in sequential order (i.e. 1,2,3...). If Delayed_Retry is selected for On_Error, there may be discontinuities (e.g. ...8,9,3,7) if the block which needs to be repeated has a lower block number than those which would normally be run next.

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.

Clear block circular buffer when: This refers to the automatic resetting of the circular buffers (recency tables) and the num_correct and num_errors counters they contain. Although BLOCKstats is updated correctly, CORTEX uses it to determine the order of blocks for the next trial. The default for this variable is "When block changes". Possible values are: Manual: CORTEX never clears BLOCKstats, so the user must do so manually.

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

5.4.2.2 More (see Figure 5.64) Next block: When this value and next condition 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).

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:

Ignore: Do not do anything special when errors occur; count them as normal block. Thus, if you specify Number of repeats = 25, there will be exactly 25 master blocks. If On error is not set to "Ignore", error blocks are not counted towards number of repeats.

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.

Clear condition circular buffer when: This refers to the automatic resetting of the circular buffers (recency tables) and the num_correct and num_errors counters they contain. Although CONDstats is updated correctly, CORTEX uses it to determine the order of conditions for the next trial. The default for this variable is "At Start". Possible values are: Manual: CORTEX never clears CONDstats, so the user must do so manually.

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
 
 

5.4.3 Options->Block/Repeat->Individual Blocks This menu option allows you to set up the staircasing parameters for each individual block. First, specify the block number that you want to edit. (See Figure 5.65) The range is specified in the dialog box in parentheses. Changing the number of individual blocks available must be done from the Options->Block/Repeat->Sizing menu option.

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.

5.4.3.1 Options (see Figure 5.66) Maximum trials: Specifies the total number of trials that should be run this block.

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:

Incremental: The conditions to be run will follow in sequential order (i.e. 1,2,3...). If Delayed_Retry is selected for On_Error, there may be discontinuities (e.g. ...8,9,3,7) if the conditions that need to be repeated have lower cond_ids than those that would normally be at the end of the sequential list.

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.

On Error: Defines what happens if an error occurs within this block. The choices are: Ignore: Do not do anything special when errors occur; count them as normal trials. Thus, if you specify Maximum trials = 25, there will be exactly 25 trials in that block. If On error is not set to "Ignore", error trials are not counted towards Maximum trials.

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

5.4.3.2 More (see Figure 5.67) Min % OK: Specifies the minimal percent correct threshold. That is, if the block's current percent correct is higher than this value, then the block will be considered correct.

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:

==Max trials: as soon as the maximum number of trials has occurred, the block will be completed. If On Error is set to Ignore, the maximum number of trials will be the same as the number of trials. Otherwise the counter for the number of trials will be number of correct conditions.

% 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.

Minimum Trials: Specifies the number of trials that the block will run before testing other parameters such as Min % OK.

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
 
 

5.4.4 Options->General Parameters

This dialog box has five pages: Eye, A2D, Debug, Misc, and More Misc.

5.4.4.1 Eye: (See Figure 5.68)

Save eye data to file: This checkbox must be checked for the eye data to be stored to the output data file.

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.

EOG: The number of clock ticks between storage of EOG data.

EPP: The number of clock ticks between storage of EPP data.

Eye spot refresh rate: The rate in milliseconds of how fast the eye dot is updated on the user screen. Basically, it sets the time of the thread which is called to draw the eye dots to the screen.

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.

X: x-dimension in degrees of visual angle

Y: y-dimension in degrees of visual angle

Max saccade allowed: This value will be used as a saccade criterion.
Figure 5.68 5.4.4.2 A2D: (see Figure 5.69)

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 gain: If for some reason you can't get your gain high enough or whatever, you can also enter an integer gain multiplication value in this field, which will be used to multiply all incoming A/D values. The default is 1, which is the recommended setting.

EOG offset:

X: This value will be subtracted from the X values of the incoming A/D data. The default setting is 0.

Y: This value will be subtracted from the Y values of the incoming A/D data. The default setting is 0.

Figure 5.69 5.4.4.3 Debug: (see Figure 5.70) # Tiks between spikes: The random_spike_device generates "fake" data for the purpose of debugging the code, interface, etc. This parameter allows testing at different rates of data input. By default, it is set to 50 milliseconds between data points. Figure 5.70 5.4.4.4 Misc: (see Figure 5.71) CLT load index: By default, color lookup tables are loaded at entry 128, leaving the lower 128 entries for Cortex to use for the background and the generic single-color items. However, if you need to use more than 128 entries for the colors in your bitmaps or movies, this parameter allows you to set different starting points.

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.

Figure 5.71 5.4.4.5 More Misc: (see Figure 5.72) Detect Bar: When using the get_bar_state() function in the timing file, Cortex will check digital input #2 of the DASH16 board for the bar state. By default, it assumes that the bar will be pressed up or down. If the left-right option is selected instead, Cortex will check a combination of digital inputs #2 and #3 to determine the position of the bar.

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 The Tools Menu Dialog Boxes

5.5.1 Tools->LUT->Set Number of Palettes

This menu option allows you to set the number of palettes, (i.e., LUT's) that you can load into your program. (See Figure 5.73) This number must be changed to a number greater than zero before you can load any LUT files. You do not need to set the Number of Palettes if you are simply using one LUT which is loaded per condition in the conditions file. You only need to set this value if you are using multiple LUTs per condition, or if you wish to edit the LUT.

Figure 5.73
 
 

5.5.2 Tools->LUT->Activate This menu option allows you to specify which LUT should be active on the graphics card on the subject's computer. (See Figure 5.74) Only one LUT can be active at a time. The LUT number is based upon the number that you assigned to the LUT, when it was loaded with File->Load->LUT File.

Figure 5.74
 
 

5.6 The Run Menu Dialog Boxes

5.6.1 Run->Start

This menu option must be chosen to begin the running of trials. Before you can select this option you must load an items file, load a conditions file, load a timing file, and set up the blocking parameters. The minimum number of blocking parameters that must be set up are the maximum number of trials, the first condition, and the last conditon in the Individual Block dialog box. All other settings are optional depending on the complexity of the blocking (staircasing) that you need. You will be prompted for the file name and path to save the output data file with a standard file open dialog box. (See Figure 5.75)

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
 
 

While the trials are running, the spikes and eye values will be drawn to the screen, if the timing file and program parameters were set up for collecting data and displaying it. The status window will be updated as the trial runs also. See Figure 5.77 below, for a view of the screen after some trials are run.

Figure 5.77
 
 

5.6.2 Run->Resume

This menu option allows you to resume running a block which was terminated by user intervention. To stop a trial within a block, the user can program the timing file to process key presses to get out. Suppose the block is 10 trials long, and the user escaped at trial #5. If the user presses Run->Start, the block will start over from the beginning and will run all 10 trials. If the user presses Run->Resume, however, the block will start from trial 5 and go on. The Run->Resume option does not clear out the blocking parameters, while Run->Start does clear them out. If the block was not interrupted and the Run->Resume menu option is chosen, then an error message will appear telling the user that the trials can not be resumed, and the Run->Start option must be chosen instead. 5.6.3 Run->Stop The Stop option is used to exit the program. It closes all the windows and exits. (It is the same as File->Exit.) 5.7 The Clear Menu Dialog Boxes

5.7.1 Clear->External Variables->All

Prompts the user before clearing all external variables. 5.7.2 Clear->Blocking->CONDstats Prompts the user before clearing the condition statistics. 5.7.3 Clear->Blocking->BLOCKstats Prompts the user before clearing the block statistics. 5.7.4 Clear->Blocking->Reset All

Prompts the user before clearing all the blocking statistics and resetting to one empty block.

5.7.5 Clear->Histogram/Rasters

Prompts the user before clearing all histograms and rasters. Please note that the clear will not take place immediately. Instead, the histograms and rasters will be cleared the next time that Run->Start is chosen. 5.8 The View Menu Dialog Boxes

5.8.1 View->Results of most recent trial->Codes

After the trials have finished running, this menu option may be chosen. The Codes option will display a window containing the encodes that occurred during the most recent trial. (See Figure 5.78) The contents of the window are determined by which encode() function calls were programming into the timing file, and the contents of the encodes.h file.

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

After the trials have finished running, this menu option may be chosen. The EOG values option will display a window containing the EOG values that occurred during the most recent trial. (See Figure 5.79) In order for EOG values to appear, the user must have selected an EOG Storage Rate greater than zero in the Options->General Parameters dialog box.

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
 
 

5.8.3 View->Display an Item

This menu option allows you to display one of the items that are loaded. You must enter the item number to be displayed. (See Figure 5.80) The range is specified in the dialog box in parentheses. When you press OK, the item will be displayed on the subject's monitor.

Figure 5.80

When you are finished viewing the item, select OK in the next dialog box.
 
 

5.8.4 View->Display a Condition

This menu option allows you to display one of the condition screens that are loaded. (See Figure 5.81) You must enter the condition number to be displayed. The range is specified in the dialog box in parentheses. For each condition, there are ten test screens that can be displayed. If you are unsure about your test screen numbers, use the Edit -> Individual Condition menu option and you will be able to view the contents of all ten test screens. An additional explanation of test screens is in the documentation for Edit->Individual Condition. This dialog box also allows you to specify if the fixspot should be displayed while viewing the testscreen, by selecting one of the circular buttons in the fixspot box. When you press OK, the testscreen of the condition will be displayed on the subject's monitor.

Figure 5.81

When you are done viewing the condition, select OK in the next dialog box.
 
 

5.8.5 View->Status Bar

This menu option is simply a toggle switch to determine whether or not the status bar at the bottom of the VCortex window is visible. Currently, VCortex only uses the status bar to display menu "tool tips". These tool tips are displayed as the mouse is moved over the menu and submenu options. 5.9 Window Menu Dialog Boxes The Window menu has options for Cascade and Tile. This adjusts the arrangements of the windows. Cascade aligns the windows on top of each other with only the heading visible. Tile arranges the windows so that they are all maximized in the space provided. 5.10 Quick Start Instructions

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)

  1. Start up the relevant programs, by double-clicking on the program icons.
  1. On the receive computer, start the DXRecv.exe program. An hourglass may (or may not) appear for a few seconds. When you start the send program, the receive computer display should go black.
  2. On the send computer, start the VCSend.exe program. The VCortex window will appear.
  1. Now, you must load an items file, a conditions file, and a timing file. The \demos directory contains a good number of these files. A simple set which is useful for testing the spike histograms, the eye movement display, and the graphics is \demos\misc\spikeeog.*. To load the spikeeog.itm items file, choose File->Load->ItemsFile. Browse the directory structure to find and select the spikeeog.itm file. To load the spikeeog.cnd conditions file, choose File->Load->ConditionsFile. Again, browse the directory structure for this file. To load the spikeeog.tim timing file, choose File->Load->TimingFile. Again, browse the directory structure for this file.
  2. There are a bunch of parameters that may be set. However, to actually run an experiment, you only absolutely must tell Cortex how many times to run, and with what conditions. To do this, choose Options->Block/Repeat->IndividualBlock. You will first be asked to specify which individual block you would like to set up. Type in "1" and click on OK. A dialog box will appear which will allow you to set the block's parameters. Enter 3 for the Maximum trials field, and 1 for the first condition and last condition. Click on OK.
  3. Now, run the trials by choosing Run->Start. It will ask you for a data file prefix for the output data file. You can browse the directory structure to put the output file into a particular directory. Type a data file prefix into the "Open" field, and click OK. You will be asked to provide a file extension for the file. The first time that you run with the given data file prefix, Cortex will append a ".1" to this name. Choose OK and the trials should start running.
  4. To quit VCortex, choose Run->Start or File->Exit from the menus.
  5. While a Windows send program is open on the screen, but when it is NOT running trials, notice how you can run any Windows program that you want. When trials are running, VCortex has priority, and will not allow you to run other things.
5.10.2 VCSingle version Double-click on the VCSingle.exe icon. Follow the instructions in section 5.10.1, step 2) onward.
6. Limitations of Cortex due to structure and hardware
6.1. Data storage

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.

6.2. Data file format

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.

6.3. Interrupt structure

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. Image File Formats and Color Lookup Tables
7.1. Image File Formats

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 Movie File Formats

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. Color Lookup Table

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.)

8. Source Code
8.1. Distribution

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
 
 

8.2. Components

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).

    1. Open the Microsoft Visual C/C++ IDE. Then, open the workspace for the program you would like to compile with the File:Open Workspace menu option. For Dxrecv.exe, the workspace is named \DXSource\DXRecv\DXrecv.dsw. For VCSend.exe, the workspace file is named \Source\VCSend\VCSend.dsw. For VCSingle.exe, the workspace file is named \Source\VCSingle\VCSingle.dsw.
    2. Open the Tools:Options:Directories dialog panel. Check that the Include file and Library files have the proper paths to the code. The following include directories must be listed: \source\include, \source\vccode, \source\lib32msc, \dxsource\include, \devstudio\vc\include, \devstudio\vc\mfc\include. The \source\lib32msc\v5m directory contains the library for the Windows serial communications. Please note that the licensing of the DirectX SDK does not allow the redistribution of the DirectX libraries. Therefore, if you want to rebuild DXRECV.EXE, you must download the DirectX SDK and the DirectX Media SDK from the Microsoft web site.
    3. Open the Project:Settings:Post-build step dialog panel. Check that it copies the executable to the proper directory.
    4. Choose Build:Set Active Configuration: Release. Then, Build:Rebuild All. After the project has built successfully, close the project.
    5. If you would like to build a debuggable version these programs, repeat the build step, but this time Set Active Configuration to Debug. Rebuild All again. Note that only the Release executable gets copied to the WCortex or VCWin32 directories, unless you change the Project:Settings:Post-build step in the Debug build Project settings. The debug workspace configuration includes the settings necessary to generate an executable that can be debugged using the NuMega SoftIce debugger. The release workspace configuration does not include debug information, so it builds a smaller (and supposedly faster) executable.
8.4. Adding new functions and external variables to Cortex

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:

  1. The string to be recognized by CSS. That is, "polar2x" is the name that you would specify in your timing file to call this function.
  2. 0 (will be translated into the index within the array for internal use)

  3.  

     
     
     
     
     
     
     
     
     

  4. the syntax string: "fff".

  5.  

     
     
     
     
     
     
     

    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 '.'.

  6. CSS_polar2x is the function name that will actually be called internally from CSS.
      1. Adding library functions
For those functions that are direct ports of internal ones, like C library math routines, there is a simplified (and faster) interface.

For example, log() is of the form

double log(double);

In order to easily add log to CSS, add the following three lines:

  1. In statefns.h, add:
CSS_1d(log,float,float) // NOTE: does not end in ';' where the first argument (log) is the name of the library function, the second argument (float) is the type of the return value of the function, and any subsequent arguments (float) are the types of the input parameters to the function.

b) In a source code file, such as \ufns\_system.c, add:

CSS_1(log,float,float) // NOTE: does not end in ';' Note that although log() expects arguments of type double, this interface will work, since the float passed to it will be promoted to double, and the result will be truncated to float by the C compiler. c) In the SystemFns[] array in the file \ufns\ufnlst.c, add: CSS_1s(log,float,float) // NOTE: does not end in ';' There are CSS_?(), CSS_?d(), and CSS_?s() macros for functions passing up to 15 arguments (and more can be made). Note that macros specify a return value and the arguments, and '?' needs to be correct, or else the macro will balk (don't worry, it will let you know). Microsoft's C/C++ compiler does more rigorous error checking, and will warn when a void function returns a value. This is not an error, since void functions traditionally return an integer value that is ignored, and those values are returned in a register, as opposed to on the stack, so the stack is not corrupted. However, in order to eliminate those warning messages, an additional class of CSS_?v() macros have been added, which expand to

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.

9. Data File Structure
As described earlier in this document, the disk file consists of the sequential data for each trial. Each trial's worth of data is preceded by a header. The structure of the header is given in the file disk.h, which is typically in the \source\include directory. The structure is as follows:

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.
 
 

9.1. Sample data file

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

  1. code for response error
The following data items each occupy 4 bytes (long integer)

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)

  1. first epp_x value
  1. first epp_y value
  1. second epp_x value
  1. second epp_y value
etc.

The following data items each occupy 2 bytes (short integer)

  1. first eog_x value
  1. first eog_y value
  1. second eog_x value
  1. second eog_y value
etc.

Following these data items would be the header for the next trial's worth of data...and so on until end of file.

10. Troubleshooting
10.1 Send/Receive computers cannot communicate: Debugging the serial connection

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).

10.4 Sound does not play

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.

    1. EOG data is not being stored to file
  1. Make sure that the wiring to the data acquisition board is set up, so that Channel 3 is the x value of the EOG, and Channel 4 is the y value of the EOG. (See Section 3.3.3)
  2. The timing file must contain a call to the function put_eye_data_in_buf(ON), to start EOG data collection. To end EOG data collection, call this function with "OFF" as the parameter. The EOG data does not get stored with timestamps. Therefore, the usual strategy is to call the function encode(), near the call to the put_eye_data_in_buf(ON) function, to place a timestamped code into the data file.
  3. The rate at which EOG data is stored is controlled through the Cortex menus. In the Options->General Parameters->Eye->EOG_storage_rate (# of clock ticks between entries) field, a value greater than 0 should be entered. This value is used as a countdown timer that determines when the x and y EOG 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.
  4. So that the values will actually be stored to file, you must also set the "Save eye data to file?" parameter to "yes". This parameter can be found in the Options->General Parameters->Eye menu.
    1. EPP data is not being stored to file
Cortex is able to input 4 channels of analog data. If you are using a version before 5.3, Cortex could only read/store two analog channels. If you are using a version of Cortex after 5.3, you will be able to store all 4 analog channels. To use Cortex with 4 analog channels:
  1. Wire the DAS16 portion of your data acquisition card so that channels 3 and 4 are used for the EOG data, and channels 1 and 2 are used for the EPP data. Refer to the diagram in section 3.3.3 for information on how to do this.
  2. Add the line "A2D_CHANNELS 4" to cortex.cfg. This will make CORTEX cycle among the 4 analog channels, reading one per clock interrupt.
  3. The timing functions put_epp_data_in_buf(ON) and put_eye_data_in_buf(ON), respectively, must be called before data can be stored in the respective buffers. To end EOG and EPP data collection, call these functions with "OFF" as the parameter. The EPP data does not get stored with timestamps. Therefore, the usual strategy is to call the function encode(), near the call to the put_epp_data_in_buf(ON) function, to place an timestamped code into the data file.
  4. Options->General Parameters->Eye->EPP_storage_rate and Options->General Parameters->Eye->EOG_storage_rate control the rate at which data is stored into the buffers. These values are used as countdown timers that determine when the x and y EOG/EPP values are stored. Since only one analog value is read per millisecond, this value should be set to at least 4 when storing all 4 channels.
    1. Adjusting the gain of the analog data
First, make sure that the data acquisition board and your analog input have the appropriate settings. Cortex expects the analog data to be input as bipolar (+/- 5V) data. Additionally, the wiring is usually configured as 16 single-ended channels. On the ISA-bus data acquisition cards (DASH-16, CIO-DAS16, CIO-AD16, and CIO-DAS1602/12), these settings can be made with jumpers on the card. Refer to the manual that was shipped with the data acquisition board for more information about the jumpers.

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.
 
 

  1. 12 Can not see spike codes when viewing data
Cortex reads the encodes.h file in the directory from which you run Cortex (and Cortview.exe) to generate the mapping between encode() values and the values printed from View->Results of most recent trial->Codes menu option from within Cortex, or from the standalone DOS program Cortview.exe. Cortex parses the encode values, expecting a format like

#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.

Appendix A. Technical Notes on Blocking
A.1 Overview of the built-in capabilities for general staircasing designs

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

  1. BLOCKset_next: sets the next block and/or condition value. You must specify non-0 to change the block/condition, or specify 0 to stay the same. If BLOCKset_next(-1,-1) is called, this triggers the end of the block of blocks. The one limitation is that the user must specify valid block and condition numbers.
  2. BLOCKget_block_num and BLOCKget_cond_num: returns the current block and condition numbers.
  3. BLOCKget_max_vals: returns the maximum values for block and condition. The minimum value is 1. This way the user does not have to know how many blocks and conditions there are ahead of time.
  4. BLOCKget_pct_correct: returns the percent correct for a given block or condition.
  5. BLOCKget_stats: returns the total number of trials, the number of correct trials, and the recency (circular) buffer for a given block or condition. When the general blocking menus look at recent correct, they are always looking at the block recency buffer. There are also recency buffers for conditions, so one could drop a particularly problematic condition out of a block if so desired.
  6. BLOCKclear_stats: Allows the user to clear the recency buffer and percent correct (num_trials and num_correct) tables for a given block or condition. Can also do this for all blocks and/or conditions.
  7. BLOCKget/set_control_info: Allows the user to view or change many of the control parameters for individual blocks. Allows semi-manual operation. For example, early on in a trial, one might want to let the subject make many mistakes. Later in a testing session, though, one might want to abort the block if the accuracy drifts too low. These functions let these criteria be changed mid-block.
A.4 Technical details on the internal operations of the Cortex code

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.

Appendix B. Known Bugs, Limitations, and Differences from DOS Cortex
  1. The Windows version of Cortex currently only works with Windows 95 or Windows 98. Additionally, it only works with the ISA versions of the data acquisition boards, or with no boards at all.
  2. The VCortex windows can be resized, but the contents of the windows will not be proportionally sized to fit the window.
  3. Play mode has not been implemented in this release.
  4. The touch screen code that was written for the DOS version of Cortex, has not been migrated to the Windows version. Therefore, touch screens are not supported in this version of VCortex.
  5. The VCortex windows can not be moved, resized, or closed while it is running trials. You must wait until the trials have completed to do this.
  6. You can run anything you want while VCortex is open on the desktop, but is NOT running trials. In this state, you can use a word processing program or Notepad to edit your files, run Matlab to look at data, etc. But it is recommended not to use any program while VCortex is running trials. In fact, it is best to kill all background tasks except for Systray and Explorer.
  7. Timing files written for the latest version of DOS Cortex (version 5.9.5) should work with VCortex, with two exceptions:
  1. The Cortex global variables (such as TIMERms_counter) had to be shared in the VxD's memory. Therefore, they require an explicit get or set function in order to retrieve them. For example, occurrences in a timing file of TIMERms_counter must be changed to get_TIMERms_counter() or set_TIMERms_counter(). See Appendix D for descriptions of the new functions.
  2. There are a subset of timing file functions that will not work in the Windows version. In particular, any standard I/O function which is supposed to read/print to the screen (like printf, scanf) will not work. Any old DOS system calls (like Cls()) will not work. Any old Cortex Lotus-style menu functions that were available for timing files (like SMENUrun), will not work.
  1. 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.
  2. Similar to #8 above, the actual directory is changed when the directory is traversed during the loading of timing files. Since many timing files use "#include <css_inc.h>" for the Cortex definitions, the Cortex compiler might not be able to find the css_inc.h file if the directory was changed. One solution is to put the css_inc.h file into the directory with the timing files. An easier solution is to put the CORTDIR environment variable into the autoexec.bat file, as instructed in Section 3.6.
  3. There are a few known bugs and limitations associated with the View->Results of most recent trial->Codes and EOG menu options. First, as mentioned above, 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, the Codes 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 these options. The first bug is that once the Codes or EOG Windows are closed, VCortex crashes if the user tries to open the windows again with these menu options. The second bug is that if the Codes or EOG Windows remain open, and the user runs another trial, the Codes and EOG Windows will not change the text inside the windows unless you resize the windows.
  4. 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 VxD device driver. The largest shared memory space that I was able to allocate was 0.5 MB. Besides the data arrays, there are other parameters that must be transferred in this memory space between the application and the device driver. Therefore, I have estimated that it can store about 25000 items of each type of data. In the sample cortex.cfg file, I have set it to 15000 of each type of data.
  5. The device drivers that are required for the operation of the VCortex program are statically loaded by the Windows operating system. In order to load these drivers, the Windows system.ini file must be changed to supply the path to these drivers. Additionally, for the DASH16 driver, an interrupt is required. Please refer to Section 3.6 of this document for more information on these issues. VCortex will not run unless these drivers have been loaded into Windows.

 
 
Appendix C: Sample Cortex.cfg file
The following is an example of the Cortex.cfg file that is used to customize Cortex. Double slashes at the front of the line indicates a comment and are not interpreted.

// *************************** 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

Appendix D: New Timing File Functions in the Windows version of Cortex
As mentioned in item #7 of Appendix B, the Cortex global variables (such as TIMERms_counter) had to be shared in the VxD's memory. Therefore, they require an explicit get or set function in order to retrieve them. For example, occurrences in a timing file of TIMERms_counter must be changed to get_TIMERms_counter() or set_TIMERms_counter(). Below is a list of the new functions that were created to handle the global variables.

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

Copyright notice


Conditions for Using Cortex

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.