Cross Correlation Documentation The file cross.scr is loaded by the Summary program when the menu option is selected for using the review program with cross-correlations. We have created several implementations of this file, the successful ones using either Forth's double number arithmetic or floating point arithmetic. Forth was originally designed for use with computers having little memory and slow speed by today's standards. Forth itself is an integer based arithmetic which required little memory and are very fast. Clever programming or formatting can sometimes allow Forth to mimic floating point arithmetic. For example, Forth's double number standard allowed greater ranges of numbers to be used. However, even then integer Forth is not always satisfactory. Software floating point routines were added to Forth. In MasterForth the floating point routines are available when the file float.rlf is loaded. The file cross.scr loads in this floating point file. In contrast, the Gormezano/Scandrett FIRST system used a computer card with a floating point processor that fit into the Apple II. Floating point co-processors or microprocessors are more commonly found in computers today. Floating point has become common in Forth systems either through software or co-processors. It should be noted that, with the exceptions of the programs for cross-correlations and z-scores, all of the other routines for Runtime and Summary use only integer arithmetic; although at times they might appear to use decimals, this impression is pure trickery, but the fantasy is accurate. For example, the eye blink response is reported in the Runtime as Summary programs as having precision of 0.1 mm. The programs, however, operate on tenths of units (0.1) rather than on units (1.0) for all of its calculations, with a decimal point being inserted into the right place for a pretty print out. For example, a real 12.7 mm movement is treated as 127 units without the decimal in our calculations yet it is printed out as 12.7 with the decimal place inserted by the formatting commands. As can be seen, simple scaling (multiplying or dividing by 10) can avoid many fixed or floating point operations. Correlations are calculated with the subroutine simply called r; the subroutine rr accepts parameters that indicate the two arrays to be correlated and the number of data pairs for the arrays; cross does the cross correlation (correlations on shifted data); and crosscorrelation adds the user interface with the review program. In the review program, a single trial (averaged with itself) or many trials are averaged together and a cross correlation is performed by selecting a key (7). Note that an autocorrelation (data shifted and correlated with itself) can also be specified. An autocorrelation can show repeating patterns within the data itself. As with the other programs in these appendices, this file has been modified in the following ways: comments have been expanded; screens have been idenfified by numbers; codes and comments used for debugging have been removed to avoid confusion (for example, we have edited out all the double number routines); screens have been combined when their separation served no compilation or documentary purpose. \ screen 0 \ CROSS.SCR file \ need to load in floating point routines (float.rlf) for this program to work. \ float.rlf is a relocatable file, meaning that it has already been compiled but because of its addressing \ properties it can be inserted anywhere in the Forth dictionary. \ \ floating point can more easily handle very large and very small numbers than the native integer \ arithmetic used by Forth, which is why it is being used here. There are trade-offs .. \ the advantage of integer arithmetic is its speed ... \ floating point routine = 785 bytes \ = 22.74 sec for 100 iterations of 25 points at 4 MHz. \ double number routine = 785 + 185 bytes \ = 14.68 sec for 100 iterations of 25 points at 4 MHz. \ screen 1 \ this screen controls all loading of the cross-correlation routines. DECIMAL need XCOR not \if forget xcor CREATE XCOR \ if xcor is found in the dictionary then cross-correlation has been loaded. CR .( Reloading FLOAT ) programdrive dv RELOADING FLOAT \ 2 load 3 LOAD 11 17 THRU 18 20 THRU 21 LOAD \ documentation: Pearson r formula. \ constants, variables, values. \ floating point pearson. \ user input. \ cross-correlation. DECIMAL \ screen 2 \ formula for Pearson correlation \ NExy - ExEy \ rxy = ----------------------------------------\ { [ NEx2 - (Ex)2 ] [ NEy2 - (Ey)2 ] } 1/2 \ \ where r = Pearson r \ N = number of points \ E = Summation of \ 2 = squared \ 1/2 = square root \ screen 3 \ constants, variables, values need wipeout \; : wipeout ( --) 20 22 eradicate 0 21 at ; \ need for debugging need printing \if variable printing 0 value adrx 0 value adry 0 value adrn 0 value xtable 0 value ytable 0 value n \ used by cross \ used by r and rr variable fixed ascii A fixed ! \ fixed array for correlations variable lagged ascii B lagged ! \ lagged array for correlations variable f# 4 f# ! \ number of decimal places for correlations \ screen 4 \ screen 5 \ screen 6 \ screen 7 \ screen 8 \ screen 9 \ screen 10 \ screens 11, 12, 13 and 14 \ floating point implementation : fsqr ( r -- r^2) \ floating point squaring. 2dup f* ; : Ex ( -- r) \ summation of x. 0 ( dummy) xtable n bounds ?do i c@ + loop 0 float ; : Ey ( -- r) \ summary of y. 0 ( dummy) ytable n bounds ?do i c@ + loop 0 float ; : (Ex)2 ( -- r) \ square of the summation of x. Ex fsqr ; : (Ey)2 ( -- r) \ square of the summation of y. Ey fsqr ; : ExEy ( -- r) \ product of the sum of x times the sum of y. Ex Ey f* ; : (Ex)2/N ( -- r) \ square of the sum of x, divided by n; error term. (Ex)2 N 0 float f/ ; : (Ey)2/N ( -- r) \ square of the sum of y, divided by n; error term. (Ey)2 N 0 float f/ ; : Exy ( -- r) \ sum of the products of x times y. 0 0 ( fdummies) n0 ?do xtable i + c@ 0 float ytable i + c@ 0 float f* f+ loop ; : NExy ( -- r) \ n times the sum of the products of x times y. Exy 0 0 n0 ?do 2over f+ loop 2swap 2drop ; : Ex2 ( -- r) \ sum of all squared x's. 0 0 ( fdummies) xtable n bounds ?do i c@ 0 float fsqr f+ loop ; : Ey2 ( -- r) \ sum of all squared y's. 0 0 ( fdummies) ytable n bounds ?do i c@ 0 float fsqr f+ loop ; : NEx2 ( -- r) \ n times the sum of all squared x's. 0 0 ( fdummies) xtable n bounds ?do i c@ 0 float fsqr f+ loop N 0 float f* ; : NEy2 ( -- r) \ n times the sum of all squared y's. 0 0 ( fdummies) ytable n bounds ?do i c@ 0 float fsqr f+ loop N 0 float f* ; : r ( -- r) \ Pearson correlation. NExy ExEy f- ( numerator) NEx2 (Ex)2 fNEy2 (Ey)2 ff* fsqrt ( denominator) f/ ; : rr ( xtable ytable n -- r) \ perform correlation given input parameters. \ check for parameter errors. depth 3 < not if is n is ytable is xtable then xtable 0= ytable 0= or n 0= or abort" parameters not defined" r; \ screen 15 \ screen 16 : frange ( r -- r|r') \ check that correlation is within range. 1. float fmin -1. float fmax ; \ screen 17 : cross ( --) \ perform and report cross-correlation for all lags possible (0-toneon) \ or until <return><return> keypresses to stop. adrx is xtable adry is ytable adrn is n filename type cr cr ." lag " f# @ spaces ." r n msec" cr cr toneon ( to) 0 ( fr) ?do i 0 5 d.r ( 2 spaces adrx u. adry i - u.) adrx adry i - adrn rr frange f# @ 4 f# @ + f.r n 0 5 d.r i bin @ 1000 / * 0 5 d.r cr nuf? ?leave loop ; \ header for print out. \ header for print out. \ \ screens 18, 19, and 20 \ user interface : invert ( --) \ inverts a/d in etch. \ this is needed only to be 'user-friendly'. \ a/d data is collected and stored so that the relaxed eye position starts as a large number \ and becomes smaller with a blink. \ this strategy works well for displaying the data on a monitor, but it confuses the intuitive sense \ when interpretting statistics and correlations. \ therefore, the a/d data is temporarily inverted for the calculating the cross correlation. easel ( fr) #a/d @ pts * ( #) bounds ?do 255 i c@ - i c! loop ; \ user input : dashes ( n --) \ print n dashes to indicate selection or condition. ascii - swap 0 ?do dup emit loop drop space ; : .f/l ( c -- c) \ print headers for corresponding fixed or lagged variables. dup fixed @ = if space 10 dashes ." fixed array" then dup lagged @ = if space 10 dashes ." lagged array" then ; : .arrays ( --) cr \ print fixed or lagged arrays. 0 4 at ascii A 1- ( c) #a/d @ ?dup if 0 ?do 2 spaces 1+ dup emit ." . a/d " i 1+ u. .f/l cr loop then #units @ ?dup if 0 ?do 2 spaces 1+ dup emit ." . unit" i 1+ u. .f/l cr loop then ( c|c') drop ; : getc ( -- c) \ get character. key bl not and ; : inrange ( c -- c) \ check that character is within range of selections for numbers of a/ds and units. ascii A max #a/d @ #units @ + ascii A + 1- min ; : .warn ( --) \ remind user that correlations can only be done in review program on averaged data. ." Cross-, auto- & correlations are only done on" ." averaged data." ; : enterarrays ( --) \ allow user to keep or change data to perform cross correlation. begin dark .warn cr ." The currently available data arrays & defaults are:" .arrays cr ." Enter <return> to accept these defaults" cr ." Press any other key to change defaults" key EOL# = not while cr cr ." Enter new fixed variable: " getc dup EOL# <> if inrange dup fixed ! else fixed @ then emit cr ." Enter new lagged variable: " getc dup EOL# <> if inrange dup lagged ! else lagged @ then emit 5 delays repeat ; \ screen 21 \ crosscorrelation : crosscorrelation ( --) \ this is the execution word used by review to perform the correlations. \ set up parameters and arrays for analysis ... enterarrays fixed @ ascii A - pts * easel + toneon + is adrx lagged @ ascii A - pts * easel + toneon + is adry pts toneon - is adrn \ print to monitor (default) or to printer ... printing @ if printer on 15 emit ( i.e., +condensed for Epson printer) then \ cross-correlation ... #a/d @ if invert then \ invert if data is a/d type. cross \ do cross-correlation. #a/d @ if invert then \ re-invert if data is a/d type. \ return from printing ... printing @ if page printer off then cr ;