Revised:
Expo uses real numbers to represent most quantities.
Expo is compiled with object sizes and alignments that are defaults for gcc. When Expo makes files that contain programs or data, the header to the file identifies the endianness and object sizes used by the copy of Expo that made the file. The first byte identifies the endianness (0 = big endian, 1 = little endian), the second byte is the size of a short, the third byte the size of a long, and the fourth byte is the size of a double. Expo examines these sizes when it opens a program or data file, and will not load the file if any object has the wrong size.
Expo uses relatively little memory except when recording raw spike waveforms. While being recorded these consume memory at about 5.3Mb/min. After a run has finished, the buffer is compressed by a factor of four, but can still be very large. It is therefore important to have a lot of memory available if raw spike waveforms are being recorded.
Expo is multithreaded. Beyond its main thread it uses three real-time threads: one to manage a running program and two others to manage spike recording and analog signal recording. These are created as standard Pthreads and are then promoted to real-time Mach threads.
Expo creates further threads to manage display updates in the spike window and the analog signal window; others are created by CoreAudio for sound recording and playback. Additional threads are created by Cocoa, but are not managed explicitly by Expo.
Regular updates to displays (e.g., in the Status Window, Variables Window) are handled by timers that run in the main program thread.
The thread that runs a program is scheduled through a "policy" that specifies how much time should be allocated to it during a defined period (the timebase tick) and whether or not this time should be made available in one chunk or potentially in multiple chunks distributed throughout the period. Expo is compiled to tell the scheduler that the runtime thread should be allocated time in units of (up to) 1/10 of a tick, that this allocation should be provided for the full period of the tick, and that the allocation can be fragmented (the thread is preemptible). These aspects of the scheduling policy can all be changed by altering source code.
When a program is running, the thread comes alive once on every tick, and suspends itself when it has passed through its routines. When the tick is defined by the internal clock, the thread wakes up on the tick, with high precision (sample timing shows an extreme range of ~90 µsec with SD ~16 µsec). When the tick is defined by a monitor's timebase, things are handled differently: the synchronization relies on the fact that the OpenGL call to swap display buffers suspends the thread, then releases it after OpenGL has done its work. OpenGL can return before the screen refresh if it has no frame update already pending, but if there's already an update in OpenGL's queue the runtime thread will remain suspended until that update has occurred. Thus in practice (because Expo prepares frames faster than they can be displayed) the runtime thread is suspended then released by OpenGL at the frame rate. Because the start of a tick is defined by the release from the OpenGL call, timing precision is vulnerable to things OpenGL might do that we don't know about. You can tell how precise the timing is by logging timing statistics or (if you have a digital I/O card) by monitoring state changes on digital output line 0, which goes TRUE at the start of every timebase tick, and FALSE whenever Expo has passed through all routines in the active state. Sample measurements point to a standard deviation of < 50 µsec, with longest and shortest tick times differing by 1.8 msec (the real error is half of this, since the longest interval also defines the shortest).
After the thread is released at the start of a tick, different runtime routines don't always take the same time to execute. However, the variations attributable to this should be negligible, and the timing precision of things Expo does while running a program (pulses, etc.) is essentially limited by the precision of the start of a tick (above).
Expo programs are Cocoa documents, managed as subclasses of NSDocument. The document subclass (EXProgramDocument) manages through its window controllers all a program's windows and various data analysis machinery including templates. The set of open programs is managed by a subclass of NSDocumentController (EXDocumentController).
The core of the functioning Expo program is managed through the Program class and classes for its associated objects (Block, Routine, Param and Slot). Each Expo document contains a single instance of Program.
Each instance of a Program contains a header, and an array of instances of Block (all the states that make up the program) and an array of instances of Slot (all the slots that make up the schedule). Each Program instance also contains arrays to hold events of different kinds accumulated during a program run. The Program class is defined in Program.h
Each instance of Block contains an array of instances of Routine (all the routines that make up a state, or matrix substate). Each instance of Routine contains an array of instances of Param (all the parameters that are used by the routine).
When executing a state in a program, Expo passes through the routines in the order of their appearance in the state (left to right in the program editing window). You should therefore position your routines so that those that assign values to variables appear in the state before those that read the variables.
There are also some special dependencies: a routine to define a texture must be placed before the routine that defines that surface or dots to which the texture will be attached; the Quest routine should be placed before the Read Key routine that usually accompanies it.
Routine parameters that take numerical values (constants or variables) can have their values expressed in different units. The conversion of a value among units is managed through a lookup table. Each of the units that Expo knows about has an entry in the table; that entry contains information about the set of alternative commensurate units, and the transformation required to convert a value in the current unit into a value in a different unit.
Each unit Expo knows about has a unique identifier. Symbolic constants that identify all units are defined in unit.h. You should never change these constants, though you can add new ones to the list. In making a conversion between units, Expo uses their identifiers to find information needed to complete the transaction. Expo looks up the destination unit in the table, and finds in its entry information about how to convert from the source unit. The table through which unit conversions are managed is an array of UGROUP structures. UGROUP is defined in unit.h. The global array u_uarray is defined and initialized in unit.m. This array manages conversions in the current environment. When analyzing data saved in files, Expo creates for each a private array for managing unit conversions.
typedef struct { /* unit group */ char uname[NAMELEN]; /* name of unit */ short gid; /* group id (same id as base unit) */ UNIT ugroup[MAXCONV]; /* array of UNIT structs */ } UGROUP;
uname is the name of the unit; this is displayed in menus and in other elements of the user interface.
gid is a unique identifier for the group of conversions that are possible for a single unit. When Expo looks up a unit in u_uarray, it finds the correct group of possible conversions by matching gid and the identifier of the unit being looked up.
ugroup is an array of UNIT structures, one for each of the units commensurate with the one identified by gid. UNIT is defined in unit.h, and is described below. MAXCONV specifies the maximum number of alternative units into which a value can be transformed. It is defined (currently as 6) in unit.h.
When Expo makes a conversion between units, it looks up the destination unit in e_uarray, and when it finds a matching UGROUP structure, looks through the array of UNITs within that structure to find the source unit in which the value is currently represented. Having found the matching UNIT, Expo makes the conversion.
Information about how to make a conversion is held in a UNIT structure, defined in unit.h.
typedef struct unit { /* structure for conversion unit */ short uid; /* id of unit */ short flags; /* kinds of compensations required */ double scale; /* base scale of conversion */ double fscale; /* final scale (after compensation) */ } UNIT;
uid is the unit identifier, and is unique. Symbolic constants for units that Expo knows about are defined in unit.h.
flags contains flags that identify sources of information that Expo will need to calculate the conversion scale, and also certain operations (e.g., taking a reciprocal) that might be required at the time the conversion is made.
RECIP During conversion, multiply the value being converted by the reciprocal of the conversion scale.
T_PER_S The conversion scale needs to be calculated from the current timebase in ticks per second.
S_PER_T The conversion scale needs to be calculated from the current timebase in seconds per tick.
P_PER_C The conversion scale needs to be calculated from the number of pixels per centimeter on the active monitor.
C_PER_P The conversion scale needs to be calculated from the number of centimeters per pixel on the active monitor.
C_PER_D The conversion scale needs to be calculated from the number of centimeters per degree on the active monitor.
D_PER_C The conversion scale needs to be calculated from the number of degrees per centimeter on the active monitor.
D_PER_A The conversion scale needs to be calculated from the number of degrees per analog unit.
A_PER_D The conversion scale needs to be calculated from the number of analog units per degree.
V_PER_A The conversion scale needs to be calculated from the number of volts per analog units.
A_PER_V The conversion scale needs to be calculated from the number of analog units per volt.
X_SPIKE The conversion scale (for analysis routines that handle spikes) is calculated at analysis time. For some conversions involving spikes (e.g., the conversion between spikes/bin and spikes/sec, when binwidth may be a parameter in the analysis) the conversion scale has to be calculated anew before each conversion. The routine unit_setscale() in unit.m sets the unit scale.
scale specifies the initial scale factor for the conversion. For many units the scale is irrevocably determined by the type of conversion (e.g., radians to degrees), and this scale factor fully determines the conversion.
fscale holds the final scale factor, adjusted for any special circumstances. Often it will be the same as scale (above), but for some conversions (e.g., pixels/cm to cy/deg) the scale factor cannot be fully determined until local circumstances (viewing distance) are known. Units sensitive to special circumstances are identified by flags (above). Whenever Expo's environment is changed, units that are sensitive to a particular change (e.g., viewing distance) are automatically re-scaled.
Expo provides two functions that handle all unit conversions. The function unit_convertvalue(ugroup, outunit, inunit, value) returns the value, converted from inunit to outunit, using the conversion array ugroup. The current environment may not be the same as the one in which data were collected, hence the need to specify ugroup. When running a program in the current environment the global array u_uarray is used. When analyzing data that has been saved in a file, obtain the unit array by sending the "ugrp" message to the Program instance reconstructed from the data file.
Expo uses variables to pass values to parameters in routines, and to receive values from parameters. Just as the values of parameters are expressed in particular units (cycles/sec, pixels, etc.) so are the values of variables. Variables are typed by their units, so that their values can be converted among commensurate units.
A variable is created when it is first referred to by name, either when you define it in a parameter while writing or editing a program, or when Expo loads an existing program. If Expo loads a program that uses a variable that already exists, it checks to see that the units used by the variable in the program are commensurate with those used by the existing variable. If they are incommensurate, Expo will warn you. It is up to you to resolve the conflict; EXPOs unit conversion functions, used internally in managing variables, will return NAN from an attempt to convert a value between incommensurate units.
If you are adding routines to Expo you should use its Param methods "getrunvalue" and "setrunvalue" to get and set parameter values. These automatically take values from, or set values in variables, and are described more fully in Appendix C. You are unlikely to need any direct dealings with the internal structure of variables.
A variable is a subclass of NSObject; all the methods that manage variables are in Variable.m (with declarations in Variable.h). Its instance variables are:
vname is a string containing the name of the variable. Names are limited in length to NAMELEN-1 characters (currently 14 NAMELEN is defined in etype.h).
vflags defines various flags that identify properties of and control the use of variables. These flags are set when the variable is created, according to the parameter that creates it.
V_RONLY TRUE when the variable is read-only.
V_UNWRITEABLE TRUE when the variable cannot be set through the user interface.
V_TEMPTAG Temporary tag used in internal management.
V_INTINBASE TRUE when the variable must have an integral value in its base unit.
V_CANWRAP TRUE if an out-of-range value can be brought into range by taking the modulus of the range.
ubase is the base unit of the variablethe unit in which the value of the variable is always held internally. When you view a variable in the Variables window, the base unit is always shown at the top of the unit menu.
min and max are, respectively, the maximum and minimum values that the variable can take, in the base unit. Expo forces the value to be within the range, either by clipping at max or min, or, if the unit permits it (the flag V_CANWRAP is TRUE), by folding the max to the min or vice-versa. The maximum and minimum values are assigned when the variable is created or retyped. The limits are the ones defined internally for the parameter through which the variable was created.
uexpress is the unit in which the value of the variable is displayed in the Variables window.
bvalue is the value of the variable in the base unit.
Most user interaction with variables is through the Variables window, which is managed by the methods in VariableController.m, VariableWindow.m and EventView.m
When running a program, Expo puts data it collects, and other information about what it was doing, in an event queue that provides a chronological record of every important thing the program did. When you save data collected by a program, Expo saves an image of the event queue.
Expo actually maintains four event queues: one records information about state changes, and the values of routine parameters; one contains information about spike times (if the program collected any), and the third contains continuously-sampled analog signals (if the program collected any). A fourth queue holds the raw spike waveform from which spikes are extracted. The spike and analog signal queues are maintained separately from the standard event queue because information about spikes and analog signals (of which there may be a great deal) can be recorded more compactly than information about standard events.
A state event is Event class instance. Event is a subclass of NSData and is defined in Event.h. The complexities of managing concrete subclasses of abstract Cocoa classes like NSData mean that there are no instance methods, and the innards of the event are made accessible through an EVENT structure:
typedef struct etag { /* event tag */ short type; /* which event */ short osize; /* size of objects */ short count; /* how many data */ long time; /* current tick count */ short data[]; /* data */ } EVENT
type is an identifier that marks the kind of event. Expo defines (in event.h) symbolic constants for a series of standard events:
EVT_NONE a null event
EVT_PROGSTART program started running
EVT_PROGSUSPEND program was suspended
EVT_PROGRESUME program resumed execution
EVT_PROGABORT program execution aborted
EVT_PROGDONE unused
EVT_PROGEND program stopped running
EVT_SLOTSTART slot activated
EVT_BLOCKEND state ends
EVT_BLOCKSTART state starts
EVT_ROUTINE+routine id identifies data from a routine
osize defines (in bytes) the size of the objects that are stored in the event (shorts, longs, doubles, etc.). event.h defines constants for the sizes of different standard objects that events can contain.
count specifies how many objects of size osize are stored in the event.
time specifies, in 100µsec units, the time at which the event occurred. The time stored is in relation to the time at which the program started running; the time in relation to any other event can be obtained by subtraction.
data is an array of count objects of size osize that contain data for the event. Some events (e.g., those that mark the starting and stopping times of states) contain no data; their importance lies in their existence. Other events such as those that record parameter values for routines in a state contain an array of data values.
When Expo runs a program it puts standard events serially in an array accessible through the eventbase instance variable in the running Program class instance. Routines to analyze data extract events from this queue. When data are loaded from a file, Expo rebuilds the queue.
The raw waveform is recorded initially as an array of sound samplesstructures of type RAWSOUNDRECORD.
typedef struct { UInt64 time; // time at which scan recorded (host units) float buffer[0]; // buffered scan } RAWSOUNDRECORD;
As soon as sampling stops this queue (which is very large) is converted to an array of compressed samplesstructures of type COMPRESSEDSOUNDRECORD:
typedef struct { double time; // time at which scan recorded (event units from prog start unsigned char buffer[0]; // buffered scan } COMPRESSEDSOUNDRECORD;
The raw sound records are 4 times larger than the compressed records.
The information needed to make use of the array of sound records is in a queue headera structure of type COMPRESSEDSOUND:
typedef struct { // header for saved compressed sound stream int nbuffers; // number of buffers recorded int framesperbuffer; // number of frames in a buffer int nchannels; // number of channels in a frame double samplerate; // # frames/sec (after downsampling raw signal long spare[8]; // spares float scale[MAXAUDIOCHANNELS]; // scale factor on conversion to/from float float offset[MAXAUDIOCHANNELS]; // offset to add after scaling COMPRESSEDSOUNDRECORD cbuffer[0]; // array of compressed records } COMPRESSEDSOUND;
nbuffers holds the number of compressed sound records.
framesperbuffer holds the number of frames in each buffer (a frame consists of a single sound sample from each of the channels being recorded). The number of frames per buffer is determined by the sound input settings.
nchannels is the number of channels sampled in each frame (determined by sound input settings).
samplerate is number of frames per second recorded, after any downsampling. This is determined by sound input settings.
scale is a gain factor use in converting between the float values actually recorded (and used in analyzing the raw waveform) and the byte values saved in the compressed records.
offset is the offset used to base the conversion between float and byte values.
The whole COMPRESSEDSOUNDRECORD object is wrapped in an NSData instance, and is accessible through the Program instance variable rawbase.
A spike event is an unsigned long integer, in which the low 29 bits hold the time in 100 µsec units, based on the same time as events in the state event queue, The top 3 bits contain a spike id (0-7) to identify the template the spike matched. The channel on which a particular spike was recorded can be recovered from the SPIKEMAP structure in the Program header.
When Expo runs a program it puts spike events serially in a queue. The complete queue is wrapped in an NSData instance accessible through the Program's spikebase instance variable.
An analog signal event consists of a header structure plus an array of (signed) short integers containing recorded signals. The event header (defined in sigevent.h) has the following structure:
typedef struct { /* analog signal event header */ unsigned long nsamples; /* number of samples in segment */ long starttime; /* time at which sampling started */ long spare1; long spare2; short samples[]; /* array of samples */ } SIGEVENT;
nsamples specifies how many samples are in the array. It is the number of channels sampled * the number of scans completed.
starttime is the time (in 100 µsec ticks) after program start at which the first scan was made. The array of samples contains no information about the time at which samples were recorded; since all scans are clocked precisely by the sampling hardware, the time at which a scan was made (in relation to starttime) can be deduced from its position in the array.
samples contains a sequence of scans of all the analog channels sampled by the program. Each scan samples all channels, with the first element being channel 0, and successive elements being successively higher channels. Each sample is a 16-bit signed integer. Expo normalizes values read from analog hardware to be within this range.
Expo puts analog signal events in an array (NSArray) accessible through the Program's instance variable analogbase. If a program runs to completion, or is aborted, without having been suspended, there will be only one analog signal event in the queue; each time the program resumes execution after being suspended Expo starts a new analog signal event.
All the information used by an analysis template is maintained in an instance of a Template class and instances of classes for its associated objects (Datarow and Datacell). At any one time an Expo program and its data can be associated with a single Template. The template that you save and load is an archived instance of Template.
Each instance of a Template contains an array of instances of Datarow (one for each row of cells that can be displayed in the analysis table). Each Datarow instance in turn contains an array of instances of Datacell (one for each cell in the table). Each Template instance also contains a pointer to an instance of another object (Bandmap) that provides structured access to all the data in the event queues.
Template is a subclass of NSObject; all the methods that manage Template are in Template.m (with declarations in Template.h). Its instance variables are:
@interface Template : NSObject <NSCoding,NSCopying> /* template for data analysis */ { BOOL byteorder; // endianness unsigned char name[TPLNAMELENGTH]; /* name of template */ uint32_t dimensionmap[DIMMAX]; // dimension ordering for display uint32_t tflags; /* miscellaneous flags */ NSMutableArray *headers; /* array of strings for column headers */ NSMutableArray *datarray; /* array of data row structures */ uint32_t columninfo[MAXDATACOLUMNS]; // column flags Bandmap * bandmap; // pointer to data NSString * path; }
name. A C string that holds the name of the template. This is filled in automatically by Expo when it loads or saves a template.
dimensionmap. An array of integers specifying the order in which matrix dimensions should be unfolded. This is filled in automatically when a template is created or modified.
tflags. Miscellaneous flags. One is currently defined (in Template.h).
TP_DIRTY TRUE when the template has been modified
headers. An array of NSStrings that provide titles to the columns of the table.
datarray. An array of instances of Datarow, each of which defines a row in the template (see below).
columninfo. An array of flag variables (one for each potential column in the analysis table managed by the template, indexed by column position) that described the states of columns. The following are defined in Template.h:
COL_SELECTED TRUE when the column at that index is selected
COL_HASRESULT TRUE when any cell in the column at that index has a result
COL_HASERRORFORMULA TRUE when any cell in the column at that index has an error formula (e.g., s.e.m).
bmp. Pointer to the bandmap for the data to which the template is applied
path. The path to the file containing the template.
For each row in the analysis table it manages, the Template instance contains a Datarow instance that provides access to all the cells in the table. Datarow is a subclass of NSObject; all the methods that manage Datarow are in Datarow.m (with declarations in Datarow.h). Its instance variables are:
@interface Datarow : NSObject <NSCoding,NSCopying> { uint32_t row; // index in template Slot * sptr; /* slot ptr */ Block * bptr; /* block ptr */ uint32_t flags; int passesexamined; Bandmap * bmp; // data access NSMutableArray *cols; // number of cells in row }
row is the index of the current instance in the Template. It corresponds to the row index in the table in the analysis window (when the table is showing all states).
sptr is a pointer to the Slot instance corresponding to the row in the table. Expo loads sptr when it creates the template. You should never change its value.
bptr is a pointer to the Block instance for the state (or matrix substate) corresponding to the row in the table. Expo loads bptr when it creates the template. You should never change its value.
flags. Miscellaneous flags (defined in examset.h). You can read these flags (though you should not generally need to) but you should not set them.
R_INALIST The row is currently displayed in the table (i.e., it is not in a hidden part of a matrix).
R_HASSELECTED At least one cell in the row is selected.
R_ISMASKED The row has a mask applied to it.
passesexamined. Holds a count of the number of passes through the data that have been analyzed. Used internally by Expo. You should not touch it.
bmp. Pointer to the bandmap for the data to which the template is applied.
cols. An array of Datacell instances, each of which specifies the analysis to be undertaken in a cell in the row.
Each cell in an analysis table is represented by an instance of Datacell. This contains the information needed to organize the analysis of data in a single cell of the table. It also holds the results of the analysis. A Datacell is a subclass of NSObject; all the methods that manage Datacell are in Datacell.m (with declarations in Datacell.h). Its instance variables are:
@interface Datacell : NSObject <NSCoding,NSCopying> { SInt32 type; // analysis type (state, spike, etc) uint32_t dflags; /* various flags: hasformula, hasresult, etc */ SInt32 rid; /* routine id, spike id, achannel 1 */ SInt32 instance; /* routine instance, achannel 2 */ SInt32 param; /* routine param, spanmode */ SInt32 offset; // start offset (spikes/analog) SInt32 duration; // duration (spikes/analog) SInt32 ubase; /* base unit for param */ SInt32 unit; /* unit type for representation */ SInt32 anal; /* analysis type wanted */ passOffset; // offset of pass to analyze double apars[APARNUM]; /* parameters required for analysis */ double scale; /* scale factor */ char format[FORMSPECLEN]; /* format of result */ UGROUP * ugroup; // unit converstion matrix double result; /* result of analysis */ long ecount; // number of events analyzed (passes) long arraysize; // size of array (objects- doubles) NSData * array; Template * tpl; // parent template Bandmap * bmp; // bandmap for data Band * band; // band for data Band * band; // band for data int rowindex; // index of parent datarow in template AINFO * ainfo; // ptr to analysis routine info }
type. Specifies the type of analysis (routine events, spike events, analog signal events). The following flags are defined in Datacell.h.
D_ISSTATE The analysis deals with the state routines.
D_ISSPIKE The analysis deals with the spike train.
D_ISANALOG The analysis deals with the analog signal train.
D_ISEXPRESSION The cell contains an expression.
dflags. This contains miscellaneous flags that identify the status of the cell. The following flags are defined in Datacell.h.
D_HASFORMULA TRUE when the cell contains a formula.
D_HASRESULT TRUE when there is a result from the analysis.
D_ISSELECT TRUE when the cell is selected.
D_ARRAYRESULT TRUE when the cell provides an array result.
D_ERRORRESULT TRUE when the result represents an error value (e.g., s.e.m.).
rid. If the analysis deals with events generated by a routine, this contains the id of the routine; if the analysis deals with spikes, this is the spike id; if it deals with analog signals this is the number of the first channel to be analyzed.
instance. If the analysis deals with routine events, this specifies the instance of the routine within a slot/state; if the analysis deals with spikes, this is ignored; if the analysis deals with analog samples, it is the number of the last channel to be analyzed.
param. If the analysis deals with routine events, this identifies the routine parameter to be analyzed. If the analysis deals with spikes or analog samples, it specifies how the duration instance variable (below) is to be interpreted.
offset. For spike and analog signal analysis this specifies the time offset (positive or negative) from the start of the slot/state at which spike times or analog signals will be examined in the relevant event queue. Times are represented internally in 100µsec units.
duration. For spike and analog signal analysis this specifies (despite its name) the time offset (positive or negative) from the end of the slot/state at which spike times or analog signals will be examined in the relevant event queue. If param (above) is TRUE, the value of is interpreted as a duration from the start offset (above). Times are represented internally in 100µsec units.
ubase. This specifies the base unit in which the result of the analysis will be calculated.
unit. This is the unit in which the results of the analysis will be expressed.
anal. This is the id of the analysis function that Expo will call to compute the result.
passOffset. This specifies the pass whose data should be analyzed, as an offset (positive or negative) from the pass represented by the Datarow that contains the current Datacell.
apars. An array of doubles that hold values for auxiliary parameters required by the analysis (e.g., for Fourier transforms, the source of the frequency signals and the harmonics to be analyzed). Not all analysis functions require auxiliary parameters. APARNUM, defined in analysis.h, is currently 18. If the cell contains an expression, the array of doubles is treated as an array of characters (144 bytes) and the text of the expression is stored there.
scale. The factor by which the computed result is to be scaled before being stored.
format. A string that defines a printf format specifier, to control the display of the stored result. FORMSPECLEN is defined in analysis.h, and is currently 20.
ugroup. A pointer to the array of unit conversion factors appropriate for the data at the time they were collected.
result. The result of the analysis undertaken by the specified function (if the function yields a scalar result). This is set to the size of the first dimension of an array if the analysis yields a multi-dimensional array result (for a one-dimensional array the value is 1).
ecount. The number of slot/state passes analyzed.
arraysize. The number of values in the results array (if any)
array. A pointer to an array of values resulting from the analysis, or NULL. In displaying results, Expo examines array to determine whether the result is an array or single-valued: if array is NULL, the value in result is used.
tpl. A pointer to the template that contains this Datacell.
bmp. A pointer to the instance of the Bandmap class that provides structured access to all the events in the event queues (see Getting Access to Events).
band. A pointer to the instance of the Band class that provides access to all the events that occurred during passes of the slot/state represented by the current Datacell instance (see Getting Access to Events).
rowindex. The index in the parent Template of the Datarow that contains this Datacell.
ainfo. A pointer to the AINFO structure that provides access to (and other information required by) the analysis function to be executed by the cell.