'---------------------------------------------------- ' S a c c a d e S c r i p t ' ' Eye movement analysis program ' ' 'This script displays eye, target and unit data collected 'by Spike2 on a CED 1401 for analysis. The output consists 'of two files: a *.txt file with the computed attributes 'and a *.mat file containing the traces associated with 'each trial of attributes. ' 'The *.txt / *.mat file combo can be plotted and further 'analyzed in the version of Graph written in Matlab ' ' 'Input file (*.smr) channels: ' ' 50 kHz Unit := 1 ' 1 kHz HE/HGaze := 2 ' 1 kHz VE/VGaze := 3 ' 1 kHz HT := 4 ' 1 kHz VT := 5 ' 1 kHz HT2 := 8 (no analysis, display only) ' 1 kHz VT2 := 9 (no analysis, display only) ' 1 kHz HE2/Hhead := 10 (vergence/gaze analysis) ' 1 kHz VE2/Vhead := 11 (vergence/gaze analysis) ' UnitEvent := 30 (added to file by SpikeEditor Spike2 script, not required for Behavioral Analysis) ' ' ' 'Output file format: ' ' *.txt file contains all attributes from accepted trials, read with Excel or Matlab ' *.mat file contains traces from accepted trial regions ' ' '1/2/04 '---------------------------------------------------- const kParameterMilestone$ := "3/20/06 saccade format", NaN := 9999999, pi := 3.14159265359, kMS := 1000.0, '1ms is 1000 samples k20ms := 0.020, kTrue := 1, kFalse := 0, kShown% := 1, kHidden% := 0, kMaxAttr% := 512-1, 'for 0 - 511 kCh2Analyze := 3, 'colors kBlack% := 0, kRed1% := 8, kRed2% := 9, kRed3% := 10, kRed4% := 11, 'attribute constants kModeBehavior% := 0, kModeBurst% := 1, kModePause% := 2, kNormalAnalysis% := 0, kVergenceAnalysis% := 1, kGazeAnalysis% := 2, kSaccadeFirst% := 0, kTargetFirst% := 1, 'burst toolbar buttons kReAnalyze := 16, kPrefOpen := 15, kPrefSave := 14, kJump := 13, kAccept := 12, kUndo := 11, kReject := 10, kEditData := 9, kEditSearch := 8, kAttributes := 7, kTarget := 6, kAuto := 5, kPSTH := 4, kEnd := 3, kNew := 2, kQuit := 1, kRatePositionDelay := 0.050, kRatePositionSampleDur := 0.100, kPriSaccadeRange := 0.300, kDot3 := 3, kDot5 := 5, kDialogRowHeight% := 10; 'global '------ var 'channels chUnit%, chSaccadeOnset%, chSaccadeOffset%, chBurstOnset%, chBurstOffset%, chTargetTime%, chTempSpd%, chUnitSmooth%, '1/5/06 formerly ch #11, ch1msBinEvent%, '1/5/06 formerly ch #14, chUnitEvent%, '1/5/06 formerly ch #10, chUnitWaveMark%, chKeyboard%, chEvents%, ' kCh2Analyze=3 <---update this as needed! chName$ [7+1], chHT% [7+1], ' 1 2 3 4 5 6 1 2 3 4 5 6 7 chVT% [7+1], 'AB CD EF GH IJ KL MN = HV-Eye1PriSac HV-Eye2PriSac HV-Vergence HV-future HV-Eye1SecondSac HV-Eye2SecondSac HV-Eye2SecondSac chHE% [7+1], 'AB CD EF GH IJ KL MN = HV-Gaze HV-Head HV-EyeInHead HV-future HV-Eye1SecondSac HV-HeadSecondSac HV-EyeInHeadSecondSac chVE% [7+1], chmHEvel% [7+1], chmVEvel% [7+1], chmAbsHEvel% [7+1], 'only need seven, request eight so I can use #1 #2 #3 #4 #5 #6 #7 and skip #0 chmAbsVEvel% [7+1], chmRecSumSacVel% [7+1], chmHEpeakVel% [7+1], chmVEpeakVel% [7+1], chmMarkerHEye% [7+1], chmMarkerVEye% [7+1], chmPSTHsaccadeOnset%, chmPSTHsaccadeOffset%, chmPSTHburstOnset%, chmPSTHburstOffset%, chmPSTHtargetTime%, chmInstantRate%, chmSpikeEventDeletable%, chmColoredEvent%, chmColoredPrePostBurstTemp%, chmMarkerSpd%, chmMarkerHTarget%, chmMarkerVTarget%, chmTargetDet%, gPalettePreviousColors[40][3], gPalettePreviousAssignments[40], gPalettePrefColors[40][3], gPalettePrefAssignments[40], gChanWeights[64+1], 'analysis marks ' kCh2Analyze=3 <---maintain this ! gSaccadeExist% [7+1], gHEsaccadeExist% [7+1], gVEsaccadeExist% [7+1], gHEonsetTime [7+1], 'Horz eye moved gHEoffsetTime [7+1], 'Horz eye stopped gVEonsetTime [7+1], 'Vert eye moved gVEoffsetTime [7+1], 'Vert eye stopped gHVonsetTime [7+1], gHVoffsetTime [7+1], gPeakHEvelTime [7+1], gPeakVEvelTime [7+1], gPeakHEvelocity [7+1], gPeakVEvelocity [7+1], gHEbegPos [7+1], gHEendPos [7+1], gHEamp [7+1], gHEDuration [7+1], gVEDuration [7+1], gVEbegPos [7+1], gVEendPos [7+1], gVEamp [7+1], gHEerror [7+1], gVEerror [7+1], gPolarError [7+1], gPolarRadius [7+1], gPolarTheta [7+1], gPeakPolarVel [7+1], gPeakPolarVelTime [7+1], gPolarVelPrePeakAccel[7+1], gPolarVelPostPeakAccel[7+1], gPreRateMeanHPos [7+1], gPreRateMeanVPos [7+1], gPostRateMeanHPos [7+1], gPostRateMeanVPos [7+1], gHGain [7+1], gVGain [7+1], gPolarGain [7+1], gStartSearch, gEarliestOnset, 'first HV eye movement gLatestOffset, 'last HV eye movement gSaccadeDuration, gTarget%, gTargetStepTime, gHTargetBegPos, gVTargetBegPos, gHTargetEndPos, gVTargetEndPos, gMeanPeakPolarVel, gTargetTheta, gTargetRadius, gHTargetStepAmp, gVTargetStepAmp, 'Adaptation/Corrective saccade attributes (very similar to analysis marks, combine someday?) zEarliestOnset, zLatestOffset, zSaccadeDuration, zTarget%, zTargetStepTime, zHTargetBegPos, zVTargetBegPos, zHTargetEndPos, zVTargetEndPos, zTargetTheta, zTargetRadius, zHTargetStepAmp, zVTargetStepAmp, 'zErrorInterval, gAutoAnalysis%, gEditMode%, gAppend%, gBurstAnalyzed%, gCursorZeroTime, gHEyePreTargetStepPos, gVEyePreTargetStepPos, gProgressView%, gEarlyTime, 'gEarlyTime is the left border of the display gLateTime, 'gLateTime is the right border of the display gWhereToStartAnalysis, 'can't be a preference gWhereToStopAnalysis, 'can't be a preference gPostOnsetSaveTime% := 100, '100ms of extra screen space stored gTimeToCheckEyeError := 0.045, 'means 0.045 s after saccade end gPrePSTHtime := 100, gPostPSTHtime := 700, gBurstSearchBegTime := 35, 'ms gBurstSearchEndTime := 35, 'ms 'views gViewData%, 'gViewData% is view handle for traces gViewAttr%, 'gViewAttr is the view handle for the attribute window gViewDetails%, 'handle for Analysis Details text window gViewSearch%, gScriptDir$, 'where the Saccade script resides gDataDir$, gPrefDir$, 'user definable variables pLogX1 := 80, 'Log window pLogY1 := 80, pLogX2 := 100, pLogY2 := 100, pDataX1 := 0, 'scrolling data window pDataY1 := 0, pDataX2 := 100, pDataY2 := 80, pAttrX1 := 0, 'attributes window pAttrY1 := 80, pAttrX2 := 50, pAttrY2 := 100, pDetailsX1 := 50, 'attributes window pDetailsY1 := 80, pDetailsX2 := 100, pDetailsY2 := 100, pScreenWidth%, pPreOnsetSaveTime := 0.750, 'amount of data saved to the output file (left edge of screen to saccade onset) pPostOnsetSaveTime := 0.750, 'amount of data saved to the output file (saccade onset to right edge of screen) pSigma := 10, '10 ms standard deviation Gaussian spike smoothing pOptimize := 1, 'whether to optimize the traces after every search pBumpAnalysis% := 0, 'use bump analysis or not pStartEndPercentThreshold := NaN, 'obsolete, not used but kept to hold the place in the preference file pStartPercentThreshold := 50, pEndPercentThreshold := 50, pDetectaSaccadeVelThreshold := 120, pDetectaHeadVelThreshold := 40, pPriPeakSaccadeThreshold := 40, pPriPeakHeadThreshold := 20, pHVonOffSaccadeThreshold := 20, pHVonOffHeadThreshold := 10, pTargetThreshold := 300, pMinTarget2EyeInterval := 0.050, pMaxTarget2EyeInterval := 0.600, pMaxPriSecInterval := 0.600, 'this is a fixed value now pMinAcceptedTargetSize := 2, pMaxAcceptedTargetSize := 18, pWriteTraces% := 1, 'write traces by default pSearchScheme% := kTargetFirst%, 'search for target then saccade pAdaptType%, pCellType% := kModeBurst%, pAnalysisType% := kNormalAnalysis%, pBurstPeakRangeMinus := 0.035, pBurstPeakRangePlus := 0.000, pUnitSmoothType% := 0, 'Neuron data attributes gBurstStartTime, gBurstEndTime, gBurstDuration, gBurstSpikeNumber%, gBurstMeanFreq, gBurstPeakTime, gBurstPeakFreq, gBurstMax5spikeAvgFreq, gBurstMax5spikeAvgFreqTime, gPreTonicNumSpk%, gPreTonicDuration, gPreTonicFreq, gPostTonicNumSpk%, gPostTonicDuration, gPostTonicFreq, gPreTonicStartTime, 'first pre-burst spike gPostTonicEndTime, 'last post-burst slike gPreRateNumSpk%, gPreRateDuration, gPreRateFreq, gPostRateNumSpk%, gPostRateDuration, gPostRateFreq, gPeakSpikeDensity, gPeakSpikeDensityTime, gBurstManuallyMarked%, gStartLevelThreshold, gEndLevelThreshold, gSpikeDensityStartTime, gSpikeDensityEndTime, gTrialAccepted%, gTrialFound%, gDatafilename$, gUnitData%, gAddDelTarget$, gDone%, gAttrNam$[512], 'Attribute names gAttrVal[50000][512], 'Attribute values for 50000 saccades and 512 parameters max (this can be changed) gAttrShow%[512]; 'set attribute number here (one more than last AttributeName index) gAttrShow%[1] := 1; 'Initialize which Array Variables to display on the screen, 1 = show gAttrShow%[17] := 1; gAttrShow%[18] := 1; gAttrShow%[56] := 1; gAttrShow%[57] := 1; gAttrShow%[60] := 1; gAttrShow%[39] := 1; gAttrShow%[75] := 1; gAttrShow%[93] := 1; 'screen channels chUnit% := 1; chHE%[1] := 2; 'primary saccades chVE%[1] := 3; chHT%[1] := 4; chVT%[1] := 5; 'chHE%[5] := 2; 'secondary saccades 'chVE%[5] := 3; 'chHT%[5] := 4; 'chVT%[5] := 5; 'del in Sactrack := 6; sactrack deletes H vel, saccade re-computes H vel and puts it into a memory channel 'del in Sactrack := 7; sactrack deletes V vel, saccade re-computes V vel and puts it into a memory channel chHT%[2] := 8; chVT%[2] := 9; chHE%[2] := 10; chVE%[2] := 11; ' := 12; ' := 13; ' := 14; ' := 15; ' := 16; chSaccadeOnset% := 17; chSaccadeOffset% := 18; chBurstOnset% := 19; chBurstOffset% := 20; chTargetTime% := 21; chTempSpd% := 22; ' := 23; ' := 24; ' := 25; ' := 26; ch1msBinEvent% := 27; '1/5/06 formerly ch #14, chUnitSmooth% := 28; '1/5/06 formerly ch #11, chUnitWaveMark% := 29; chUnitEvent% := 30; '1/5/06 formerly ch #10, chKeyboard% := 31; chEvents% := 32; '---------------------------------------------------- ' Main '< 3/10/04 '---------------------------------------------------- var gCheckFinished%, gResult1%, gResult2%; view(App()).Window(0,0,100,100); 'set maximum application size ToolbarVisible(1); 'Make toolbar visible always var a$; PaletteGetCurrent(gPalettePreviousColors, gPalettePreviousAssignments); PaletteSaccade(); gPrefDir$ := "C:/Documents and Settings/All Users/Desktop/"; 'get the current file path gScriptDir$ := View(App(3)).FileName$(2); ' gDataDir$ := View(App(3)).FileName$(2); 'default, assume data is in the script directory FilePathSet(gPrefDir$); 'aim at the desktop where preference files are saved arrConst(gChanWeights,1); PreferencesOpen%(kFalse); repeat gWhereToStartAnalysis := 0.7; gCursorZeroTime := gWhereToStartAnalysis; gEarlyTime := gWhereToStartAnalysis; gLateTime := gWhereToStartAnalysis; gStartSearch := gWhereToStartAnalysis; gLatestOffset := gWhereToStartAnalysis; gTargetStepTime := gWhereToStartAnalysis; zLatestOffset := gWhereToStartAnalysis; zTargetStepTime := gWhereToStartAnalysis; gWhereToStopAnalysis := 99999; 'no file is open at this point so a very big number is the best we can do, must be reset between files gStartSearch := 0; gTrialAccepted% := 0; gTrialFound% := 0; repeat gResult1% := Open%(); 'Open the file and prepare display if gResult1% < 0 then gResult2% := Query("\nNo file was opened. \n\nWhat do you to do next?\n", "Try Again", "Quit Saccade"); 'response=1, response=0 if gResult2% < 1 then halt; endif endif until gResult1% >= 0; FrontView(gViewData%); docase case pCellType% = kModeBehavior% then '4/3/06 why not move this to DialogAnalogChoices sets pCellType ? ? ? gUnitData% := 0; gCheckFinished% := Burst%(); case pCellType% = kModePause% then gUnitData% := 1; gCheckFinished% := Pause%(); case pCellType% = kModeBurst% then gUnitData% := 1; gCheckFinished% := Burst%(); endcase if pCellType% <> kModePause% then if gCheckFinished% = -1 then if gUnitData% = 1 then SavePSTHChan(); Save1msBinRaster(); Visual%(); endif WriteFileAttributes(); 'write the attributes first in case writing the traces fails if pWriteTraces% <> 0 then DialogSelectTraces(); 'write the traces the user selects endif CloseAllTheWindows(); ToolbarClear(); view(LogHandle()); WindowVisible(1); Window(pDetailsX1,pDetailsY1,pDetailsX2,pDetailsY2); 'Display it at the bottom of the screen Print(Str$(gTrialAccepted%) + " trials accepted from the " + Str$(gTrialFound%) + " trials found"); if pWriteTraces% then gDone% := Query("\nThe Attribute and Trace files were written. What do you want to do now?\n", "Quit Saccade", "Analyze Another File"); else gDone% := Query("\nThe Attribute file has been written. What do you want to do now?\n", "Quit Saccade", "Analyze Another File"); endif endif endif until gDone% = 1; 'Main '---------------------------------------------------- ' PaletteGetCurrent 'Read the current palette. '2/10/06 '---------------------------------------------------- proc PaletteGetCurrent(&aColors[][], &aAssignments[]) var i%,aRed,aGrn,aBlu; 'the palette of colors for i% := 0 to 39 do PaletteGet(i%,aRed,aGrn,aBlu); aColors[i%][0] := aRed; aColors[i%][1] := aGrn; aColors[i%][2] := aBlu; next 'the CED assigned traces, backgrounds, etc. for i% := 0 to 39 do 'range is 1-37 (trouble to do more?) aAssignments[i%] := Colour(i%); next end; 'PaletteGetCurrent '---------------------------------------------------- ' PaletteSetNew 'Restore the color palette after customizing it. '2/10/06 '---------------------------------------------------- proc PaletteSetNew(aColors[][], aAssignments[]) var i%,aRed,aGrn,aBlu; 'colors in the palette for i% := 0 to 39 do aRed := aColors[i%][0]; aGrn := aColors[i%][1]; aBlu := aColors[i%][2]; PaletteSet(i%,aRed,aGrn,aBlu); next 'colors assigned to special traces, backgrounds, etc. for i% := 0 to 39 do 'range is 1-37 (trouble to do more?) Colour(i%, aAssignments[i%]); next end; 'PaletteSetNew '---------------------------------------------------- ' PaletteSaccade 'These are the default color values for Saccade. 'The colors are grouped more logically than the CED 'default. This enables us to easily pick related 'colors for related traces. '2/8/06 '---------------------------------------------------- proc PaletteSaccade() 'The 40 palette colors for Saccade 'PaletteSet(0, 'palette positions 0-7 (6?) hold a grey scale and should not be changed. 'PaletteSet(1, 'PaletteSet(2, 'PaletteSet(3, 'PaletteSet(4, 'PaletteSet(5, 'PaletteSet(6, PaletteSet(7,0,0,0); 'black Red%,Green%,Blue% PaletteSet(8,66,0,0); 'crimson PaletteSet(9,100,0,0); 'bright red PaletteSet(10,100,50,50); 'rose PaletteSet(11,100,75,75); 'pink PaletteSet(12,0,37,0); 'dark green PaletteSet(13,0,50,0); 'green PaletteSet(14,0,255,0); 'bright green PaletteSet(15,50,100,50); 'minty green PaletteSet(16,0,0,50); 'navy PaletteSet(17,0,0,100); 'bright blue PaletteSet(18,50,50,100); 'dusty blue PaletteSet(19,75,75,100); 'baby blue PaletteSet(20,75,37,0); 'dark pumpkin PaletteSet(21,75,50,0); 'harvest gold PaletteSet(22,100,75,50); 'flesh PaletteSet(23,100,87,75); 'flesh PaletteSet(24,100,75,0); 'dark yellow PaletteSet(25,100,100,0); 'bright yellow PaletteSet(26,100,100,37); 'lighter yellow PaletteSet(27,100,100,75); 'even lighter yellow PaletteSet(28,75,0,75); 'dark purple PaletteSet(29,100,0,100); 'bright purple PaletteSet(30,100,50,100); PaletteSet(31,100,75,100); 'PaletteSet(32, 'what color should we make these? 'PaletteSet(33, 'PaletteSet(34, 'PaletteSet(35, 'PaletteSet(36, 'PaletteSet(37, 'PaletteSet(38, 'PaletteSet(39, 'The 40 items including background color 'Copied from CED default values Colour(0,-1); 'item, index to palette color Colour(1,3); Colour(2,8); Colour(3,0); Colour(4,0); Colour(5,0); Colour(6,0); Colour(7,17); Colour(8,0); Colour(9,0); Colour(10,7); Colour(11,29); Colour(12,6); Colour(13,0); Colour(14,0); Colour(15,16); Colour(16,7); Colour(17,29); Colour(18,0); Colour(19,17); Colour(20,14); Colour(21,15); Colour(22,9); Colour(23,17); Colour(24,18); Colour(25,31); Colour(26,8); Colour(27,0); Colour(28,0); Colour(29,0); Colour(30,4); Colour(31,0); Colour(32,6); Colour(33,4); Colour(34,10); Colour(35,16); Colour(36,6); Colour(37,6); Colour(38,-1); Colour(39,-1); end 'PaletteSaccade '---------------------------------------------------- ' CloseAllTheWindows '7/20/04 '---------------------------------------------------- proc CloseAllTheWindows() if ViewKind(gViewAttr%) >= 0 then View(gViewAttr%); FileClose(0,-1); 'close the log window endif if ViewKind(gViewDetails%) >= 0 then view(gViewDetails%); FileClose(0,-1); 'close the text window without asking endif if ViewKind(gViewSearch%) >= 0 then view(gViewSearch%); FileClose(0,-1); 'close the search details window without asking endif if ViewKind(gViewData%) >= 0 then View(gViewData%); FileClose(); 'close the traces window endif FileClose(-1); 'close remaining windows end; 'CloseAllTheWindows '---------------------------------------------------- ' DialogAnalysisChoices 'Sets the parameters that define what type of analysis 'needs to be done. These parameters CANNOT be changed 'during the analysis. '7/9/04 '---------------------------------------------------- proc DialogAnalysisChoices() var i%, aTab1 := 35, aRow := 1, aTab3, aPreOnsetMS, aPostOnsetMS; aTab3 := aTab1 + 13; aPreOnsetMS := pPreOnsetSaveTime*kMS; aPostOnsetMS := pPostOnsetSaveTime*kMS; View(gViewData%); DlgCreate("General Analysis Parameters"); if binsize(1) < 0.001 then DlgList(1, "Unit Firing Type","Behavior|Burst|Pause", 20, aTab1, aRow); else DlgList(1, "Unit Firing Type","Behavior", 20, aTab1, aRow); endif aRow := aRow + 1; DlgList(2, "Experiment Type","Non-Adapt|Non-Adapt+Corrective|Adapt", 20, aTab1, aRow); aRow := aRow + 1; aRow := aRow + 1; DlgList(3, "Analysis Type","Saccades (one eye)|Vergence (two eyes)|Gaze (head)", 20, aTab1, aRow); aRow := aRow + 1; DlgList(4, "Search Scheme","Saccade Then Target|Target Then Saccade", 20, aTab1, aRow); aRow := aRow + 1; DlgList(5, "Data Saved","Attributes Only|Attributes & Traces", 20, aTab1, aRow); aRow := aRow + 2; DlgInteger(6,"Data Saved Before Saccade Onset", 100, 2000, aTab1, aRow); DlgText("ms",aTab3,aRow); aRow := aRow + 1; DlgInteger(7,"Data Saved After Saccade Onset", 100, 2000, aTab1, aRow); DlgText("ms", aTab3, aRow); aRow := aRow + 1; for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next DlgButton(0,""); 'remove the CANCEL button DlgShow(pCellType%, pAdaptType%, pAnalysisType%, pSearchScheme%, pWriteTraces%, aPreOnsetMS, aPostOnsetMS); pScreenWidth% := aPreOnsetMS + aPostOnsetMS; pPreOnsetSaveTime := aPreOnsetMS / kMS; pPostOnsetSaveTime := aPostOnsetMS / kMS; docase case pAnalysisType% = kNormalAnalysis% then chName$[1] := "Primary Saccade"; chName$[2] := "unassigned channel"; chName$[3] := "unassigned channel"; chName$[4] := "unassigned channel"; chName$[5] := "Secondary Saccade"; chName$[6] := "unassigned channel"; chName$[7] := "unassigned channel"; case pAnalysisType% = kVergenceAnalysis% then chName$[1] := "Eye1 Primary Saccade"; chName$[2] := "Eye2 Primary Saccade"; chName$[3] := "Vergence Saccade"; chName$[4] := "unassigned channel"; chName$[5] := "Eye1 Secondary Saccade"; chName$[6] := "Eye2 Secondary Saccade"; chName$[7] := "Vergence Secondary Saccade"; case pAnalysisType% = kGazeAnalysis% then chName$[1] := "Gaze Primary Saccade"; chName$[2] := "Head Primary Saccade"; chName$[3] := "Eye in Head Saccade"; chName$[4] := "unassigned channel"; chName$[5] := "Gaze Secondary Saccade"; chName$[6] := "Head Secondary Saccade"; chName$[7] := "Eye in Head Secondary Saccade"; endcase end 'DialogAnalysisChoices '---------------------------------------------------- ' DialogSelectTonicDisplayAttributes ' 'Present all 512 attributes to the user, but spread them 'out over four dialog boxes. Only present those boxes 'that have at least one valid attribute name. ' '< 3/10/04 '---------------------------------------------------- func DialogSelectTonicDisplayAttributes%() const kColWidth% := 50, kColMax% := 2, kRowMax% := 25, '32, kBlockSize% := 50; '64; var ok%, aRow%, aCol%, i%, j%, aTab%, aStr$, aValid%, aTemp%[kBlockSize%], aItem% := 0, bItem% := 0, cItemNum% := 0, aBeg% := 0, aEnd% := kBlockSize%-1; 'for aPanel% := 1 to 4 do 'display checkboxes in four windows repeat aValid% := 0; aItem% := bItem%; cItemNum% := 0; ArrConst(aTemp%[],0); 'transfer block of attribute checkbox selections for j% := 0 to kBlockSize%-1 do aTemp%[j%] := gAttrShow%[j% + aBeg%]; next 'test if this block has any active attributes for i% := aBeg% to aEnd% do if gAttrNam$[i%] <> "" then 'attribute name empty? aValid% := 1; endif next 'only show blocks that have at least one active attribute if aValid% = 1 then DlgCreate("Choose attributes to monitor:", 0, 0, kColMax% * kColWidth%, 0); for aCol% := 1 to kColMax% do for aRow% := 1 to kRowMax% do docase case aCol% = 1 then aTab% := 0 * kColWidth%; case aCol% = 2 then aTab% := 1 * kColWidth%; case aCol% = 3 then aTab% := 2 * kColWidth%; case aCol% = 4 then aTab% := 3 * kColWidth%; endcase aStr$ := Str$(aItem%, 3) + " " + gAttrNam$[aItem%]; DlgCheck(cItemNum% + 1, aStr$, aTab%, aRow%); aItem% := aItem% + 1; cItemNum% := cItemNum% + 1; next; next; dlgButton(0,"uncheck all"); dlgButton(1,"next"); dlgButton(2,"prev"); ok% := DlgShow(aTemp%[]); if ok% = 0 then 'uncheck all boxes for j% := 0 to kMaxAttr% do gAttrShow%[j%] := 0; next endif if ok% = 1 then 'NEXT forward one set of attributes for j% := 0 to kBlockSize% - 1 do gAttrShow%[j% + aBeg%] := aTemp%[j%]; next bItem% := aItem%; aBeg% := aBeg% + kBlockSize%; 'advance to next block of attributes aEnd% := aEnd% + kBlockSize%; endif if ok% = 2 then 'LAST for j% := 0 to kBlockSize% - 1 do gAttrShow%[j% + aBeg%] := aTemp%[j%]; next if bItem% > 0 then 'don't go into negative numbers bItem% := bItem%- kBlockSize%; aBeg% := aBeg% - kBlockSize%; 'RESET back one set of attributes aEnd% := aEnd% - kBlockSize%; endif endif endif 'next; until aValid% <> 1; FrontView(gViewData%); return ok%; end 'DialogSelectTonicDisplayAttributes '---------------------------------------------------- ' DialogPSTHmidAnalysis 'Present a PSTH plot before the end of the analysis '7/20/04 '---------------------------------------------------- proc DialogPSTHmidAnalysis(); var aPSTHVisualView%, aLineUpTrace%, ok%, item1%, item2, aTitle$, aResult%, aRow%, aTab1% := 35, aTab2%; aTab2% := aTab1% + 13; aRow% := 1; dlgCreate("PSTH Plot"); dlgList(1, "Choose an attribute to line up on", "Target Step Time|Burst Onset|Burst Offset|Saccade Onset|Saccade Offset", 20, aTab1%, aRow%); aRow% := aRow% + 1; dlgReal(2, "Pre-trigger time", 0, 1000, aTab1%, aRow%); DlgText("ms", aTab2%, aRow%); aRow% := aRow% + 1; dlgReal(3, "Post-trigger time", 0, 1000, aTab1%, aRow%); DlgText("ms", aTab2%, aRow%); aRow% := aRow% + 1; DlgText("", aTab1%, aRow%); ok% := dlgShow(item1%, gPrePSTHtime, gPostPSTHtime); if ok% > 0 then 'cancel is available docase case item1% = 0 then aTitle$ := "Line-up on Target Step"; aLineUpTrace% := chmPSTHtargetTime%; case item1% = 1 then aLineUpTrace% := chmPSTHburstOnset%; aTitle$ := "Line-up on Burst Onset"; case item1% = 2 then aLineUpTrace% := chmPSTHburstOffset%; aTitle$ := "Line-up on Burst Offset"; case item1% = 3 then aLineUpTrace% := chmPSTHsaccadeOnset%; aTitle$ := "Line-up on Saccade Onset"; case item1% = 4 then aLineUpTrace% := chmPSTHsaccadeOffset%; aTitle$ := "Line-up on Saccade Offset"; endcase aTitle$ := aTitle$ + " through " + str$(gEarliestOnset) + " seconds"; FrontView(gViewData%); var a; a := gPrePSTHtime + gPostPSTHtime; aPSTHVisualView% := SetPsth(chmSpikeEventDeletable%, (gPrePSTHtime+gPostPSTHtime)*2/10, 0.005, gPrePSTHtime/1000, aLineUpTrace%, 2); Process(0, MaxTime(), 0, 1); View(aPSTHVisualView%); FrontView(aPSTHVisualView%); WindowVisible(1); 'make PSTH normal sized WindowTitle$(aTitle$); aResult% := DupChan(1,1); DrawMode(aResult%,9,2,16,0); 'make raster dots large endif end 'DialogPSTHmidAnalysis '---------------------------------------------------- ' DialogEditData 'Directs where to go for manual marking procedures '6/29/04 '---------------------------------------------------- func DialogEditData() FrontView(gViewData%); gEditMode% := 1; ManualTargetAnalysis(); ManualSaccadeAnalysis(); if pCellType% = kModeBurst% then ManualBurstModeAnalysis(); endif gEditMode% := 0; CursorOnsetOffset(); 'uses gEditMode% return kTrue; end 'DialogEditData '---------------------------------------------------- ' DialogSelectTraces 'Lets the user select which traces are written to the '*.MAT file for Graph to use. '3/29/06 '---------------------------------------------------- func DialogSelectTraces() const kMaxVertLines% := 38, 'maximum number of useable vertical lines in a dialog box kMaxDigCh% := 32, kNumVelCh% := 6; var i%, j%, tVar$, aRow%, aTab2% := 20, aResult%, accepted%, aNumOfChannels%, headerB$, version%, endian%, aDatfilename$, aFileNum%, aUnitFound%, cItemNum%[kMaxVertLines%], cTraceNum%[kMaxVertLines%], cTraceName$[kMaxVertLines%], cTraceUnit$[kMaxVertLines%], cTraceRes[kMaxVertLines%], cTraceType[kMaxVertLines%], aVelocities%[kNumVelCh%]; arrconst(cItemNum%[],0); 'copy velocity trace numbers to a contiguous array so we can loop through them aVelocities%[0] := chmHEvel%[1]; aVelocities%[1] := chmVEvel%[1]; aVelocities%[2] := chmHEvel%[2]; aVelocities%[3] := chmVEvel%[2]; aVelocities%[4] := chmHEvel%[3]; aVelocities%[5] := chmVEvel%[3]; DlgCreate("Output File Choices"); aRow% := 1; DlgLabel(aRow%, "Select the traces you want written to Graph's *.MAT file."); aRow% := aRow% + 1; View(gViewData%); 'present the normal digitized channels for i% := 1 to kMaxDigCh% do if chankind(i%) = 1 then '1=waveform channel DlgCheck(aRow%,chanTitle$(i%)); dlgText("channel " + str$(i%), aTab2%, aRow%); if i% = 1 then cTraceRes[aRow%-1] := 0.5; else cTraceRes[aRow%-1] := 1; endif cTraceType[aRow%-1] := 7; cItemNum%[aRow%-1] := 1; 'check the checkbox cTraceNum%[aRow%-1] := i%; 'record the trace number cTraceName$[aRow%-1] := chanTitle$(i%); 'record the trace title for j% := len(cTraceName$[aRow%-1])+1 to 29 do cTraceName$[aRow%-1] := cTraceName$[aRow%-1] + " "; 'pad the trace title to 29 char next cTraceUnit$[aRow%-1] := ChanUnits$(i%); 'record the trace units for j% := len(cTraceUnit$[aRow%-1])+1 to 10 do cTraceUnit$[aRow%-1] := cTraceUnit$[aRow%-1] + " "; 'pad the trace unit to 10 char next aRow% := aRow% + 1; endif next 'present the computed channels for i% := 0 to kNumVelCh%-1 do if chankind(aVelocities%[i%]) = 9 then '9=wavemark channel DlgCheck(aRow%,chanTitle$(aVelocities%[i%])); dlgText("memory channel", aTab2%, aRow%); cTraceRes[aRow%-1] := 1; cItemNum%[aRow%-1] := 1; 'check the checkbox cTraceType[aRow%-1] := 7; cTraceNum%[aRow%-1] := aVelocities%[i%]; 'record the trace number cTraceName$[aRow%-1] := chanTitle$(aVelocities%[i%]); 'record the trace title for j% := len(cTraceName$[aRow%-1])+1 to 29 do cTraceName$[aRow%-1] := cTraceName$[aRow%-1] + " "; 'pad the trace title to 29 char next cTraceUnit$[aRow%-1] := ChanUnits$(aVelocities%[i%]); 'record the trace units for j% := len(cTraceUnit$[aRow%-1])+1 to 10 do cTraceUnit$[aRow%-1] := cTraceUnit$[aRow%-1] + " "; 'pad the trace unit to 10 char next aRow% := aRow% + 1; endif next DlgButton(0,"No *.MAT file"); 'CANCEL button DlgButton(1,"Write selected traces"); 'OK button aResult% := DlgShow(cItemNum%); if aResult% = 1 then 'determine how many traces will be sent '-------------------------------------- aNumOfChannels% := 0; for i% := 1 to kMaxDigCh% do if cItemNum%[i%] = 1 then aNumOfChannels% := aNumOfChannels% + 1; endif next 'continue only if user has selected one or more traces to send to Graph '-------------------------------------- if aNumOfChannels% > 0 then var dTraceName$[aNumOfChannels%], dTraceUnit$[aNumOfChannels%], dTraceRes[aNumOfChannels%], dTraceType[aNumOfChannels%]; j% := 0; 'aNumOfChannels% := 0; for i% := 1 to kMaxDigCh% do if cItemNum%[i%] = 1 then dTraceName$[j%] := cTraceName$[i%]; 'copy trace title of accepted traces dTraceUnit$[j%] := cTraceUnit$[i%]; 'copy trace unit of accepted traces dTraceRes[j%] := cTraceRes[i%]; dTraceType[j%] := cTraceType[i%]; j% := j% + 1; endif next ' 'continue only if user has selected one or more traces to send to Graph ' '-------------------------------------- ' if aNumOfChannels% > 0 then '+ initialization for *.mat file headerB$ := "Matlab 5 mat-file created by spike2 "; version% := 0x0100; '0x0100, must be written as int16 endian% := 0x4d49; 'MI endian check 'start write the initial part of MAT file aDatfilename$ := Mid$(gDatafilename$,1,Len(gDatafilename$)-3) + "mat"; 'save with same name as data, but with mat extension aFileNum% := FileOpen(aDatfilename$,9,1); if aFileNum% < 0 then halt; endif View(aFileNum%); BWriteSize(124,headerB$); BWriteSize(2,version%); BWriteSize(2,endian%); '- initialization for *.mat file '+ write the analog traces aUnitFound% := 0; accepted% := 0; for i% := 1 to kMaxDigCh% do if cItemNum%[i%] = 1 then if cTraceNum%[i%] = 1 then 'this is the unit channel aUnitFound% := 1; else accepted% := accepted% + 1; if accepted% < 10 then tVar$ := "t0" + str$(accepted%); else tVar$ := "t" + str$(accepted%); endif 'write a non-unit trace WriteTrace(cTraceNum%[i%], tVar$, cTraceName$[i%], aFileNum%); endif endif next '- write the analog traces '+ write the unit trace, it has to be last if aUnitFound% = 1 then i% := 1; accepted% := accepted% + 1; if accepted% < 10 then tVar$ := "t0" + str$(accepted%); else tVar$ := "t" + str$(accepted%); endif WriteBlockUnit(tVar$, cTraceName$[i%], aFileNum%); '- write the unit trace, it has to be last '+ shuffle the unit names, labels and resolutions to the end of the arrays var aName$,aUnit$,aRes,aType; aName$ := dTraceName$[0]; aUnit$ := dTraceUnit$[0]; aRes := dTraceRes[0]; aType := dTraceType[0]; for i%:= 1 to aNumOfChannels% -1 do dTraceName$[i%-1] := dTraceName$[i%]; dTraceUnit$[i%-1] := dTraceUnit$[i%]; dTraceRes[i%-1] := dTraceRes[i%]; dTraceType[i%-1] := dTraceType[i%]; next dTraceName$[aNumOfChannels% -1] := aName$; dTraceUnit$[aNumOfChannels% -1] := aUnit$; dTraceRes[aNumOfChannels% -1] := aRes; dTraceType[aNumOfChannels% -1] := aType; endif '- shuffle the unit names, labels and resolutions to the end of the arrays '+ write the trace names WriteArrayOfStringsX1(aNumOfChannels%, "TraceNam", dTraceName$[], aFileNum%); '- write the trace names '+ write the trace units 'WriteArrayOfStringsX1(aNumOfChannels%, "TraceLbl", dTraceUnit$[], aFileNum%); WriteArrayOfStringsX1(aNumOfChannels%, "TraceLbl", dTraceName$[], aFileNum%); '- write the trace units '+ write the trace resolution WriteArrayofNumbersDimX2(aNumOfChannels%, "ResTypes", dTraceRes[], dTraceType[], aFileNum%); '- write the trace resolution View(aFileNum%); FileClose(); endif 'if aNumOfChannels% > 0 endif 'if aResult% = 1 return 1; end 'DialogSelectTraces '---------------------------------------------------- ' DialogDisplayParameters 'Sets some general analysis and appearance parameters. '9/15/06 '---------------------------------------------------- proc DialogDisplayParameters() var i%, aDataMargin := 0.7, aTab1 := 60, aTab2, aTab3 := 0, aTab4, aRow := 1, aItem% := 1, aDefault%, aResult%; ToolbarClear(); aTab2 := aTab1 + 13; aTab4 := aTab1 - 1; aRow := 1; DlgCreate("Display Parameters"); DlgButton(0,""); 'remove the CANCEL button DlgText("Optimize Y-Axis Scale of the Traces After Every Find ",aTab3,aRow); DlgCheck(aItem%,"", aTab4, aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgText("Reset Program Colors to the Saccade Default ",aTab3,aRow); DlgCheck(aItem%,"", aTab4, aRow); aRow := aRow + 2; aItem% := aItem% + 1; View(gViewData%); DlgReal(aItem%, "Start Analysis at", aDataMargin, MaxTime()-aDataMargin, aTab1, aRow); DlgText("sec",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%, "End Analysis at", aDataMargin, MaxTime()-aDataMargin, aTab1, aRow); DlgText("sec",aTab2,aRow); aRow := aRow + 2; aItem% := aItem% + 1; for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next aResult% := DlgShow( pOptimize, aDefault%, gWhereToStartAnalysis, gWhereToStopAnalysis); if aDefault% <> 0 then PaletteSaccade(); endif end 'DialogDisplayParameters '---------------------------------------------------- ' DialogSearchBehaviorParameters '9/15/06 '---------------------------------------------------- proc DialogSearchBehaviorParameters() var i%, aDataMargin := 0.7, aTab1 := 60, aTab2, aTab3 := 0, aTab4, aTab5, aRow := 1, aItem% := 1, aDefault%, aResult%,bResult%,cResult%; if pCellType% <> kModePause% then ToolbarClear(); aTab4 := aTab1 - 1; aRow := 1; DlgCreate("Behavior Search Parameters"); DlgButton(0,""); 'remove the CANCEL button if (pAnalysisType% = kGazeAnalysis%) then aTab5 := aTab1 + 15; aTab2 := aTab5 + 13; DlgText("Gaze and EIH",aTab1,aRow); DlgText("Head",aTab5,aRow); aRow := aRow + 1; DlgReal(aItem%,"HV RecSum Velocity movement detected using this Velocity Threshold",0,500, aTab1, aRow); aItem% := aItem% + 1; DlgReal(aItem%,"",0,500, aTab5, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"H or V component must exceed this Peak Velocity Threshold",0,100, aTab1, aRow); aItem% := aItem% + 1; DlgReal(aItem%,"",0,500, aTab5, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Onset/Offset marked using this Velocity Threshold",0,300, aTab1, aRow); aItem% := aItem% + 1; DlgReal(aItem%,"",0,500, aTab5, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 2; aItem% := aItem% + 1; DlgText("Mark 'Bumps' when present",aTab3,aRow); DlgCheck(aItem%,"", aTab4, aRow); aRow := aRow + 2; aItem% := aItem% + 1; for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next aResult% := DlgShow( pDetectaSaccadeVelThreshold, pDetectaHeadVelThreshold, pPriPeakSaccadeThreshold, pPriPeakHeadThreshold, pHVonOffSaccadeThreshold, pHVonOffHeadThreshold, pBumpAnalysis%); else aTab2 := aTab1 + 13; DlgText("Eye",aTab1,aRow); aRow := aRow + 1; DlgReal(aItem%,"HV RecSum Velocity movement detected using this Velocity Threshold",0,500, aTab1, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"H or V component must exceed this Peak Velocity Threshold",0,100, aTab1, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Onset/Offset marked using this Velocity Threshold",0,300, aTab1, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 2; aItem% := aItem% + 1; DlgText("Mark 'Bumps' when present",aTab3,aRow); DlgCheck(aItem%,"", aTab4, aRow); aRow := aRow + 2; aItem% := aItem% + 1; for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next aResult% := DlgShow( pDetectaSaccadeVelThreshold, pPriPeakSaccadeThreshold, pHVonOffSaccadeThreshold, pBumpAnalysis%); endif endif 'if pCellType% <> kModePause% end 'DialogSearchBehaviorParameters '---------------------------------------------------- ' DialogTargetSearchParameters '9/15/06 '---------------------------------------------------- proc DialogTargetSearchParameters() var i%, aTab1 := 60, aTab2, aRow := 1, aItem% := 1, aResult%, aStr$; if pCellType% <> kModePause% then ToolbarClear(); aTab2 := aTab1 + 13; aRow := 1; if (pAnalysisType% = kGazeAnalysis%) then aStr$ := "Gaze"; else aStr$ := "Saccade"; endif; DlgCreate("Target Search Parameters"); DlgButton(0,""); 'remove the CANCEL button DlgReal(aItem%,"Target Detection Threshold",100,500, aTab1, aRow); DlgText("d/s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Shortest Target to Eye Latency (negative value if target trails eye)",-0.500,0.500, aTab1, aRow); DlgText("s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Longest Target to Eye Latency (negative value if target trails eye)",-1.0,1.0, aTab1, aRow); DlgText("s",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; if pAdaptType% = 0 or pAdaptType% = 1 then 'pAdaptType% = 0 --- non-adapt step experiments pAdaptType% = 1 --- Non-Adapt with Corrective Saccades Trials for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next aResult% := DlgShow( pTargetThreshold, pMinTarget2EyeInterval, pMaxTarget2EyeInterval); else 'pAdaptType% = 2 --- adapt experiements 'aRow := aRow + 1; 'aItem% := aItem% + 1; DlgReal(aItem%,"Abs Min Detected Primary Target Amp",1,100, aTab1, aRow); DlgText("deg",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Abs Max Detected Primary Target Amp",1,100, aTab1, aRow); DlgText("deg",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next aResult% := DlgShow( pTargetThreshold, pMinTarget2EyeInterval, pMaxTarget2EyeInterval, pMinAcceptedTargetSize, pMaxAcceptedTargetSize); endif endif end 'DialogTargetSearchParameters '---------------------------------------------------- ' DialogSearchParameters 'Set the parameters that are used to find trial events. 'The dialogbox can be re-entered while the program is 'running. '3/26/04 '---------------------------------------------------- func DialogSearchParameters() var aResult%,bResult%,cResult%, aDefault%; DialogDisplayParameters(); DialogSearchBehaviorParameters(); DialogTargetSearchParameters(); if pCellType% = kModeBurst% then 'gUnitData% is not set yet, it is done in... bResult% := DialogSearchUnitParameters(); endif cResult% := 1; if(gTrialFound% > 0) and (gAppend% = kFalse) then cResult% := DialogReAnalyze(); endif if aDefault% <> 0 then PaletteSaccade(); endif PreferencesSave%(kFalse); return cResult%; end 'DialogSearchParameters '---------------------------------------------------- ' DialogUndoTrial 'Queries the user if they want to undo a trial. '4/4/06 '---------------------------------------------------- func DialogUndoTrial(aReal) var aResult%; DlgCreate("Undo a Trial"); DlgText("Delete everything saved from the trial at " + str$(aReal) + " seconds?",0,1); DlgText(" ",0,2); DlgButton(0, "Cancel"); DlgButton(1, "Delete"); aResult% := DlgShow( ); return aResult%; end 'DialogUndoTrial '---------------------------------------------------- ' DialogReAnalyze 'Offers the user a chance to reanalyze the current 'trial with the new parameters or use the parameters 'on the next trial. '4/4/06 '---------------------------------------------------- func DialogReAnalyze() var aResult%; DlgCreate("Apply the Search Parameters"); DlgText("Do you want to RE-ANALYZE the current trial with the new parameters or just SAVE them for the trials that follow? ",1,1); DlgText(" ",2,1); DlgButton(0, "Cancel"); DlgButton(1, "Save"); DlgButton(2, "Re-analyze"); aResult% := DlgShow( ); return aResult%; end 'DialogReAnalyze '---------------------------------------------------- ' DialogSearchUnitParameters 'Set the parameters that are used to locate unit 'events. The dialogbox can be re-entered while the 'program is running. '3/26/04 '---------------------------------------------------- func DialogSearchUnitParameters() var i%, aTab1, aTab2, aTab4, aRow, aItem%, aResult%; aTab1 := 60; aTab2 := aTab1 + 13; aTab4 := aTab1 - 1; aRow := 1; aItem% := 1; DlgCreate("Unit Search Parameters"); DlgButton(0,""); 'remove the CANCEL button DlgList(aItem%, "Unit Smoothing Type","Fixed Width Gaussian|Adaptive Width Gaussian", 20, aTab1, aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Gaussian Standard Deviation",1,50, aTab1, aRow); DlgText("ms",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Percent of Peak Gaussian SD that Defines Begin of Burst",10,90, aTab1, aRow); '"Spike Density from Peak:" DlgText("%",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%,"Percent of Peak Gaussian SD that Defines End of Burst",10,90, aTab1, aRow); '"Spike Density from Peak:" DlgText("%",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%, "Earliest burst peak is saccade onset minus", 0, 0.500, aTab1, aRow); DlgText("sec",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; DlgReal(aItem%, "Latest burst peak is saccade offset plus", 0, 0.500, aTab1, aRow); DlgText("sec",aTab2,aRow); aRow := aRow + 1; aItem% := aItem% + 1; for i% := aRow to kDialogRowHeight% do DlgText("", aTab1, aRow); aRow := aRow + 1; next aResult% := DlgShow(pUnitSmoothType%, pSigma, pStartPercentThreshold, pEndPercentThreshold, pBurstPeakRangeMinus, pBurstPeakRangePlus); return aResult%; end 'DialogSearchUnitParameters '---------------------------------------------------- ' Pause '< 3/10/04 '---------------------------------------------------- func Pause%() message("The Pause analysis has not been implemented yet."); return -1; end 'Pause '---------------------------------------------------- ' Burst 'Eventually this will analyze the following cell types: ' Behavior ' Burst ' BurstTonic ' Visuomotor '< 3/10/04 '---------------------------------------------------- func Burst%(); const kRemove$ := "RemoveTarget", kRestore$ := "RestoreTarget"; var aMsg$:= "", aButtonResult%, dummy% := 0, 'for repeat loop, dummy% is never incremented! a, i%, aResult%, aLineUpTrace%, ok%, item1%, aTitle$, aResponse%, aSearchAgain%; AttributeName(); gAutoAnalysis% := 0; gEditMode% := 0; gCursorZeroTime := gWhereToStartAnalysis; 'start the analysis where the user indicates ShowAnalysisDetails(0); 'show it at least once for the automatic aSearchAgain% := kTrue; repeat if aSearchAgain% = kTrue then docase case aButtonResult% = kUndo then gStartSearch := gCursorZeroTime; case aButtonResult% = kReAnalyze then gStartSearch := gStartSearch; 're-use the last gStartSearch 'gCursorZeroTime; 'move back in time a bit to reanalyze else gStartSearch := GetLatestMarkedTime(); 'prepare to find NEXT trial endcase '2/2/06 initialize eye, target and burst variables here ResetEarliestLatest(); ResetGaussian(); ResetPreBurst(); ResetPostBurst(); ResetAdaptTarget(); if gAutoAnalysis% = 0 then view(gViewSearch%); EditSelectAll(); 'Select all text in search view EditClear(); endif 'Find the next valid saccade if pSearchScheme% = kSaccadeFirst% then if DetectSaccadeThenTarget() < 0 then 'find the saccade first return -1; 'hit the end of the file endif else if DetectTargetThenSaccade() < 0 then 'find the target first return -1; 'hit the end of the file endif endif endif 'if aSearchAgain% = kTrue then aSearchAgain% := kTrue; 'abc call MetricsSaccade(aTrace%) here remove from HighlightComputeAndMark if gAutoAnalysis% = 1 then aButtonResult% := kAccept; 'AUTOMATIC ANALYSIS HighlightComputeAndMark(); 'process what the computer has found else repeat HighlightComputeAndMark(); 'process what the computer has found ShowAnalysisDetails(1); gAddDelTarget$ := kRemove$; aButtonResult% := Interact(aMsg$,1023,0, "QuitProgram","OpenNewFile","FinalizeThisAnalysis", "show PSTH","AutoAnalysis",gAddDelTarget$,"ChooseAttribs","EditSearch","&EditData", "&Reject","&UndoLast","&Accept","&Jump", "PrefSave","PrefOpen"); FrontView(gViewData%); if aButtonResult% = kQuit then 'QUIT PROGRAM aResponse% := query("\nQuit Saccade now and your current analysis will not be saved.\n", "Quit", "Cancel"); if aResponse% = 1 then 'be sure the user really wants to quit PreferencesSave%(kFalse); CloseAllTheWindows(); PaletteSetNew(gPalettePreviousColors,gPalettePreviousAssignments); Halt; endif endif if aButtonResult% = kNew then 'OPEN A NEW FILE aResponse% := query("\nOpen a new file now and your current analysis will not be saved.\n", "Open a New File", "Cancel"); if aResponse% = 1 then 'be sure the user really wants to quit CloseAllTheWindows(); return kNew; endif endif if aButtonResult% = kEnd then 'END ANALYSIS return -1; endif if aButtonResult% = kPSTH then DialogPSTHmidAnalysis(); endif if aButtonResult% = kAuto then 'AUTO ANALYSIS gAutoAnalysis% := 1; 'automatcally accept aButtonResult% := kAccept; 'this trial and all that follow endif if aButtonResult% = kTarget then 'NO TARGET if gAddDelTarget$ = kRemove$ then gAddDelTarget$ := kRestore$; MemDeleteTime(chmMarkerHTarget%,3,gEarlyTime,gLateTime); MemDeleteTime(chmMarkerVTarget%,3,gEarlyTime,gLateTime); gTarget% := 0; gTargetStepTime := NaN; HighlightComputeAndMark(); else gAddDelTarget$ := kRemove$; if gCursorZeroTime < 0.601 then DetectaTarget(gCursorZeroTime,0,pTargetThreshold,gTargetStepTime,gTarget%); else 'jump back 0.050 to miss an adapt target step if one is present DetectaTarget(gCursorZeroTime-pMinTarget2EyeInterval, gCursorZeroTime-pMaxTarget2EyeInterval, pTargetThreshold,gTargetStepTime,gTarget%); 'Search backward endif HighlightComputeAndMark(); endif endif if aButtonResult% = kAttributes then 'CHOOSE ATTRIBUTES DialogSelectTonicDisplayAttributes%(); AttributeComputeAndShow(); endif if aButtonResult% = kPrefOpen then 'open parameters PreferencesOpen%(kTrue); aSearchAgain% := kFalse; endif if aButtonResult% = kPrefSave then 'save parameters PreferencesSave%(kTrue); aSearchAgain% := kFalse; endif if aButtonResult% = kUndo then 'UNDO if gTrialAccepted%-1 >= 0 then aResult% := DialogUndoTrial(gAttrVal[gTrialAccepted%-1][22]); if aResult% = 0 then aButtonResult% := 0; 'cancel the UNDO endif else aButtonResult% := 0; 'cancel the UNDO endif endif if aButtonResult% = kEditSearch then 'SET SEARCH PARAMETERS aResult% := DialogSearchParameters(); if aResult% = 2 then 'choice2: optionally re-edit trial on screen 'search the same region with the new parameters gCursorZeroTime := gTargetStepTime - 0.100; '4/18/05 reposition the start point slightly before the beginning of the current ---> gAttrVal[gTrialAccepted%][00] := gTargetStepTime; DeleteMarks(); 'DeleteCursors? aButtonResult% := kReAnalyze; 'if pSearchScheme% = kSaccadeFirst% then ' if DetectSaccadeThenTarget() < 0 then 'find the saccade first ' return -1; 'hit the end of the file ' endif 'else ' if DetectTargetThenSaccade() < 0 then 'find the target first ' return -1; 'hit the end of the file ' endif 'endif 'HighlightComputeAndMark(); '4/18/05, process a trial endif endif if aButtonResult% = kEditData then 'EDIT DATA, spikes or highlights DialogEditData(); endif until (aButtonResult% >= kReject) 'until accept or reject endif 'if gAutoAnalysis% = 1 docase case aButtonResult% = kAccept then 'ACCEPT View(gViewData%); AttributeComputeAndShow(); HighlightSaccadeAndBurstForPSTH(); gTrialAccepted% := gTrialAccepted% + 1; case aButtonResult% = kUndo then 'UNDO View(gViewData%); if gTrialAccepted%-1 >= 0 then gCursorZeroTime := gAttrVal[gTrialAccepted%-1][39]; 'relocate to where the last accepted trial was by using the left side of screen attribute for i% := 0 to kMaxAttr% do gAttrVal[gTrialAccepted%][i%] := 0; 'reset all the attributes from the currently DISPLAYED trial gAttrVal[gTrialAccepted%-1][i%] := 0; 'reset all the attributes from the most recently SAVED trial next gTrialAccepted% := gTrialAccepted% - 1; 'aim at previous set of attributes, prepare to write over them gTrialFound% := gTrialFound% - 2; if gTrialAccepted% < 0 then gTrialAccepted% := 0; 'don't go past the very beginning gTrialFound% := 0; gCursorZeroTime := 0; endif endif case aButtonResult% = kReject then 'REJECT case aButtonResult% = kJump then 'JUMP gCursorZeroTime := Input("Jump ahead to what time?", gCursorZeroTime , 0, MaxTime()); 'no lower than curren tlocation 'jump ahead and move to the next event endcase until dummy% = 1; 'this never gets incremented return gTrialAccepted%; 'control never gets this far end 'Burst '---------------------------------------------------- ' GetLatestMarkedTime ' 3/18/06 '---------------------------------------------------- func GetLatestMarkedTime() var aTime; aTime := gCursorZeroTime; 'the default value if gStartSearch <> NaN then aTime := max(aTime,gStartSearch); endif if gLatestOffset <> NaN then aTime := max(aTime,gLatestOffset); endif if gTargetStepTime <> NaN then aTime := max(aTime,gTargetStepTime); endif if zLatestOffset <> NaN then aTime := max(aTime,zLatestOffset); endif if zTargetStepTime <> NaN then aTime := max(aTime,zTargetStepTime); endif ' gStartSearch := gStartSearch + 1.000; 'this keeps the search mark moving ahead return aTime; end 'GetLatestMarkedTime '---------------------------------------------------- ' ResetEarliestLatest ' 2/3/06 '---------------------------------------------------- proc ResetEarliestLatest() var aTrace%; gTarget% := 0; gEarliestOnset := NaN; gLatestOffset := NaN; gSaccadeDuration := NaN; gTargetStepTime := NaN; gHTargetBegPos := NaN; gVTargetBegPos := NaN; gHTargetEndPos := NaN; gVTargetEndPos := NaN; gMeanPeakPolarVel := NaN; gTargetTheta := NaN; gTargetRadius := NaN; gHTargetStepAmp := NaN; gVTargetStepAmp := NaN; gHEyePreTargetStepPos := NaN; gVEyePreTargetStepPos := NaN; zTarget% := 0; zEarliestOnset := NaN; zLatestOffset := NaN; zSaccadeDuration := NaN; zTargetStepTime := NaN; zHTargetBegPos := NaN; zVTargetBegPos := NaN; zHTargetEndPos := NaN; zVTargetEndPos := NaN; zTargetTheta := NaN; zTargetRadius := NaN; zHTargetStepAmp := NaN; zVTargetStepAmp := NaN; for aTrace% := 0 to 6 do gSaccadeExist% [aTrace%] := 0; gHEsaccadeExist% [aTrace%] := 0; gVEsaccadeExist% [aTrace%] := 0; gHEonsetTime [aTrace%] := NaN; gHEoffsetTime [aTrace%] := NaN; gVEonsetTime [aTrace%] := NaN; gVEoffsetTime [aTrace%] := NaN; gHVonsetTime [aTrace%] := NaN; gHVoffsetTime [aTrace%] := NaN; gPeakHEvelTime [aTrace%] := NaN; gPeakVEvelTime [aTrace%] := NaN; gPeakHEvelocity [aTrace%] := NaN; gPeakVEvelocity [aTrace%] := NaN; gHEbegPos [aTrace%] := NaN; gHEendPos [aTrace%] := NaN; gHEamp [aTrace%] := NaN; gHEDuration [aTrace%] := NaN; gVEDuration [aTrace%] := NaN; gVEbegPos [aTrace%] := NaN; gVEendPos [aTrace%] := NaN; gVEamp [aTrace%] := NaN; gHEerror [aTrace%] := NaN; gVEerror [aTrace%] := NaN; gPolarError [aTrace%] := NaN; gPolarRadius [aTrace%] := NaN; gPolarTheta [aTrace%] := NaN; gPeakPolarVel [aTrace%] := NaN; gPeakPolarVelTime [aTrace%] := NaN; gPolarVelPrePeakAccel[aTrace%] := NaN; gPolarVelPostPeakAccel[aTrace%] := NaN; gPreRateMeanHPos [aTrace%] := NaN; gPreRateMeanVPos [aTrace%] := NaN; gPostRateMeanHPos [aTrace%] := NaN; gPostRateMeanVPos [aTrace%] := NaN; gHGain [aTrace%] := NaN; gVGain [aTrace%] := NaN; gPolarGain [aTrace%] := NaN; next end 'ResetEarliestLatest '---------------------------------------------------- ' ResetAdaptTarget '3/17/04 '---------------------------------------------------- proc ResetAdaptTarget() zTargetStepTime := NaN; zHTargetBegPos := NaN; zVTargetBegPos := NaN; zHTargetEndPos := NaN; zVTargetEndPos := NaN; zHTargetStepAmp := NaN; zVTargetStepAmp := NaN; zTargetTheta := NaN; zTargetRadius := NaN; end 'ResetAdaptTarget '---------------------------------------------------- ' ResetGaussian '3/17/04 '---------------------------------------------------- proc ResetGaussian() gBurstAnalyzed% := kFalse; ' gBurstSpikeNumber% := 0; ' gBurstStartTime := NaN; ' gBurstEndTime := NaN; ' gBurstDuration := NaN; ResetBurst(); gBurstMax5spikeAvgFreq := NaN; gBurstMax5spikeAvgFreqTime := NaN; gBurstPeakFreq := NaN; gBurstPeakTime := NaN; gBurstMeanFreq := NaN; gPeakSpikeDensityTime := NaN; gPeakSpikeDensity := NaN; gSpikeDensityStartTime := NaN; gSpikeDensityEndTime := NaN; end 'ResetGaussian '---------------------------------------------------- ' ResetBurst ' 2/16/05 '---------------------------------------------------- proc ResetBurst() gBurstSpikeNumber% := 0; gBurstStartTime := NaN; gBurstEndTime := NaN; gBurstDuration := NaN; end 'ResetBurst '---------------------------------------------------- ' ResetPreBurst '< 3/10/04 '---------------------------------------------------- proc ResetPreBurst() gPreTonicNumSpk% := 0; 'there is no burst gPreTonicStartTime := NaN; gPreTonicDuration := NaN; gPreTonicFreq := NaN; end 'ResetPreBurst '---------------------------------------------------- ' ResetPostBurst '< 3/10/04 '---------------------------------------------------- proc ResetPostBurst() gPostTonicNumSpk% := 0; gPostTonicEndTime := NaN; gPostTonicDuration := NaN; gPostTonicFreq := NaN; end 'ResetPostBurst '---------------------------------------------------- ' ResetPostRate ' 2/16/05 '---------------------------------------------------- proc ResetPostRate() gPostRateNumSpk% := 0; gPostRateDuration := NaN; gPostRateFreq := NaN; gPostRateMeanHPos[1] := NaN; gPostRateMeanVPos[1] := NaN; end 'ResetPostRate '---------------------------------------------------- ' ResetPreRate ' 2/16/05 '---------------------------------------------------- proc ResetPreRate() gPreRateNumSpk% := 0; gPreRateDuration := NaN; gPreRateFreq := NaN; gPreRateMeanHPos[1] := NaN; gPreRateMeanVPos[1] := NaN; end 'ResetPreRate '---------------------------------------------------- ' HighlightComputeAndMark 'Positions the highlight marks so further analysis 'can take place. '3/24/04 '---------------------------------------------------- func HighlightComputeAndMark() var i%; DeleteMarks(); MetricsTarget(gTarget%,gTargetStepTime,gHTargetBegPos,gVTargetBegPos,gHTargetEndPos,gVTargetEndPos,gHTargetStepAmp,gVTargetStepAmp,gTargetTheta,gTargetRadius); MetricsEyeAroundTarget(); for i% := 1 to kCh2Analyze do '3 do if gSaccadeExist%[i%] > 0 then MetricsSaccade(i%); endif next MetricsSecSaccade(1,5); MetricsSecSaccade(2,6); ComputeScreenWidth(); if gUnitData% = 1 then if pCellType% = kModeBurst% then if gBurstAnalyzed% = kFalse then 'only seach spike regions the first time through for each trial MetricsBurstAutoGaussian(); MetricsBurstAutoPrePost(); endif endif HighlightSaccadeAndBurstForPSTH(); endif AttributeComputeAndShow(); HighlightPrimary(); if pAdaptType% > 0 then HighlightSecondary(); endif if gUnitData% = 1 then HighlightBurst(); endif gBurstAnalyzed% := kTrue; CursorOnsetOffset(); end 'HighlightComputeAndMark '---------------------------------------------------- ' Open 'Open the file and prepare traces '< 3/10/04 '---------------------------------------------------- func Open%(); const kFixedUnitSmooth% := 0, kAdaptiveUnitSmooth% := 1; var i%,j%, aRow% := -1, '-1 = no previous trials loaded from *.txt file aResult%, aTextFile%, a$,b$,c$, aStr$, bStr$, aInt%, aBigStr$, temp$[kMaxAttr%+2], aWhere, bWhere, aMore,aSubStr$, aLength, aPrevAnalysis$, aBinSizeData, aBinSizeUnit; gAppend% := kFalse; FilePathSet(gDataDir$); 'FilePathSet(gScriptDir$); gViewData% := FileOpen("",0,1,"Select a file to analyze"); gDataDir$ := filePath$(); WindowVisible(0); if gViewData% < 0 then return gViewData%; else View(LogHandle()); 'Make log view the current view EditSelectAll(); 'Select all text in log view EditClear(); 'Delete it Window(pLogX1,pLogY1,pLogX2,pLogY2); 'Display it at the bottom of the screen View(gViewData%); aBinSizeData := BinSize(chHE%[1]); 'all the analog traces and the unit smooth trace too aBinSizeUnit := BinSize(chUnit%); gDatafilename$ := FileName$(); Window(pDataX1,pDataY1,pDataX2,pDataY2); XRange(0,1); gViewAttr% := FileNew(1,1); WindowTitle$("Attributes"); Window(pAttrX1,pAttrY1,pAttrX2,pAttrY2); gViewDetails% := FileNew(1,1); WindowTitle$("Analysis Details"); Window(pDetailsX1,pDetailsY1,pDetailsX2,pDetailsY2); 'determine what the *.txt name would be aLength := Len(gDatafilename$); aPrevAnalysis$ := Left$(gDatafilename$, aLength - 3); aPrevAnalysis$ := aPrevAnalysis$ + "txt"; gViewSearch% := FileNew(1,1); 'for reporting saccade finding parameters WindowTitle$("Search Details"); Window(0,0,25,80); 'see if it exists aTextFile% := FileOpen(aPrevAnalysis$, 8, 0); 'open the previous attribute file if aTextFile% < 0 then DialogAnalysisChoices(); 'working with a new file, Can't change parameters after they are set aResult% := TraceCheck(); if aResult% < 0 then return -1 endif else 'aTextFile% := Query("A previous analysis session has been found for this data file.", "Append It", "Overwrite It"); 'query if user wants to RESUME DlgCreate("Old File Found"); DlgText("This file was analyzed before. What do you want to do?",1,1); DlgButton(0, "Cancel"); 'Cancel = 0 Append = 1 Overwrite = 2 DlgButton(1, "Append File"); 'Cancel = 0 Append = 1 Overwrite = 2 DlgButton(2, "Overwrite File"); 'Cancel = 0 Append = 1 Overwrite = 2 aResult% := DlgShow(); docase case aResult% = 0 then 'cancel aResult% := FileClose(-1); 'close current file return -1; case aResult% = 2 then 'overwrite view(aTextFile%); aResult% := FileClose(); 'close current file DialogAnalysisChoices(); 'working with a new file, Can't change parameters after they are set aResult%:= TraceCheck(); if aResult% < 0 then return -1 endif case aResult% = 1 then 'append, 'more accurately, re-load old values and carry on gAppend% := kTrue; aResult% := TraceCheck(); 'make sure no traces have been deleted if aResult% < 0 then return -1 endif 'Read the row of attribute names '------------------------------- view(aTextFile%); aResult% := Read(aBigStr$); aWhere := instr(aBigStr$,"\n"); 'is there a CR if aWhere > 0 then aBigStr$ := delstr$(aBigStr$,aWhere,1); 'lop off the CR, it can only be at the end endif aBigStr$ := aBigStr$ + "\t"; 'place a tab at the end so last str will be handled properly aMore := 0; i% := -1; 'separate sub-strings repeat aWhere := instr(aBigStr$,"\t"); 'find the next tab (end of next str) aSubStr$ := left$(aBigStr$,aWhere); 'copy the first string of interest aBigStr$ := delstr$(aBigStr$,1,aWhere); 'delete the area copied out aMore := len(aBigStr$); 'how much is left bWhere := instr(aSubStr$,"\t"); aSubStr$ := delstr$(aSubStr$,bWhere,1); 'remove the tab at the end of the copy i% := i% + 1; 'prepare to save it temp$[i%] := aSubStr$; 'save it until aMore < 1; 'save some of the sub-strings for i% := 0 to kMaxAttr% do gAttrNam$[i%] := temp$[i%+1]; 'transfer names without the "Trace Number" label (first one) next 'Read the rows of attribute values '--------------------------------- repeat aResult% := Read(aBigStr$); if aResult% > 0 then aRow% := aRow% + 1; aWhere := instr(aBigStr$,"\n"); 'is there a CR if aWhere > 0 then aBigStr$ := delstr$(aBigStr$,aWhere,1); 'lop off the CR, it can only be at the end endif aBigStr$ := aBigStr$ + "\t"; 'place a tab at the end so last str will be handled properly aMore := 0; i% := -1; repeat aWhere := instr(aBigStr$,"\t"); 'find the next tab (end of next str) aSubStr$ := left$(aBigStr$,aWhere); 'copy the first string of interest aBigStr$ := delstr$(aBigStr$,1,aWhere); 'delete the area copied out aMore := len(aBigStr$); 'how much is left bWhere := instr(aSubStr$,"\t"); aSubStr$ := delstr$(aSubStr$,bWhere,1); 'remove the tab at the end of the copy i% := i% + 1; 'prepare to save it if aSubStr$ = chr$(0) then aSubStr$ := print$("%7d",NaN); 'str$() can't handle 9999999, substitute empty cells with the text representation of NaN endif temp$[i%]:= aSubStr$; 'save it until aMore < 1; for i% := 0 to kMaxAttr% do gAttrVal[aRow%][i%] := val(temp$[i%+1]); 'transfer all the values except the "Trace Number" (first one) next if gAttrVal[aRow%][19] > 0 then gUnitData% := 1; 'a boilerplate method to set whether spikes are being analyzed endif endif until aResult% < 1; aInt% := gAttrVal[aRow%][121]; pAnalysisType% := aInt%/10000; aInt% := aInt%-pAnalysisType%*10000; pWriteTraces% := aInt%/1000; aInt% := aInt%-pWriteTraces%*1000; pSearchScheme% := aInt%/100; aInt% := aInt%-pSearchScheme%*100; pAdaptType% := aInt%/10; aInt% := aInt%-pAdaptType%*10; pCellType% := aInt%; 'pAnalysisType%*10000 + pWriteTraces%*1000 + pSearchScheme%*100 + pAdaptType%*10 + pCellType%; gWhereToStopAnalysis := gAttrVal[aRow%][122]; pPreOnsetSaveTime := gAttrVal[aRow%][22] - gAttrVal[aRow%][39]; pPostOnsetSaveTime := gAttrVal[aRow%][61] - gAttrVal[aRow%][22]; 'gWhereToStartAnalysis := gAttrVal[aRow%][22]; 'absolute saccade onset gWhereToStartAnalysis := gAttrVal[aRow%][61]; 'right edge of screen gCursorZeroTime := gAttrVal[aRow%][61]; gTrialAccepted% := aRow%+1; gTrialFound% := aRow%+1; view(aTextFile%); aResult% := FileClose(); 'close current file endcase endif aResult% := DialogSearchParameters(); 'User can re-enter this dialog at anytime ShowAnalysisDetails(0); 'just analysis type, no trial information bStr$ := ""; docase case pCellType% = kModeBehavior% then aStr$ := "Behavior Analysis"; case pCellType% = kModePause% then aStr$ := "Pause Analysis"; case pCellType% = kModeBurst% then aStr$ := "Burst Analysis"; endcase bStr$ := aStr$ + "\n"; docase case pAdaptType% = 0 then aStr$ := "Non-Adapt Analysis"; case pAdaptType% = 1 then aStr$ := "Non-Adapt with Corrective Saccade Analysis"; case pAdaptType% = 2 then aStr$ := "Adapt Analysis"; endcase bStr$ := bStr$ + aStr$ + "\n"; docase case pSearchScheme% = kSaccadeFirst% then aStr$ := "Find Saccade First, then Target"; case pSearchScheme% = kTargetFirst% then aStr$ := "Find Target First, then Saccade"; endcase bStr$ := bStr$ + aStr$ + "\n"; docase case pWriteTraces% = 0 then aStr$ := "Save only Attributes"; case pWriteTraces% = 1 then aStr$ := "Save Attributes and Traces"; endcase bStr$ := bStr$ + aStr$ + "\n"; Print(bStr$); View(gViewData%); 'Create cursors for manual and marking Cursor(0,0); 'Position cursor at time zero for i% := 1 to 9 do CursorNew(i%); Cursor(i%,0); 'Move all cursors to time zero CursorLabelPos(i%,i%*2-1); 'cascade the labels from the top so they don't overlap next; CursorLabel(4,8,"Onset"); CursorLabel(4,9,"Offset"); CursorVisible(-1,0); 'All cursors invisible 'Delete non memory channels created by previous analysis ChanDelete(chSaccadeOnset%); ChanDelete(chSaccadeOffset%); ChanDelete(chBurstOnset%); ChanDelete(chBurstOffset%); ChanDelete(chTargetTime%); ChanDelete(chTempSpd%); ChanDelete(ch1msBinEvent%); ChanDelete(chUnitSmooth%); '11/10/05 SpikeEditor hides some traces, this brings them back into view for i% := 0 to 500 do if chankind(i%) > 0 then 'test if the trace exists chanshow(i%); 'reveal those that exist endif next YRange(chUnit%,-5,5); YRange(chHE%[1],-25,25); YRange(chHE%[2],-25,25); YRange(chHT%[1],-25,25); YRange(chVE%[1],-25,25); YRange(chVE%[2],-25,25); YRange(chVT%[1],-25,25); Colour(1,3); 'background is GREY ChanColour(chHT%[1],1,kBlack%); 'black ChanColour(chVT%[1],1,kBlack%); 'black ChanColour(chHE%[1],1,9); 'red ChanColour(chHE%[2],1,11); 'rose ChanColour(chVE%[1],1,17); 'blue ChanColour(chVE%[2],1,19); 'dusty blue ChanColour(chUnit%,1,1); 'black ChanTitle$(chUnit%,"Unit"); ChanTitle$(chHE%[1],"HE"); ChanTitle$(chHT%[1],"HT"); ChanTitle$(chVE%[1],"VE"); ChanTitle$(chVT%[1],"VT"); ChanTitle$(chUnitEvent%,"Raster"); ChanUnits$(chUnit%,"volts"); ChanUnits$(chHE%[1],"deg"); ChanUnits$(chHT%[1],"deg"); ChanUnits$(chVE%[1],"deg"); ChanUnits$(chVT%[1],"deg"); ProgressBar("",1,0); 'create the activity bar '7/2/04 All data files with UNITS must have an event channel #10, BEHAVIORAL data does not '1/5/06 moved from ch #10 to #30 if pCellType% <> kModeBehavior% then docase case pUnitSmoothType% = kFixedUnitSmooth% then '---------------------------------------------------------- ' "fixed width gaussian" (original) unit smoothing routine '---------------------------------------------------------- ProgressBar("Generating Memory Channels, Spike Density",0,0); View(gViewData%); var gausskernel[4*pSigma*8+1]; GaussKernelGen(gausskernel[]); EventToWaveform(0.001*pSigma*4,chUnitEvent%,chUnitSmooth%,aBinSizeData,0,MaxTime(),4095,0,1,gausskernel[]); YRange(chUnitSmooth%,0,1000); ChanTitle$(chUnitSmooth%,"Spike Density"); ChanUnits$(chUnitSmooth%,"Hz"); ChanColour(chUnitSmooth%,1,kBlack%); ChanShow(chUnitSmooth%); case pUnitSmoothType% = kAdaptiveUnitSmooth% then '---------------------------------------------------------- ' "adaptive width gaussian" unit smoothing routine '---------------------------------------------------------- chUnitSmooth% := MemchanMake%(aBinSizeData,0,1000,kBlack%,"Spike Density","Hz",kShown%); AdaptiveGaussian%(chUnitEvent%,chUnitSmooth%,pSigma,0,Maxtime(2),0.001); '---------------------------------------------------------- endcase endif docase case pAnalysisType% = kNormalAnalysis% then a$ := "E"; b$ := "????"; c$ := "????"; case pAnalysisType% = kVergenceAnalysis% then a$ := "E1"; b$ := "E2"; c$ := "verg"; case pAnalysisType% = kGazeAnalysis% then a$ := "gaze"; b$ := "head"; c$ := "eih"; endcase ProgressBar("Generating Memory Channels, Analysis AB",0,0); View(gViewData%); 'Compute eye velocities chmHEvel%[1] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chHE%[1],1),"H"+a$+" vel","deg/s",kShown%); 'Horizontal eye ChanDiff(chmHEvel%[1], chHE%[1], 0, MaxTime()); HCursorNew(chmHEvel%[1], 0); 'centerline chmVEvel%[1] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chVE%[1],1),"V"+a$+" vel","deg/s",kShown%); 'Vertical eye ChanDiff(chmVEvel%[1], chVE%[1], 0, MaxTime()); HCursorNew(chmVEvel%[1], 0); 'centerline if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then ProgressBar("Generating Memory Channels, Analysis CD",0,100*2/38); View(gViewData%); chmHEvel%[2] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chHE%[2],1),"H"+b$+" vel","deg/s",kShown%); 'Horizontal eye ChanDiff(chmHEvel%[2], chHE%[2], 0, MaxTime()); chmVEvel%[2] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chVE%[2],1),"V"+b$+" vel","deg/s",kShown%); 'Vertical eye ChanDiff(chmVEvel%[2], chVE%[2], 0, MaxTime()); chmAbsHEvel%[2] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmHEvel%[2],1),"Abs H"+b$+" vel","deg/s",kHidden%); 'abs H eye2 vel ChanAbs(chmAbsHEvel%[2],chmHEvel%[2],0,MaxTime()); 'memory channel chmAbsVEvel%[2] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmVEvel%[2],1),"Abs V"+b$+" vel","deg/s",kHidden%); 'abs V eye2 vel ChanAbs(chmAbsVEvel%[2],chmVEvel%[2],0,MaxTime()); 'memory channel chmHEpeakVel%[2] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmHEvel%[2],1),"H"+b$+" Pk Vel","deg/s",kShown%); 'peak H eye2 vel DrawMode(chmHEpeakVel%[2], 1, kDot5); chmVEpeakVel%[2] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmVEvel%[2],1),"V"+b$+" Pk Vel","deg/s",kShown%); 'peak V eye2 vel DrawMode(chmVEpeakVel%[2], 1, kDot5); ProgressBar("Generating Memory Channels, Analysis EF",0,100*8/38); View(gViewData%); chHE%[3] := MemchanMake%(aBinSizeData,1000,-1000,13,"H"+c$+"","deg",kShown%); 'Horizontal eye vergence ChanSub(chHE%[3], chHE%[1], chHE%[2], 0, MaxTime()); 'memory channel chVE%[3] := MemchanMake%(aBinSizeData,1000,-1000,21,"V"+c$+"","deg",kShown%); 'Vertical eye vergence ChanSub(chVE%[3], chVE%[1], chVE%[2], 0, MaxTime()); 'memory channel chmHEvel%[3] := MemchanMake%(aBinSizeData,1000,-1000,14,"H"+c$+" vel","deg/s",kShown%); 'Horizontal eye2 vel ChanDiff(chmHEvel%[3], chHE%[3], 0, MaxTime()); chmVEvel%[3] := MemchanMake%(aBinSizeData,1000,-1000,22,"V"+c$+" vel","deg/s",kShown%); 'Vertical eye2 vel ChanDiff(chmVEvel%[3], chVE%[3], 0, MaxTime()); ProgressBar("Generating Memory Channels, Analysis EF",0,100*12/38); View(gViewData%); chmAbsHEvel%[3] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmHEvel%[3],1),"Abs H"+c$+" vel","deg/s",kHidden%); 'abs Vergence vel ChanAbs(chmAbsHEvel%[3],chmHEvel%[3],0,MaxTime()); 'memory channel chmAbsVEvel%[3] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmVEvel%[3],1),"Abs V"+c$+" vel","deg/s",kHidden%); 'abs Vergence vel ChanAbs(chmAbsVEvel%[3],chmVEvel%[3],0,MaxTime()); 'memory channel chmHEpeakVel%[3] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmHEvel%[3],1),"H"+c$+" Pk Vel","deg/s",kShown%); 'Hverg Pk Vel DrawMode(chmHEpeakVel%[3], 1, kDot5); chmVEpeakVel%[3] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmVEvel%[3],1),"V"+c$+" Pk Vel","deg/s",kShown%); 'Vverg Pk Vel DrawMode(chmVEpeakVel%[3], 1, kDot5); ProgressBar("Generating Memory Channels, Rectified Velocities",0,100*16/38); View(gViewData%); 'Compute rectified summed saccade velocities for detecting saccade in memory channel chmRecSumSacVel%[2] := MemChan(9,0,aBinSizeData); 'memory channel for Eye2/Head if chmRecSumSacVel%[2] <= 0 then Message("Error creating memory channel, halt..."); halt; else ChanDiffRecSum(chmRecSumSacVel%[2],chHE%[2],chVE%[2],0,MaxTime()); Optimise(chmRecSumSacVel%[2],0,MaxTime()); ChanTitle$(chmRecSumSacVel%[2],"Rec Sum Vel"); endif chmRecSumSacVel%[3] := MemChan(9,0,aBinSizeData); 'memory channel for Verg/EIH if chmRecSumSacVel%[3] <= 0 then Message("Error creating memory channel, halt..."); halt; else ChanDiffRecSum(chmRecSumSacVel%[3],chHE%[3],chVE%[3],0,MaxTime()); Optimise(chmRecSumSacVel%[3],0,MaxTime()); ChanTitle$(chmRecSumSacVel%[3],"Rec Sum Vel"); endif endif 'if vergence or gaze ProgressBar("Generating Memory Channels, Rectified Velocities",0,100*18/38); View(gViewData%); 'Compute Rectified Summed target velocities for detecting target step in memory channel chmTargetDet% := MemChan(9,0,aBinSizeData); 'memory channel if chmTargetDet% <= 0 then Message("Error creating memory channel, halt..."); halt; else ChanDiffRecSum(chmTargetDet%,chHT%[1],chVT%[1],0,MaxTime()); Optimise(chmTargetDet%,0,MaxTime()); ChanTitle$(chmTargetDet%,"Target Detect"); endif 'Compute rectified summed saccade velocities for detecting saccade in memory channel chmRecSumSacVel%[1] := MemChan(9,0,aBinSizeData); 'memory channel chmRecSumSacVel%[5] := chmRecSumSacVel%[1]; 'adapt saccade uses this channel too if chmRecSumSacVel%[1] <= 0 then Message("Error creating memory channel, halt..."); halt; else ChanDiffRecSum(chmRecSumSacVel%[1],chHE%[1],chVE%[1],0,MaxTime()); Optimise(chmRecSumSacVel%[1],0,MaxTime()); ChanTitle$(chmRecSumSacVel%[1],"Rec Sum Vel"); endif 'Create instant frequency channel chmInstantRate% := MemChan(3,0,BinSize(chUnit%)); 'memory channel MemImport(chmInstantRate%,chUnitEvent%,0,MaxTime()); DrawMode(chmInstantRate%,7,kDot3); ChanTitle$(chmInstantRate%,"Instant Freq"); ChanUnits$(chmInstantRate%,"Hz"); ChanShow(chmInstantRate%); YRange(chmInstantRate%,0,1100); HCursorNew(chmInstantRate%, 0); 'centerline 'Create Rectified velocities chmAbsHEvel%[1] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmHEvel%[1],1),"Abs H"+a$+" vel","deg/s",kHidden%); 'Abs HE vel","deg/s chmAbsHEvel%[5] := chmAbsHEvel%[1]; 'adapt saccade uses this channel too ChanAbs(chmAbsHEvel%[1],chmHEvel%[1],0,MaxTime()); chmAbsVEvel%[1] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmVEvel%[1],1),"Abs V"+a$+" vel","deg/s",kHidden%); 'Abs VE vel","deg/s chmAbsVEvel%[5] := chmAbsVEvel%[1]; 'adapt saccade uses this channel too ChanAbs(chmAbsVEvel%[1],chmVEvel%[1],0,MaxTime()); 'Create Marker traces on eye and target traces chmMarkerHTarget% := MemchanMake%(aBinSizeData,25,-25,chancolour(chHT%[1],1),"H Targ Marker","deg",kShown%); 'H Targ Marker DrawMode(chmMarkerHTarget%, 1, kDot5); chmMarkerVTarget% := MemchanMake%(aBinSizeData,25,-25,chancolour(chVT%[1],1),"V Targ Marker","deg",kShown%); 'V Targ Marker DrawMode(chmMarkerVTarget%, 1, kDot5); ProgressBar("Generating Memory Channels, Marker Traces",0,100*25/38); View(gViewData%); '2/17/06 can we move this up where we can use a$ b$ c$???? 'Create Marker traces on eye traces for i% := 1 to kCh2Analyze do '3 do if chHE%[i%] > 0 then chmMarkerHeye%[i%] := MemchanMake%(aBinSizeData,25,-25,chancolour(chHE%[i%],1),"H"+a$+" Marker","deg",kShown%); 'H Eye Marker DrawMode(chmMarkerHeye%[i%], 1, kDot5); chmMarkerVeye%[i%] := MemchanMake%(aBinSizeData,25,-25,chancolour(chVE%[i%],1),"V"+a$+" Marker","deg",kShown%); 'V Eye Marker DrawMode(chmMarkerVeye%[i%], 1, kDot5); endif next chmHEpeakVel%[1] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmHEvel%[1],1),"H"+a$+" Pk Vel","deg/s",kShown%); 'HE Pk Vel DrawMode(chmHEpeakVel%[1], 1, kDot5); chmVEpeakVel%[1] := MemchanMake%(aBinSizeData,1000,-1000,chancolour(chmVEvel%[1],1),"V"+a$+" Pk Vel","deg/s",kShown%); 'VE Pk Vel DrawMode(chmVEpeakVel%[1], 1, kDot5); if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then 'do nothing else ChanHide(8); ChanHide(9); ChanHide(10); ChanHide(11); for i% := 2 to kCh2Analyze do if chankind(chmMarkerHeye%[i%]) > 0 then ChanHide(chmMarkerHeye%[i%]); 'Marker chan hidden again 4/17/07 endif if chankind(chmMarkerVeye%[i%]) > 0 then ChanHide(chmMarkerVeye%[i%]); 'Marker chan hidden again 4/17/07 endif next endif 'NOT vergence or gaze if pCellType% = kModeBehavior% then ChanHide(chUnit%); ChanHide(chmInstantRate%); else 'unit ProgressBar("Generating Memory Channels, Unit-related",0,100*29/38); View(gViewData%); 'Draw memch for delectable spike events ChanHide(chUnitEvent%); chmSpikeEventDeletable% := MemChan(3,0,BinSize(chUnit%)); 'memory channel MemImport(chmSpikeEventDeletable%,chUnitEvent%,0,MaxTime()); DrawMode(chmSpikeEventDeletable%,2,1); ChanShow(chmSpikeEventDeletable%); ChanTitle$(chmSpikeEventDeletable%,"Spike"); 'Draw memch for colored spike event chmColoredEvent% := MemChan(6,2,BinSize(chUnit%),1); 'memory channel DrawMode(chmColoredEvent%,3); 'Draw as waveform YRange(chmColoredEvent%,-4,4); ChanWeight(chmColoredEvent%,0.25); ChanShow(chmColoredEvent%); ChanTitle$(chmColoredEvent%,"Burst Hilite"); 'ChanColour doesn't work on WaveMark channels Colour(19,17); 'Wavemark type 1 = blue Colour(22,9); 'Wavemark type 4 = red 'Draw marker for spike density trace chmMarkerSpd% := MemchanMake%(aBinSizeData,1000,0,chancolour(chUnitSmooth%,1),"Spike Pk","spk/s",kShown%); 'Spike Pk DrawMode(chmMarkerSpd%,1,kDot5); aResult% := ChanOrder(chUnitSmooth%,0,chmMarkerSpd%); 'Draw chmColoredPrePostBurstTemp% chmColoredPrePostBurstTemp% := MemChan(6,2,BinSize(chUnit%),1); 'memory channel DrawMode(chmColoredPrePostBurstTemp%,3); ChanWeight(chmColoredPrePostBurstTemp%,0.25); ChanShow(chmColoredPrePostBurstTemp%); ChanTitle$(chmColoredPrePostBurstTemp%,"Pre/Post Hilite"); endif ProgressBar("Generating Memory Channels, PSTH",0,100*33/38); View(gViewData%); 'memch for psth events chmPSTHsaccadeOnset% := MemChan(3,0,aBinSizeData); 'memory channel ChanTitle$(chmPSTHsaccadeOnset%,"Sac Onset"); chmPSTHsaccadeOffset% := MemChan(3,0,aBinSizeData); 'memory channel ChanTitle$(chmPSTHsaccadeOffset%,"Sac Offset"); if pCellType% <> kModeBehavior% then chmPSTHburstOnset% := MemChan(3,0,BinSize(chUnit%)); 'memory channel ChanTitle$(chmPSTHburstOnset%,"Burst Onset"); chmPSTHburstOffset% := MemChan(3,0,BinSize(chUnit%)); 'memory channel ChanTitle$(chmPSTHburstOffset%,"Burst Offset"); endif chmPSTHtargetTime% := MemChan(3,0,aBinSizeData); 'memory channel ChanTitle$(chmPSTHtargetTime%,"Targ Time"); ProgressBar("Generating Memory Channels",0,100*38/38); View(gViewData%); 'Set channel ORDER ChanOrder(1); 'High number channel on top 'group E+T+Marker if pAnalysisType% = kGazeAnalysis% then ChanOrder(chHE%[1],0,chHE%[2]); ChanOrder(chHE%[1],0,chHE%[3]); ChanOrder(chHE%[1],0,chmMarkerHEye%[1]); ChanOrder(chHE%[2],0,chmMarkerHEye%[2]); ChanOrder(chHE%[3],0,chmMarkerHEye%[3]); ChanOrder(chVE%[1],0,chVE%[2]); ChanOrder(chVE%[1],0,chVE%[3]); ChanOrder(chVE%[1],0,chmMarkerVeye%[1]); ChanOrder(chVE%[2],0,chmMarkerVeye%[2]); ChanOrder(chVE%[3],0,chmMarkerVeye%[3]); ChanOrder(chmHEvel%[1],0,chmHEvel%[2]); ChanOrder(chmHEvel%[1],0,chmHEvel%[3]); ChanOrder(chmHEvel%[1],0,chmHEpeakVel%[1]); ChanOrder(chmHEvel%[2],0,chmHEpeakVel%[2]); ChanOrder(chmHEvel%[3],0,chmHEpeakVel%[3]); ChanOrder(chmVEvel%[1],0,chmVEvel%[2]); ChanOrder(chmVEvel%[1],0,chmVEvel%[3]); ChanOrder(chmVEvel%[1],0,chmVEpeakVel%[1]); ChanOrder(chmVEvel%[2],0,chmVEpeakVel%[2]); ChanOrder(chmVEvel%[3],0,chmVEpeakVel%[3]); endif 'group E+T+Marker if pAnalysisType% = kVergenceAnalysis% then ChanOrder(chHE%[1],0,chHE%[2]); ChanOrder(chHE%[2],0,chmMarkerHEye%[2]); ChanOrder(chVE%[1],0,chVE%[2]); ChanOrder(chVE%[2],0,chmMarkerVeye%[2]); ChanOrder(chmHEvel%[2],0,chmHEpeakVel%[2]); ChanOrder(chmHEvel%[3],0,chmHEpeakVel%[3]); ChanOrder(chmVEvel%[2],0,chmVEpeakVel%[2]); ChanOrder(chmVEvel%[3],0,chmVEpeakVel%[3]); ChanOrder(chHE%[3],0,chmMarkerHeye%[3]); ChanOrder(chVE%[3],0,chmMarkerVeye%[3]); endif ChanOrder(chHE%[1],0,chHT%[1]); ChanOrder(chHE%[1],0,chmMarkerHTarget%); ChanOrder(chHE%[1],0,chmMarkerHEye%[1]); ChanOrder(chVE%[1],0,chVT%[1]); ChanOrder(chVE%[1],0,chmMarkerVTarget%); ChanOrder(chVE%[1],0,chmMarkerVeye%[1]); ChanOrder(chmHEvel%[1],0,chmHEpeakVel%[1]); ChanOrder(chmVEvel%[1],0,chmVEpeakVel%[1]); 'arrange unit traces if pCellType% <> kModeBehavior% then ChanOrder(chmInstantRate%,1,chUnitSmooth%); ChanOrder(chUnitSmooth%,0,chmMarkerSpd%); ChanOrder(chmColoredEvent%,-1,chUnit%); ChanHide(chmColoredPrePostBurstTemp%); endif ChanHide(chHT%[2]); 'hide H second target channel ChanHide(chVT%[2]); 'hide V second target channel ChanHide(chUnitWaveMark%); 'hide unit wavemark channel ChanHide(chKeyboard%); 'hide keyboard channel ChanHide(chEvents%); 'hide event channel endif 'memchan ProgressBar("Generating Memory Channels",1,0); 'toggle the ProgressBar closed View(gViewData%); FrontView(gViewData%); WindowVisible(1); 'FOR TESTING PURPOSES ONLY 'DialogSelectTraces(); 'FOR TESTING PURPOSES ONLY return gViewData%; end 'open '---------------------------------------------------- ' A d a p t i v e G a u s s i a n '5/31/06 '---------------------------------------------------- func AdaptiveGaussian%(inCh%,outCh%,multiplier,sT,eT,deltat) var nspk%, tnspk%, n%, pi, datlen%, aProgress := 0; aProgress := aProgress + 0; ProgressBar("Generating Memory Channels, Spike Density",1,aProgress); View(gViewData%); datlen% := 1 + ((eT-sT) / deltat); pi := 4 * atan(1,1); var t[datlen%], t2[datlen%], data[datlen%]; for n% := 0 to datlen% - 1 do t[n%] := sT + (n% * deltat); Next; aProgress := aProgress + 12; ProgressBar("Generating Memory Channels, Spike Density",0,aProgress); View(gViewData%); ArrConst(data[],0); 'data is 0 nspk% := chanmeasure(inCh%,4,sT,eT); var spkT[nspk%], spkdeltaT[nspk%], spksigma[nspk%], spksigmaorig[nspk%], gaussstart[nspk%], gaussend[nspk%]; aProgress := aProgress + 12; ProgressBar("Generating Memory Channels, Spike Density",0,aProgress); View(gViewData%); tnspk% := chandata(inCh%,spkT[],sT,eT); nspk% := tnspk%; 'tnspk% is more accurate for some reason ArrConst(spkdeltaT[],spkT[]); ArrDiff(spkdeltaT[]); spkdeltaT[0] := spkdeltaT[1]; ' 1st and 2nd delta t are the same ArrConst(spksigma[],spkdeltaT[]); ArrMul(spksigma[],5*multiplier);' 5 sigma ArrConst(gaussstart[],spkT[]); ArrSub(gaussstart[],spksigma[]); 'minus 5*sigma 'check for negative, if found, make them 0 for n% := 0 to nspk% - 1 do if gaussstart[n%] < 0 then gaussstart[n%] := 0; endif; next; aProgress := aProgress + 25; ProgressBar("Generating Memory Channels, Spike Density",0,aProgress); View(gViewData%); ArrDiv(gaussstart[],deltat); ' divide by the fraction to get rounded time to deltat precision Round(gaussstart[]); ArrMul(gaussstart[],deltat); ' back to second rounded to deltat fraction ArrConst(gaussend[],spkT[]); ArrAdd(gaussend[],spksigma[]); ' plus 5*sigma 'check for more that eT for n% := 0 to nspk% - 1 do if gaussend[n%] > eT then gaussend[n%] := eT; endif; next; aProgress := aProgress + 25; ProgressBar("Generating Memory Channels, Spike Density",0,aProgress); View(gViewData%); ArrDiv(gaussend[],deltat); ' divide by the fraction to get rounded time to deltat precision Round(gaussend[]); ArrMul(gaussend[],deltat); ' back to second rounded to deltat fraction var g1[nspk%], kernellength%; ArrConst(g1[],spkdeltaT[]); 'sigma ArrMul(g1[],multiplier*sqrt(2*pi)); ArrDivR(g1[],1); 'k of gaussian aProgress := aProgress + 12; ProgressBar("Generating Memory Channels, Spike Density",0,aProgress); View(gViewData%); for n% := 0 to nspk% - 1 do kernellength% := 1 + ((gaussend[n%] - gaussstart[n%])/deltat); var kernel[kernellength%]; ArrConst(kernel[],t[(gaussstart[n%]-sT)/deltat:kernellength%]); 'copy the time required ArrSub(kernel[],spkT[n%]); ArrMul(kernel[],kernel[]); ArrDiv(kernel[],-2*spkdeltaT[n%]*spkdeltaT[n%]*multiplier*multiplier); Exp(kernel[]); ArrMul(kernel[],g1[n%]); ArrAdd(data[(gaussstart[n%]-sT)/deltat:kernellength%],kernel[]); next; ChanWriteWave(outCh%,data[],sT); aProgress := 100; ProgressBar("Generating Memory Channels, Spike Density",0,aProgress); View(gViewData%); return 1; end; 'AdaptiveGaussian '---------------------------------------------------- ' TraceCheck '3/21/06 '---------------------------------------------------- func TraceCheck() var aBadFile%; View(gViewData%); 'test here if all the proper traces are present aBadFile% := 0; 'burst files must have a channel with unit acceptance marks '---------------------------------------------------------- if pCellType% = kModeBurst% then 'if chankind(chUnitEvent%) <> 6 then 'unit wavemark ' aBadFile% := 1; ' message("This file is missing channel 30, the unit wavemark channel. \n\nWhen analyzing unit data you must run your file through SPIKE EDITOR before using SACCADE.\n"); 'endif 'aBadFile% := chankind(chUnitEvent%); if chankind(chUnitEvent%) < 1 then 'unit message("This file is missing the unit channel 30. \n\nWhen analyzing unit data you must run your file through SPIKE EDITOR before using SACCADE.\n"); halt; endif if chankind(chUnit%) <> 1 then 'unit waveform aBadFile% := 1; message("This file is missing channel 1, the unit waveform channel."); endif endif 'all files must have these traces '-------------------------------- if chankind(chHE%[1]) <> 1 then 'HE waveform aBadFile% := 1; message("This file is missing channel 2, the Horizontal Eye waveform channel.\n"); endif if chankind(chVE%[1]) <> 1 then 'VE waveform aBadFile% := 1; message("This file is missing channel 3, the Vertical Eye waveform channel.\n"); endif if chankind(chHT%[1]) <> 1 then 'HT waveform aBadFile% := 1; message("This file is missing channel 4, the Horizontal Target waveform channel.\n"); endif if chankind(chVT%[1]) <> 1 then 'VT waveform aBadFile% := 1; message("This file is missing channel 5, the Vertical Target waveformchannel.\n"); endif 'vergence files must have these additional traces '------------------------------------------------ if pAnalysisType% = kVergenceAnalysis% then if chankind(chHT%[2]) <> 1 then 'HT2 waveform aBadFile% := 1; message("This file is missing channel 8, the Second Horizontal Target waveform channel.\n"); endif if chankind(chVT%[2]) <> 1 then 'VT2 waveform aBadFile% := 1; message("This file is missing channel 9, the Second Vertical Target waveform channel.\n"); endif if chankind(chHE%[2]) <> 1 then 'HE2 waveform aBadFile% := 1; message("This file is missing channel 10, the Second Horizontal Eye waveform channel.\n"); endif if chankind(chVE%[2]) <> 1 then 'VE2 waveform aBadFile% := 1; message("This file is missing channel 11, the Second Vertical Eye waveform channel.\n"); endif endif 'gaze files must have these additional traces '-------------------------------------------- if pAnalysisType% = kGazeAnalysis% then if chankind(chHE%[2]) <> 1 then 'HE2 waveform aBadFile% := 1; message("This file is missing channel 10, the Horizonal Head waveform channel.\n"); endif if chankind(chVE%[2]) <> 1 then 'VE2 waveform aBadFile% := 1; message("This file is missing channel 11, the Vertical Head waveform channel.\n"); endif endif if aBadFile% > 0 then fileclose(0,1); 'close the current view without a query return -1; 'signals that no file was opened endif end 'TraceCheck '---------------------------------------------------- ' MemchanMake '2/10/06 '---------------------------------------------------- func MemchanMake%(aBinSize,aUpLim,aDnLim,aColor%,aTitle$,aUnit$,aShown%) var aMemChan%; aMemChan% := MemChan(9,0,aBinSize); YRange(aMemChan%,aDnLim,aUpLim); ChanColour(aMemChan%,1,aColor%); ChanTitle$(aMemChan%,aTitle$); ChanUnits$(aMemChan%,aUnit$); if aShown% = kShown% then ChanShow(aMemChan%); else ChanHide(aMemChan%); endif return aMemChan%; end 'memchanmake '---------------------------------------------------- ' ChanWeightsGet '9/19/06 '---------------------------------------------------- proc ChanWeightsGet() var i%, j%; if Viewkind(gViewData%) >= 0 then View(gViewData%); 'sampled channels for i% := 1 to 32 do if chankind(i%) > 0 then gChanWeights[i%] := chanweight(i%); endif next 'memory channels j% := 400; for i% := 33 to 64 do j% := j% + 1; if chankind(j%) > 0 then gChanWeights[i%] := chanweight(j%); endif next endif end 'ChanWeightsGet '---------------------------------------------------- ' ChanWeightsSet '9/19/06 '---------------------------------------------------- proc ChanWeightsSet() var i%, j%, aResult%; if Viewkind(gViewData%) >= 0 then View(gViewData%); 'sampled channels for i% := 1 to 32 do aResult%:= chankind(i%); if chankind(i%) > 0 then aResult%:= chanweight(i%, gChanWeights[i%]); endif next 'memory channels j% := 400; for i% := 33 to 64 do j% := j% + 1; aResult% := chankind(j%); if chankind(j%) > 0 then aResult% := chanweight(j%, gChanWeights[i%]); endif next endif end 'ChanWeightsSet '---------------------------------------------------- ' PrefSave ' '3/30/05 '---------------------------------------------------- func PrefSave%() PreferencesSave%(kTrue); return kTrue; 'Stay in toolbar end; 'PrefSave '---------------------------------------------------- ' PreferencesSave 'This saves the user preferences to a file called 'sactrack_parameters.txt found in the same directory 'that the application scripts are found. '3/30/05 '---------------------------------------------------- func PreferencesSave%(aDialog%) var aResult, aStr$, aVector%, j%,k%; PaletteGetCurrent(gPalettePrefColors, gPalettePrefAssignments); ChanWeightsGet(); 'get log window position and size if ViewKind(LogHandle()) >= 0 then View(LogHandle()); 'Make log view the current view WindowGetPos(pLogX1,pLogY1,pLogX2,pLogY2); endif 'get scrolling data window position and size if ViewKind(gViewData%) >= 0 then View(gViewData%); 'Make the data view the current view WindowGetPos(pDataX1,pDataY1,pDataX2,pDataY2); endif 'get spot scope position and size if ViewKind(gViewAttr%) >= 0 then View(gViewAttr%); 'Make the data view the current view WindowGetPos(pAttrX1,pAttrY1,pAttrX2,pAttrY2); endif 'get debug window position and size if ViewKind(gViewDetails%) >= 0 then View(gViewDetails%); 'Make the data view the current view WindowGetPos(pDetailsX1,pDetailsY1,pDetailsX2,pDetailsY2); endif 'write out the preference values now 'for backward compatibility, DO NOT REARRANGE the order which the parameters are written aStr$ := kParameterMilestone$ + Chr$(13); 'specifies the attribute format aStr$ := aStr$ + str$(pLogX1) + " " + str$(pLogY1) + " " + str$(pLogX2) + " " + str$(pLogY2) + Chr$(13); 'log window location aStr$ := aStr$ + str$(pDataX1) + " " + str$(pDataY1) + " " + str$(pDataX2) + " " + str$(pDataY2) + Chr$(13); 'data window location aStr$ := aStr$ + str$(pAttrX1) + " " + str$(pAttrY1) + " " + str$(pAttrX2) + " " + str$(pAttrY2) + Chr$(13); 'attribute window location aStr$ := aStr$ + str$(pDetailsX1) + " " + str$(pDetailsY1) + " " + str$(pDetailsX2) + " " + str$(pDetailsY2) + Chr$(13); 'details window location aStr$ := aStr$ + str$(pCellType%) + " " + str$(pAdaptType%) + " " + str$(pSearchScheme%) + " " + str$(pWriteTraces%) + Chr$(13); 'analysis choices dialog aStr$ := aStr$ + str$(pMaxPriSecInterval) + " " + str$(pPreOnsetSaveTime) + " " + str$(pScreenWidth%) + Chr$(13); 'screen width saved aStr$ := aStr$ + str$(pHVonOffSaccadeThreshold) + " " + str$(pDetectaSaccadeVelThreshold) + " " + str$(pPriPeakSaccadeThreshold) + " " + str$(pTargetThreshold) + " " + str$(pStartEndPercentThreshold) + " " + str$(pSigma) + " " + str$(pOptimize) + " " + str$(pMinAcceptedTargetSize) + " " + str$(pMaxAcceptedTargetSize) + Chr$(13); 'search parameters dialog k% := 0; for j% := 0 to 31 do aStr$ := aStr$ + str$(gAttrShow%[k%+0]) + " " + str$(gAttrShow%[k%+1]) + " " + str$(gAttrShow%[k%+2]) + " " + str$(gAttrShow%[k%+3]) + " " + str$(gAttrShow%[k%+4]) + " " + str$(gAttrShow%[k%+5]) + " " + str$(gAttrShow%[k%+6]) + " " + str$(gAttrShow%[k%+7]) + Chr$(13); 'attributes to show k% := k% + 8; next aStr$ := aStr$ + str$(pMinTarget2EyeInterval) + " " + str$(pMaxTarget2EyeInterval) + " " + str$(pAnalysisType%) + " " + str$(pBumpAnalysis%) + Chr$(13); for j% := 0 to 39 do aStr$ := aStr$ + str$(gPalettePrefColors[j%][0]) + " " + str$(gPalettePrefColors[j%][1]) + " " + str$(gPalettePrefColors[j%][2]) + Chr$(13); next for j% := 0 to 39 do aStr$ := aStr$ + str$(gPalettePrefAssignments[j%]) + Chr$(13); next aStr$ := aStr$ + gDataDir$ + Chr$(13); aStr$ := aStr$ + str$(pUnitSmoothType%) + " " + str$(pStartPercentThreshold) + " " + str$(pEndPercentThreshold) + " " + str$(pBurstPeakRangeMinus) + " " + str$(pBurstPeakRangePlus) + Chr$(13); aStr$ := aStr$ + str$(pDetectaHeadVelThreshold) + " " + str$(pPriPeakHeadThreshold) + " " + str$(pHVonOffHeadThreshold) + Chr$(13); for j% := 0 to 64 do aStr$ := aStr$ + str$(gChanWeights[j%]) + Chr$(13); next '------------------------------------------- '^^^ add NEW PARAMETERS above this line ^^^ aResult := filenew(1); 'open a new file 'TEST THAT THE STRING DOES NOT EXCEED THE SIZE LIMIT 'according to the manual, strings can be up to 65534 characters long aResult := print("%s", aStr$); 'fill it with a string FilePathSet(gPrefDir$); 'aim at the desktop where preference files are saved if aDialog% = kTrue then aResult := filesaveas("",1,1); 'save it, with the filename the user chooses else aResult := filesaveas("saccade_parameters.txt",1,1); 'save it endif aResult := fileclose(0); 'close it end 'PreferencesSave '---------------------------------------------------- ' PrefOpen ' '3/30/05 '---------------------------------------------------- func PrefOpen%() PreferencesOpen%(kTrue); return kTrue; 'Stay in toolbar end; 'PrefOpen '---------------------------------------------------- ' PreferencesOpen 'This loads the user preferences from a file called 'sactrack_parameters.txt found in the same directory 'that the application scripts are found. This file 'should readable by all future versions of Sactrack. ' 'Delete sactrack_parameters.txt if you want the default 'values. '3/30/05 '---------------------------------------------------- func PreferencesOpen%(aDialog%) var a$, aVector%, j%,k%, aResult, bResult; if aDialog% = kTrue then bResult := fileopen("",1); 'open the preference file, a file the user chooses if aResult <= 0 then bResult := fileopen(gPrefDir$ + "saccade_parameters.txt",1); 'something went wrong, try to open the default pref file endif else bResult := fileopen(gPrefDir$ + "saccade_parameters.txt",1); 'open the preference file endif if bResult > 0 then aResult := read(a$); 'read milestone date if (aResult > 0) and (a$ = kParameterMilestone$) then if aResult > 0 then readstr(a$, pLogX1, pLogY1, pLogX2, pLogY2); 'log window endif aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pLogX1, pLogY1, pLogX2, pLogY2); 'log window endif aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pDataX1, pDataY1, pDataX2, pDataY2); 'data window endif aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pAttrX1, pAttrY1, pAttrX2, pAttrY2); 'attributes window endif aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pDetailsX1, pDetailsY1, pDetailsX2, pDetailsY2); 'details window endif 'analysis choices dialog aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$,pCellType%,pAdaptType%,pSearchScheme%,pWriteTraces%); endif 'screen width saved dialog aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pMaxPriSecInterval,pPreOnsetSaveTime,pScreenWidth%); 'window endif 'search parameters dialog aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$,pHVonOffSaccadeThreshold,pDetectaSaccadeVelThreshold,pPriPeakSaccadeThreshold,pTargetThreshold, pStartEndPercentThreshold,pSigma,pOptimize,pMinAcceptedTargetSize,pMaxAcceptedTargetSize); endif k% := 0; for j% := 0 to 31 do aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$,gAttrShow%[k%+0],gAttrShow%[k%+1],gAttrShow%[k%+2],gAttrShow%[k%+3],gAttrShow%[k%+4],gAttrShow%[k%+5],gAttrShow%[k%+6],gAttrShow%[k%+7]); 'attributes to show k% := k% + 8; endif next aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pMinTarget2EyeInterval,pMaxTarget2EyeInterval,pAnalysisType%,pBumpAnalysis%); 'details window endif for j% := 0 to 39 do aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, gPalettePrefColors[j%][0], gPalettePrefColors[j%][1], gPalettePrefColors[j%][2]); endif next for j% := 0 to 39 do aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, gPalettePrefAssignments[j%]); endif next aResult := read(a$); 'read in the data directory if it exists if aResult > 0 then readstr(a$, gDataDir$); endif aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pUnitSmoothType%, pStartPercentThreshold, pEndPercentThreshold, pBurstPeakRangeMinus, pBurstPeakRangePlus); endif aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, pDetectaHeadVelThreshold, pPriPeakHeadThreshold, pHVonOffHeadThreshold); endif for j% := 0 to 64 do aResult := read(a$); 'read in the data string if it exists if aResult > 0 then readstr(a$, gChanWeights[j%]); endif next '------------------------------------------- '^^^ add NEW PARAMETERS above this line ^^^ PaletteSetNew(gPalettePrefColors, gPalettePrefAssignments); ChanWeightsSet(); else message("The parameter file was not loaded because it is incompatible with the current format."); endif 'if (aResult > 0) and (a$ = kParameterMilestone$) then view(bResult); aResult := fileclose(0); 'close the input file, prepare to overwrite endif end 'PreferencesOpen '---------------------------------------------------- ' ShowAnalysisDetails 'Show target status and details about the analysis in 'text window. ' 'mode% = 0 means display no target information 'mode% = 1 means display target information ' '7/16/04 '---------------------------------------------------- proc ShowAnalysisDetails(mode%) var aStr$, bStr$; View(gViewDetails%); EditSelectAll(); 'Select all text in log view EditClear(); 'Delete it bStr$ := ""; docase case pCellType% = kModeBehavior% then aStr$ := "Behavior Analysis"; case pCellType% = kModePause% then aStr$ := "Pause Analysis"; case pCellType% = kModeBurst% then aStr$ := "Burst Analysis"; endcase bStr$ := aStr$ + "\n"; docase case pAdaptType% = 0 then aStr$ := "Non-Adapt Analysis"; case pAdaptType% = 1 then aStr$ := "Non-Adapt with Corrective Saccade Analysis"; case pAdaptType% = 2 then aStr$ := "Adapt Analysis"; endcase bStr$ := bStr$ + aStr$ + "\n"; docase case pSearchScheme% = kSaccadeFirst% then aStr$ := "Find Saccade First, then Target"; case pSearchScheme% = kTargetFirst% then aStr$ := "Find Target First, then Saccade"; endcase bStr$ := bStr$ + aStr$ + "\n"; docase case pWriteTraces% = 0 then aStr$ := "Save only Attributes"; case pWriteTraces% = 1 then aStr$ := "Save Attributes and Traces"; endcase bStr$ := bStr$ + aStr$ + "\n"; if mode% > 0 then aStr$ := ""; if gTarget%=1 then aStr$ := aStr$ + "Target FOUND."; else aStr$ := aStr$ + "Target NOT FOUND."; endif aStr$ := aStr$ + "\nTrials Accepted/Found so far = " + Str$(gTrialAccepted%) + "/" + Str$(gTrialFound%) + ". If accepted, trial shown will be #" + Str$(gTrialAccepted%+1); 'use +1 because it starts at ZERO bStr$ := bStr$ + aStr$ + "\n"; endif Print(bStr$); end 'ShowAnalysisDetails '---------------------------------------------------- ' ChanDiffRecSum '< 3/10/04 '---------------------------------------------------- func ChanDiffRecSum(aOutputCh%, aTarget1%, aTarget2%, aBeg, aEnd) var aDataLength%; aDataLength% := (aEnd-aBeg)/BinSize(aTarget1%) + 1; var data1[aDataLength%], data2[aDataLength%]; chandata(aTarget1%, data1[], aBeg, aEnd); 'get first ch of data chandata(aTarget2%, data2[], aBeg, aEnd); 'get sec chan of data ArrDiffRobi(data1[], BinSize(aTarget1%)); 'differentiate first ch ArrDiffRobi(data2[], BinSize(aTarget1%)); 'differentiate sec chan Abs(data1[]); 'ABS first ch Abs(data2[]); 'ABS sec chan arradd(data1[], data2[]); 'SUM the chan chanwritewave(aOutputCh%, data1[], aBeg); return aDataLength%; end 'ChanDiffRecSum '---------------------------------------------------- ' ChanSub ' 1/20/06 '---------------------------------------------------- func ChanSub(dest%,aSource%,bSource%,sTime,eTime) '(chHE%[3], chHE%[1], chHE%[2], 0, MaxTime(); 'subtract two entire traces from each other to create vergence or eye-in-head var DataLength%; DataLength% := (eTime-sTime)/BinSize(aSource%) + 1; var aData[DataLength%],bData[DataLength%]; ChanData(aSource%,aData[],sTime,eTime); ChanData(bSource%,bData[],sTime,eTime); ArrSub(aData[],bData[]); ChanWriteWave(dest%,aData[],sTime); return DataLength%; end 'ChanSub '---------------------------------------------------- ' ChanAbs '< 3/10/04 Robi's routine '---------------------------------------------------- func ChanAbs(dest%, source%, sTime, eTime) 'rectify a channel and put the results in another channel var DataLength%; DataLength% := (eTime-sTime)/BinSize(source%) + 1; var data[DataLength%]; ChanData(source%,data[],sTime,eTime); Abs(data[]); ChanWriteWave(dest%,data[],sTime); return DataLength%; end 'ChanAbs '---------------------------------------------------- ' ChanDiff '< 3/10/04 Robi's routine '---------------------------------------------------- func ChanDiff(dest%, source%, sTime, eTime) '5 coefficient FIR derivative 'dest% is destination channel 'source% is source channel var DataLength%; DataLength% := (eTime-sTime)/BinSize(source%) + 1; var data1[DataLength%]; ChanData(source%, data1[], sTime, eTime); ArrDiffRobi(data1[],BinSize(source%)); chanwritewave(dest%,data1[],sTime); return DataLength%; end 'ChanDiff '---------------------------------------------------- ' ArrDiffRobi ' put the data to be differentiated in dest[], it will ' be replaced by its derivative ' TimeStep is in second '< 3/10/04 Robi's routine '---------------------------------------------------- func ArrDiffRobi(dest[], TimeStep) var coeffFIR[5]; coeffFIR[0] := -0.2; coeffFIR[1] := -0.1; coeffFIR[2] := 0; coeffFIR[3] := 0.1; coeffFIR[4] := 0.2; ArrFilt(dest[],coeffFIR[]); ArrDiv(dest[],TimeStep); return TimeStep; end 'ArrDiffRobi '---------------------------------------------------- ' DetectSaccadeThenTarget 'Find the next saccade and then find the target that 'precedes it. '3/23/04 '---------------------------------------------------- func DetectSaccadeThenTarget() var aBeg, aResult; repeat gStartSearch := GetLatestMarkedTime(); aBeg := gStartSearch; '4/1/04 this fixes a situation that hangs the program in auto mode when searching by saccade and the target view(gViewData%); if aBeg >= MaxTime() then return -1; endif aResult := DetectaSaccade(aBeg, MaxTime(), 1); 'HV eye1 if gSaccadeExist%[1] < 0 then return -1; endif 'A saccade is always found even though a target step may not be. 'Stop if the detected event is beyond the user's specified range. if gCursorZeroTime >= gWhereToStopAnalysis then 'change the value of gCursorZeroTime for next search? return -1; 'the user said to stop analyzing here endif if gSaccadeExist%[1] > 0 then if gCursorZeroTime < 0.601 then DetectaTarget(0, gCursorZeroTime, pTargetThreshold,gTargetStepTime,gTarget%); 'beginning of file else DetectaTarget(gCursorZeroTime-pMinTarget2EyeInterval, gCursorZeroTime-pMaxTarget2EyeInterval, pTargetThreshold,gTargetStepTime,gTarget%); endif endif until gSaccadeExist%[1] > 0; DetectCommonStuff(); ' ComputeEarliestAndLatest(1); ' COMPAREearliestAndLatest(1); ' ' if (pAnalysisType% = kVergenceAnalysis%) ' or (pAnalysisType% = kGazeAnalysis%) then ' aResult := DetectaSaccade(gEarliestOnset-0.100, gEarliestOnset+0.100, 2);'HV eye2 ' ComputeEarliestAndLatest(2); ' COMPAREearliestAndLatest(2); ' endif ' if gSaccadeExist%[1]+gSaccadeExist%[2]+gSaccadeExist%[3]+gSaccadeExist%[4] > 0 then ' gSaccadeDuration := gLatestOffset - gEarliestOnset; ' endif ' ' if pAdaptType% > 0 then ' DetectaSecondEvent(gLatestOffset+0.040, gLatestOffset+pMaxPriSecInterval); ' ComputeEarliestAndLatest(5); ' COMPAREearliestAndLatest(5); ' if gSaccadeExist%[5] > 0 then ' zSaccadeDuration := zLatestOffset - zEarliestOnset; ' endif ' endif gTrialFound% := gTrialFound% + 1; return 1; 'found a saccade, maybe found a target end 'DetectSaccadeThenTarget '---------------------------------------------------- ' DetectTargetThenSaccade 'Locate the next target then locate the saccade on [1] 'that follows it. Find a saccade on [2] if this is a 'vergence analysis. '4/2/04 '---------------------------------------------------- func DetectTargetThenSaccade() var aResult, aStartSearch; repeat gStartSearch := GetLatestMarkedTime(); View(gViewData%); 'Make the data view the current view ' DetectaTarget(gCursorZeroTime, MaxTime(), pTargetThreshold, gTargetStepTime, gTarget%); DetectaTarget(gStartSearch, MaxTime(), pTargetThreshold, gTargetStepTime, gTarget%); if gTarget% = 0 then return -1; 'no targets in the rest of the file endif if gTargetStepTime >= gWhereToStopAnalysis then return -1; 'the user said to stop analyzing here endif aResult := DetectaSaccade(gTargetStepTime + pMinTarget2EyeInterval, gTargetStepTime + pMaxTarget2EyeInterval, 1); 'search forward for the saccade that follows the target step until gSaccadeExist%[1] > 0; DetectCommonStuff(); ' ComputeEarliestAndLatest(1); ' COMPAREearliestAndLatest(1); ' ' docase ' case (pAnalysisType% = kVergenceAnalysis%) then ' aResult := DetectaSaccade(gEarliestOnset-0.100, gLatestOffset+0.100, 2); 'HV eye2 ' ComputeEarliestAndLatest(2); ' COMPAREearliestAndLatest(2); ' aResult := DetectaSaccade(gEarliestOnset-0.100, gLatestOffset+0.100, 3); 'HV vergence ' ComputeEarliestAndLatest(3); ' COMPAREearliestAndLatest(3); ' ' case (pAnalysisType% = kGazeAnalysis%) then ' aResult := DetectaSaccade(gEarliestOnset, gLatestOffset, 3); 'HV EIH ' ComputeEarliestAndLatest(3); ' COMPAREearliestAndLatest(3); ' 'find head last because it is so slow ' aResult := DetectaSaccade(gEarliestOnset-0.500, gLatestOffset+1.000, 2); 'head ' ComputeEarliestAndLatest(2); ' COMPAREearliestAndLatest(2); ' endcase ' ' if gSaccadeExist%[1]+gSaccadeExist%[2]+gSaccadeExist%[3]+gSaccadeExist%[4] > 0 then ' gSaccadeDuration := gLatestOffset - gEarliestOnset; ' endif ' ' if pAdaptType% > 0 then ' DetectaSecondEvent(gLatestOffset+0.040, gLatestOffset+pMaxPriSecInterval); ' ComputeEarliestAndLatest(5); ' COMPAREearliestAndLatest(5); ' if (pAnalysisType% = kVergenceAnalysis%) ' or (pAnalysisType% = kGazeAnalysis%) then ' ComputeEarliestAndLatest(6); ' COMPAREearliestAndLatest(6); ' endif ' if gSaccadeExist%[5]+gSaccadeExist%[6] > 0 then ' zSaccadeDuration := zLatestOffset - zEarliestOnset; ' endif ' endif gTrialFound% := gTrialFound% + 1; return 1; 'found one end 'DetectTargetThenSaccade '---------------------------------------------------- ' DetectRestOfTrial 'This routine finds the events on the two other 'traces when analyzing vergence or gaze. '6/19/06 '---------------------------------------------------- func DetectCommonStuff() var aResult; ComputeEarliestAndLatest(1); COMPAREearliestAndLatest(1); docase case (pAnalysisType% = kVergenceAnalysis%) then aResult := DetectaSaccade(gEarliestOnset-0.100, gLatestOffset+0.100, 2); 'HV eye2 ComputeEarliestAndLatest(2); COMPAREearliestAndLatest(2); aResult := DetectaSaccade(gEarliestOnset-0.100, gLatestOffset+0.100, 3); 'HV vergence ComputeEarliestAndLatest(3); COMPAREearliestAndLatest(3); case (pAnalysisType% = kGazeAnalysis%) then aResult := DetectaSaccade(gEarliestOnset, gLatestOffset, 3); 'HV EIH ComputeEarliestAndLatest(3); COMPAREearliestAndLatest(3); 'find head last because it is so slow aResult := DetectaSaccade(gEarliestOnset-0.500, gLatestOffset+1.000, 2); 'head ComputeEarliestAndLatest(2); COMPAREearliestAndLatest(2); endcase if gSaccadeExist%[1]+gSaccadeExist%[2]+gSaccadeExist%[3]+gSaccadeExist%[4] > 0 then gSaccadeDuration := gLatestOffset - gEarliestOnset; endif if pAdaptType% > 0 then DetectaSecondEvent(gLatestOffset+0.040, gLatestOffset+pMaxPriSecInterval); ComputeEarliestAndLatest(5); COMPAREearliestAndLatest(5); if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then ComputeEarliestAndLatest(6); COMPAREearliestAndLatest(6); endif if gSaccadeExist%[5]+gSaccadeExist%[6] > 0 then zSaccadeDuration := zLatestOffset - zEarliestOnset; endif endif end 'DetectCommonStuff '---------------------------------------------------- ' COMPAREearliestAndLatest 'Computes when the saccade started and ended as well. '2/13/06 '---------------------------------------------------- proc COMPAREearliestAndLatest(aTrace%); if (aTrace% = 5) or (aTrace% = 6) then docase case (zEarliestOnset <> NaN) and (gHVonsetTime[aTrace%] <> NaN) then zEarliestOnset := min(zEarliestOnset,gHVonsetTime[aTrace%]); 'Both H V saccades exist zLatestOffset := max(zLatestOffset,gHVoffsetTime[aTrace%]); case (gHVonsetTime[aTrace%] <> NaN) then zEarliestOnset := gHVonsetTime[aTrace%]; zLatestOffset := gHVoffsetTime[aTrace%]; endcase else docase case (gEarliestOnset <> NaN) and (gHVonsetTime[aTrace%] <> NaN) then gEarliestOnset := min(gEarliestOnset,gHVonsetTime[aTrace%]); 'Both H V saccades exist gLatestOffset := max(gLatestOffset,gHVoffsetTime[aTrace%]); case (gHVonsetTime[aTrace%] <> NaN) then gEarliestOnset := gHVonsetTime[aTrace%]; gLatestOffset := gHVoffsetTime[aTrace%]; endcase endif end 'COMPAREearliestAndLatest '---------------------------------------------------- ' ComputeEarliestAndLatest 'Computes when the saccade started and ended as well. '3/23/04 '---------------------------------------------------- proc ComputeEarliestAndLatest(aTrace%) docase case (gHEsaccadeExist%[aTrace%] > 0) and (gVEsaccadeExist%[aTrace%] > 0) then 'gSaccadeExist%[aTrace%] > 1 then gHVonsetTime[aTrace%] := min(gHEonsetTime[aTrace%], gVEonsetTime[aTrace%]); 'Both H V saccades exist gHVoffsetTime[aTrace%] := max(gHEoffsetTime[aTrace%], gVEoffsetTime[aTrace%]); case gVEsaccadeExist%[aTrace%] > 0 then gHVonsetTime[aTrace%] := gVEonsetTime[aTrace%]; 'No H saccade gHVoffsetTime[aTrace%] := gVEoffsetTime[aTrace%]; case gHEsaccadeExist%[aTrace%] > 0 then gHVonsetTime[aTrace%] := gHEonsetTime[aTrace%]; 'No V saccade gHVoffsetTime[aTrace%] := gHEoffsetTime[aTrace%]; endcase end 'ComputeEarliestAndLatest '---------------------------------------------------- ' DetectaTarget 'Search the Rectified Summed target velocities channel 'for a peak. '< 3/10/04 '---------------------------------------------------- proc DetectaTarget(aBeg, aEnd, aThreshold, &aTargetStepTime, &aTarget%) View(gViewData%); 'Make the data view the current view aTargetStepTime := ChanSearch(chmTargetDet%, 4, aBeg, aEnd, aThreshold); 'search for a peak if aTargetStepTime < 0 then aTargetStepTime := NaN; aTarget% := 0; 'means no target else aTarget% := 1; 'target exists endif end 'DetectaTarget '---------------------------------------------------- ' DetectaSaccade 'Saccade detection for manual and automatic modes '< 3/10/04 '---------------------------------------------------- func DetectaSaccade(aBeg, aEnd, aTrace%) var aRecSumVelBeg := -1, aRecSumVelEnd := -1, aSacTime := -1, aThreshold, bThreshold, cThreshold, dThreshold, aReturnValue, bBeg := -1, bEnd := -1, a$; 'H & V peak velocity Detection '-------------------------- 'Finds the peak time on the Rectified Summed saccade velocity, threshold is default set to 120 deg/s. aThreshold := pDetectaSaccadeVelThreshold; if pAnalysisType% = kGazeAnalysis% then if (aTrace% = 2) then 'head signal aThreshold := pDetectaHeadVelThreshold; endif endif view(gViewData%); if gTargetStepTime <> NaN then if aBeg < gTargetStepTime then aBeg := gTargetStepTime; 'don't search before the target movement for a peak, if one exists endif endif aSacTime := ChanSearch(chmRecSumSacVel%[aTrace%], 4, aBeg, aEnd, aThreshold); 'find the next saccade (next PEAK mode), if there is one if aSacTime < 0 then gCursorZeroTime := aEnd; 'prepare for next event search, just after the current search range aReturnValue := -1; 'did not find one. use the old cursor time else bBeg := aSacTime-kPriSaccadeRange; ':= 0.300 bEnd := aSacTime+kPriSaccadeRange; if pAnalysisType% = kGazeAnalysis% then 'if (aTrace% = 2) then 'head signal bBeg := bBeg - 0.500; 'head movements can start earlier bEnd := bEnd + 1.000; 'head movements can end later if gTargetStepTime <> NaN then if bBeg < gTargetStepTime then bBeg := gTargetStepTime; 'don't search before the target movement, if one exists endif endif 'endif endif if bBeg < 0 then bBeg := 0; 'beginning of file protection endif if bEnd > MaxTime() then bEnd := MaxTime(); 'end of file protection endif 'Finds the begin and end times with the Rectified Summed saccade velocity, threshold is set at 40 deg/s. Using the rectified velocity trace 'is for general location, the actual beg & end times are re-located in MetricsPrimarySaccade() using the actual velocity trace. bThreshold := pHVonOffSaccadeThreshold; if pAnalysisType% = kGazeAnalysis% then if (aTrace% = 2) then 'head signal bThreshold := pHVonOffHeadThreshold; endif endif aRecSumVelBeg := ChanSearch(chmRecSumSacVel%[aTrace%], 8, aSacTime, bBeg, bThreshold); aRecSumVelEnd := ChanSearch(chmRecSumSacVel%[aTrace%], 8, aSacTime, bEnd, bThreshold); if (aRecSumVelBeg < 0) or (aRecSumVelEnd < 0) then gCursorZeroTime := aSacTime+kPriSaccadeRange; 'a saccade was found, but no beginning or end, next search starts where this one ended aReturnValue := -1; else gCursorZeroTime := aRecSumVelEnd; 'found a saccade! use the new cursor time 'H & V saccade measurements '-------------------------- gHEsaccadeExist%[aTrace%] := MetricsPrimarySaccade( gPeakHEvelTime[aTrace%], gHEonsetTime[aTrace%], gHEoffsetTime[aTrace%], cThreshold, dThreshold, chmAbsHEvel%[aTrace%], aRecSumVelBeg, aRecSumVelEnd); gVEsaccadeExist%[aTrace%] := MetricsPrimarySaccade( gPeakVEvelTime[aTrace%], gVEonsetTime[aTrace%], gVEoffsetTime[aTrace%], cThreshold, dThreshold, chmAbsVEvel%[aTrace%], aRecSumVelBeg, aRecSumVelEnd); if (gHEsaccadeExist%[aTrace%] = 1) and (pBumpAnalysis% = 1) then gHEsaccadeExist%[aTrace%] := MetricsBump(aSacTime, gHEonsetTime[aTrace%], gHEoffsetTime[aTrace%], chmAbsHEvel%[aTrace%], chHE%[aTrace%], chmHEvel%[aTrace%], aTrace%); endif if (gVEsaccadeExist%[aTrace%] = 1) and (pBumpAnalysis% = 1) then gVEsaccadeExist%[aTrace%] := MetricsBump(aSacTime, gVEonsetTime[aTrace%], gVEoffsetTime[aTrace%], chmAbsVEvel%[aTrace%], chVE%[aTrace%], chmVEvel%[aTrace%], aTrace%); endif gSaccadeExist%[aTrace%] := gHEsaccadeExist%[aTrace%] + gVEsaccadeExist%[aTrace%]; 'Saccade exists if value > 0 'abc call MetricsSaccade(aTrace%) here remove from HighlightComputeAndMark aReturnValue := gSaccadeExist%[aTrace%]; endif endif if gAutoAnalysis% = 0 then view(gViewSearch%); a$ := "---------------------" + Chr$(13); a$ := a$ + print$("%13.5f",aTrace%) + " = Trace" + " = " + chName$[aTrace%] + Chr$(13); a$ := a$ + Chr$(13); a$ := a$ + print$("%13.5f",aThreshold) + " = Pk Thresh " + Chr$(13); a$ := a$ + print$("%13.5f",aBeg) + " = RecSum peak search limit" + Chr$(13); a$ := a$ + print$("%13.5f",aSactime) + " = RecSum Peak" + Chr$(13); a$ := a$ + print$("%13.5f",aEnd) + " = RecSum peak search limit" + Chr$(13); a$ := a$ + Chr$(13); a$ := a$ + print$("%13.5f",bThreshold) + " = On/Offset Thresh" + Chr$(13); a$ := a$ + print$("%13.5f",bBeg) + " = RecSum onset search limit" + Chr$(13); a$ := a$ + print$("%13.5f",aRecSumVelBeg) + " = RecSum Onset" + Chr$(13); a$ := a$ + print$("%13.5f",aRecSumVelEnd) + " = RecSum Offset" + Chr$(13); a$ := a$ + print$("%13.5f",bEnd) + " = RecSum offset search limit" + Chr$(13); a$ := a$ + Chr$(13); a$ := a$ + print$("%13.5f",cThreshold) + " = Pk Thresh " + Chr$(13); a$ := a$ + print$("%13.5f",dThreshold) + " = On/Offset Thresh" + Chr$(13); a$ := a$ + print$("%13.5f",gHEonsetTime[aTrace%]) + " = H Onset" + Chr$(13); a$ := a$ + print$("%13.5f",gPeakHEvelTime[aTrace%]) + " = H Peak" + Chr$(13); a$ := a$ + print$("%13.5f",gHEoffsetTime[aTrace%]) + " = H Offset" + Chr$(13); a$ := a$ + print$("%13.5f",gVEonsetTime[aTrace%]) + " = V Onset" + Chr$(13); a$ := a$ + print$("%13.5f",gPeakVEvelTime[aTrace%]) + " = V Peak" + Chr$(13); a$ := a$ + print$("%13.5f",gVEoffsetTime[aTrace%]) + " = V Offset" + Chr$(13); Print(a$); endif return aReturnValue; end 'DetectaSaccade '---------------------------------------------------- ' MetricsPrimarySaccade ' Finds the beginning and the end of the movement ' plus the peak velocity. "doCrazyThing" code used ' to be here. ' 9/23/05 '---------------------------------------------------- func MetricsPrimarySaccade( &aPeakEyeVelTime, &aEyeOnset, &aEyeOffset, &cThreshold, &dThreshold, aMemChAbsEyeVel%, aRecSumVelBeg, aRecSumVelEnd) var aSaccadeExist% := 0, aOffsetEnd; ' if pAnalysisType% = kGazeAnalysis% then ' aOffsetEnd := 1.000; 'gaze movements are much slower than saccades ' else ' aOffsetEnd := 0.200; '4/6/06 for elena 0.100; ' endif ' 'peak detection '-------------------------- cThreshold := pPriPeakSaccadeThreshold; if pAnalysisType% = kGazeAnalysis% then if (aMemChAbsEyeVel% = chmAbsHEvel%[2]) or (aMemChAbsEyeVel% = chmAbsVEvel%[2]) then 'head signal cThreshold := pPriPeakHeadThreshold; endif endif view(gViewData%); if (aRecSumVelEnd<=0) or (aRecSumVelEnd=NAN) then aRecSumVelEnd := aRecSumVelEnd; endif 'aPeakEyeVelTime := ChanSearch(aMemChAbsEyeVel%, 1, aRecSumVelBeg, aRecSumVelEnd, cThreshold); 'find the peak aPeakEyeVelTime := ChanSearch(aMemChAbsEyeVel%, 1, aRecSumVelBeg, aRecSumVelEnd); 'find the peak if chanvalue(aMemChAbsEyeVel%,aPeakEyeVelTime) < cThreshold then aPeakEyeVelTime := -1; 'invalid velocity, not fast enough, 4/17/07 endif 'onset and offset detection '-------------------------- dThreshold := pHVonOffSaccadeThreshold; if pAnalysisType% = kGazeAnalysis% then if (aMemChAbsEyeVel% = chmAbsHEvel%[2]) or (aMemChAbsEyeVel% = chmAbsVEvel%[2]) then 'head signal dThreshold := pHVonOffHeadThreshold; endif endif if aPeakEyeVelTime >= 0 then 'is this peak fast enough to be a saccade? ' aEyeOnset := ChanSearch(aMemChAbsEyeVel%, 8, aPeakEyeVelTime, aPeakEyeVelTime-aOffsetEnd, dThreshold); ' aEyeOffset := ChanSearch(aMemChAbsEyeVel%, 8, aPeakEyeVelTime, aPeakEyeVelTime+aOffsetEnd, dThreshold); aEyeOnset := ChanSearch(aMemChAbsEyeVel%, 8, aPeakEyeVelTime, 0, dThreshold); 'search to beg of file aEyeOffset := ChanSearch(aMemChAbsEyeVel%, 8, aPeakEyeVelTime, maxtime(), dThreshold); 'search to end of file aSaccadeExist% := 1; '4/7/07 this is probably obsolete now that it will search to ends of file. A saccade that 'doesn't end at the end of the file could trigger this exception '11/10/05 a provision for when a peak is found, but not an onset or offset if (aEyeOnset < 0) or (aEyeOffset < 0) then aPeakEyeVelTime := NaN; aEyeOnset := NaN; aEyeOffset := NaN; aSaccadeExist% := 0; endif else aPeakEyeVelTime := NaN; aEyeOnset := NaN; aEyeOffset := NaN; aSaccadeExist% := 0; endif return aSaccadeExist% end 'MetricsPrimarySaccade '---------------------------------------------------- ' MetricsBump ' Determine if the eye movement found is actually a ' "bump" instead of a saccade. If it is, change the ' appropriate attributes. ' ' 9/26/05 '---------------------------------------------------- func MetricsBump(&aPeakEyeVelTime, &aEyeOnsetTime, &aEyeOffsetTime, aMemChAbsEyeVel%, chEye%, chEyeVel%, aTrace%) const aEyeSettled := 0.200, '0.075, aJustOutsideRecVel := 0.005; 'based efforts with MetricPrimarySaccade() var aLtEyePos, aRtEyePos, aLtEyeTime, aRtEyeTime, aMaxEyePosTime, aMinEyePosTime, aMaxEyePos, aMinEyePos, aPkEyePos, aThreshold, aMaxEyeVelTime, aMinEyeVelTime, aMaxEyeVel, aMinEyeVel, aAmpDiff, aTemp, bTemp; aLtEyeTime := aPeakEyeVelTime - aEyeSettled; 'pick a point pre-saccade aRtEyeTime := aPeakEyeVelTime + aEyeSettled; 'pick a point post-saccade aLtEyePos := ChanValue(chEye%, aLtEyeTime); 'get the position values aRtEyePos := ChanValue(chEye%, aRtEyeTime); aMaxEyePosTime := ChanSearch(chEye%, 1, aLtEyeTime, aRtEyeTime); 'find the max position in that region aMinEyePosTime := ChanSearch(chEye%, 2, aLtEyeTime, aRtEyeTime); 'find the min position in that region aMaxEyePos := ChanValue(chEye%, aMaxEyePosTime); 'determine which velocity is bigger aMinEyePos := ChanValue(chEye%, aMinEyePosTime); if abs(aLtEyePos - aMaxEyePos) > abs(aLtEyePos - aMinEyePos) then 'choose the one that is most eccentric from the start position aPkEyePos := aMaxEyePos; else aPkEyePos := aMinEyePos; endif aAmpDiff := abs(aRtEyePos - aLtEyePos); 'compute pre-post position difference aThreshold := abs(aPkEyePos - aLtEyePos) * 0.5; 'amplitude to the max velocity is the bump threshold if aAmpDiff < aThreshold then 'it may be a bump! '11/17/05 it seems that some of the "bumps" are being found by the new 'onset/offset searching techinque in MetricsPrimarySaccade which now 'searches inward from the onset/offset of the recsumvel 'search outward from aPeakEyeVelTime to find the onset and offset on recsumvel aLtEyeTime := ChanSearch(chmRecSumSacVel%[aTrace%], 8, aPeakEyeVelTime, aLtEyeTime, pHVonOffSaccadeThreshold); 'find the next saccade, if there is one aRtEyeTime := ChanSearch(chmRecSumSacVel%[aTrace%], 8, aPeakEyeVelTime, aRtEyeTime, pHVonOffSaccadeThreshold); 'find the next saccade, if there is one if (aLtEyeTime > 0) and (aRtEyeTime > 0) then 'add/sub aJustOutsideRecVel from that range, then aLtEyeTime := aLtEyeTime - aJustOutsideRecVel; 'pick a point pre-saccade aRtEyeTime := aRtEyeTime + aJustOutsideRecVel; 'pick a point post-saccade 'search inward to find the onset and offset on the ACTUAL velocity trace aTemp := ChanSearch(aMemChAbsEyeVel%, 7, aLtEyeTime, aPeakEyeVelTime, pHVonOffSaccadeThreshold); 'search from the left for the onset bTemp := ChanSearch(aMemChAbsEyeVel%, 7, aRtEyeTime, aPeakEyeVelTime, pHVonOffSaccadeThreshold); 'search from the right for the offset '11/9/05 this tests that it did not get confused in an area of lots of saccades which can confuse the bump identification process if (aTemp > 0) and (bTemp > 0) then aEyeOnsetTime := aTemp; aEyeOffsetTime := bTemp; aPeakEyeVelTime:= ChanSearch(aMemChAbsEyeVel%, 1, aTemp, bTemp); 'the peak velocity is between the on-offsets endif endif endif return kTrue; 'saccade or bump are both true end 'MetricsBump '---------------------------------------------------- ' DetectaSecondEvent 'Dectect the next Adaptive or Corrective Saccade ' '< 3/10/04 '---------------------------------------------------- proc DetectaSecondEvent(sTime, eTime) var aResult, aHTargetData[40], aVTargetData[40]; DetectaTarget(gEarliestOnset - k20ms, gLatestOffset + 0.030, pTargetThreshold, zTargetStepTime, zTarget%); MetricsTarget(zTarget%,zTargetStepTime,zHTargetBegPos,zVTargetBegPos,zHTargetEndPos,zVTargetEndPos,zHTargetStepAmp,zVTargetStepAmp,zTargetTheta,zTargetRadius); DetectaSecSaccade(sTime, eTime, 1, 5); if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then DetectaSecSaccade(sTime, eTime, 2, 6); endif end 'DetectaSecondEvent '---------------------------------------------------- ' DetectaSecSaccade 'Saccade detection for manual and automatic modes ' 2/2/06 '---------------------------------------------------- proc DetectaSecSaccade(aBeg, aEnd, a, b); var aRecSumVelBeg, aRecSumVelEnd, cThreshold, dThreshold, aSacTime; 'detect a peak velocity aSacTime := ChanSearch(chmRecSumSacVel%[a], 4, aBeg, aEnd, pDetectaSaccadeVelThreshold); if aSacTime >= 0 then 'detect beginning and ending of the peak velocity aRecSumVelBeg := ChanSearch(chmRecSumSacVel%[a], 8, aSacTime, aSacTime-0.1, pHVonOffSaccadeThreshold); aRecSumVelEnd := ChanSearch(chmRecSumSacVel%[a], 8, aSacTime, aSacTime+0.1, pHVonOffSaccadeThreshold); 'if (aRecSumVelBeg >= 0) or (aRecSumVelEnd >= 0) then if (aRecSumVelBeg >= 0) and (aRecSumVelEnd >= 0) then '5.5.06 'compute metrics gHESaccadeExist%[b] := MetricsPrimarySaccade(gPeakHEvelTime[b], gHEonsetTime[b], gHEoffsetTime[b], cThreshold, dThreshold, chmAbsHEvel%[a], aRecSumVelBeg, aRecSumVelEnd); gVESaccadeExist%[b] := MetricsPrimarySaccade(gPeakVEvelTime[b], gVEonsetTime[b], gVEoffsetTime[b], cThreshold, dThreshold, chmAbsVEvel%[a], aRecSumVelBeg, aRecSumVelEnd); gSaccadeExist%[b] := gHESaccadeExist%[b] + gVESaccadeExist%[b]; 'Saccade exists if value > 0 endif endif end 'DetectaSecSaccade '---------------------------------------------------- ' MetricsSecSaccade ' 2/2/06 '---------------------------------------------------- proc MetricsSecSaccade(a, b) 'a=data channel b=parameter index var aHEposData[10], aHTposData[10], aVEposData[10], aVTposData[10], avgHEpos, avgHTpos, avgVEpos, avgVTpos, aNumPosData%, aTempDataLength%; 'Check HE movement data if gHESaccadeExist%[b] = 1 then gPeakHEvelocity[b] := ChanValue(chmHEvel%[a],gPeakHEvelTime[b]); gHEbegPos[b] := ChanValue(chHE%[a],gHEonsetTime[b]); gHEendPos[b] := ChanValue(chHE%[a],gHEoffsetTime[b]); gHEAmp[b] := gHEendPos[b] - gHEbegPos[b]; gHEDuration[b] := gHEoffsetTime[b] - gHEonsetTime[b]; else if gVESaccadeExist%[b]=1 then gHEbegPos[b] := ChanValue(chHE%[a],gVEonsetTime[b]); 'Set both these values at the onset of V saccade if no H saccade. gHEendPos[b] := gHEbegPos[b]; endif endif 'Check VE movement data if gVESaccadeExist%[b] = 1 then gPeakVEvelocity[b] := ChanValue(chmVEvel%[a],gPeakVEvelTime[b]); gVEbegPos[b] := ChanValue(chVE%[a],gVEonsetTime[b]); gVEendPos[b] := ChanValue(chVE%[a],gVEoffsetTime[b]); gVEamp[b] := gVEendPos[b] - gVEbegPos[b]; gVEDuration[b] := gVEoffsetTime[b] - gVEonsetTime[b]; else if gHESaccadeExist%[b]=1 then gVEbegPos[b] := ChanValue(chVE%[a],gHEonsetTime[b]); 'Set both these values at the onset of H saccade if no V saccade. gVEendPos[b] := gVEbegPos[b]; endif endif 'Create polar data if (gHESaccadeExist%[b] + gVESaccadeExist%[b]) > 0 then 'At least one comp saccade exist 'Check for atan singularity at 90 and -90 if gHEAmp[b] = 0 then if gVEamp[b] > 0 then gPolarTheta[b] := 90; endif if gVEamp[b] < 0 then gPolarTheta[b] := -90; endif else gPolarTheta[b] := (180*ATan(gVEamp[b],gHEAmp[b]))/pi; endif if gPolarTheta[b] <0 then gPolarTheta[b] := 360+gPolarTheta[b]; endif gPolarRadius[b] := Sqrt((gVEamp[b]*gVEamp[b]) + (gHEAmp[b]*gHEAmp[b])); 'Compute polar velocity peak, mean and time 'Create polar trace aTempDataLength% := (zSaccadeDuration/BinSize(chHE%[a])) + (2*k20ms*kMS);'40; 'Add 40ms length var tempH[aTempDataLength%], tempV[aTempDataLength%]; ChanData(chHE%[a],tempH[],zEarliestOnset-k20ms,zLatestOffset+k20ms);'Read 20ms earlier and later ChanData(chVE%[a],tempV[],zEarliestOnset-k20ms,zLatestOffset+k20ms); ArrSub(tempH[],tempH[0]); 'Start from zero by substracting with first element ArrSub(tempV[],tempV[0]); ArrMul(tempH[],tempH[]); ArrMul(tempV[],tempV[]); 'Pythagorean ArrAdd(tempH[],tempV[]); 'result in tempH Sqrt(tempH[]); 'Polar trajectory in tempH ArrDiffRobi(tempH[], BinSize(chHE%[a])); 'tempH is velocity, because both H V start from zero, vel is always pos gPeakPolarVel[b] := tempH[Max(tempH[])]; gPeakPolarVelTime[b] := zEarliestOnset - k20ms + (Max(tempH[])*BinSize(chHE%[a])); ' '------------------------------------------- 'Compute error rel to target aNumPosData% := ChanData(chHE%[a],aHEposData[],zLatestOffset + gTimeToCheckEyeError, zLatestOffset + gTimeToCheckEyeError + 0.008); avgHEpos := ArrSum(aHEposData[:aNumPosData%])/aNumPosData%; aNumPosData% := ChanData(chHT%[a],aHTposData[],zLatestOffset + gTimeToCheckEyeError, zLatestOffset + gTimeToCheckEyeError + 0.008); avgHTpos := ArrSum(aHTposData[:aNumPosData%])/aNumPosData%; gHEerror[b] := avgHEpos - avgHTpos; aNumPosData% := ChanData(chVE%[a],aVEposData[],zLatestOffset + gTimeToCheckEyeError, zLatestOffset + gTimeToCheckEyeError + 0.008); avgVEpos := ArrSum(aVEposData[:aNumPosData%])/aNumPosData%; aNumPosData% := ChanData(chVT%[a],aVTposData[],zLatestOffset + gTimeToCheckEyeError, zLatestOffset + gTimeToCheckEyeError + 0.008); avgVTpos := ArrSum(aVTposData[:aNumPosData%])/aNumPosData%; gVEerror[b] := avgVEpos - avgVTpos; gPolarError[b] := sqrt((gHEerror[b]*gHEerror[b]) + (gVEerror[b]*gVEerror[b])); endif 'the end of the bigger if loop. end 'MetricsSecSaccade [1] [5] '---------------------------------------------------- ' MetricsTarget 'Measure the target step ' '< 3/10/04 '---------------------------------------------------- proc MetricsTarget(aTarget%,aStepTime,&aHBegPos,&aVBegPos,&aHEndPos,&aVEndPos,&aHStepAmp,&aVStepAmp,&aTheta,&aRadius) var aHTargetData[40], aVTargetData[40]; View(gViewData%); if aTarget% > 0 then 'Target found? ChanData(chHT%[1],aHTargetData[],aStepTime-0.019,aStepTime+k20ms); 'Read H Target Step ChanData(chVT%[1],aVTargetData[],aStepTime-0.019,aStepTime+k20ms); 'Read V Target Step aHBegPos := ArrSum(aHTargetData[0:8])/8; '8 Point average aVBegPos := ArrSum(aVTargetData[0:8])/8; '8 Point average aHEndPos := ArrSum(aHTargetData[29:8])/8; '8 Point average aVEndPos := ArrSum(aVTargetData[29:8])/8; '8 Point average aHStepAmp := aHEndPos - aHBegPos; aVStepAmp := aVEndPos - aVBegPos; aTheta := (180*ATan(aVStepAmp,aHStepAmp+0.000001))/pi; '0.000001 to avoid singularity if aTheta < 0 then aTheta := 360 + aTheta; endif aRadius := Sqrt((aVStepAmp*aVStepAmp) + (aHStepAmp*aHStepAmp)); endif end 'MetricsTarget '---------------------------------------------------- ' MetricsEyeAroundTarget 'Measure the target step ' '< 3/10/04 '---------------------------------------------------- proc MetricsEyeAroundTarget() var aHEyeData[40], aVEyeData[40]; if gTarget% > 0 then 'Target found View(gViewData%); ChanData(chHE%[1],aHEyeData[],gTargetStepTime-0.019,gTargetStepTime+k20ms); 'Read H eye ChanData(chVE%[1],aVEyeData[],gTargetStepTime-0.019,gTargetStepTime+k20ms); 'Read V eye gHEyePreTargetStepPos := ArrSum(aHEyeData[0:8])/8; '8 Point average gVEyePreTargetStepPos := ArrSum(aVEyeData[0:8])/8; '8 Point average endif end 'MetricsEyeAroundTarget '---------------------------------------------------- ' MetricsSaccade '< 3/10/04 '---------------------------------------------------- proc MetricsSaccade(aTrace%) var aTempDataLength%, aHEposData[10], aHTposData[10], aVEposData[10], aVTposData[10], avgHEpos, avgHTpos, avgVEpos, avgVTpos, aNumPosData%; 'Check HE movement data if gHEsaccadeExist%[aTrace%] = 1 then gPeakHEvelocity[aTrace%] := ChanValue(chmHEvel%[aTrace%],gPeakHEvelTime[aTrace%]); gHEbegPos[aTrace%] := ChanValue(chHE%[aTrace%],gHEonsetTime[aTrace%]); gHEendPos[aTrace%] := ChanValue(chHE%[aTrace%],gHEoffsetTime[aTrace%]); gHEamp[aTrace%] := gHEendPos[aTrace%] - gHEbegPos[aTrace%]; gHEDuration[aTrace%] := gHEoffsetTime[aTrace%] - gHEonsetTime[aTrace%]; else gPeakHEvelocity[aTrace%] := 0; gHEamp[aTrace%] := 0; gHEDuration[aTrace%] := 0; if gVEsaccadeExist%[aTrace%] = 1 then gHEbegPos[aTrace%] := ChanValue(chHE%[aTrace%],gVEonsetTime[aTrace%]); 'Set both these values at the onset of V saccade if no H saccade. gHEendPos[aTrace%] := gHEbegPos[aTrace%]; endif endif 'Check VE movement data if gVEsaccadeExist%[aTrace%] = 1 then gPeakVEvelocity[aTrace%] := ChanValue(chmVEvel%[aTrace%],gPeakVEvelTime[aTrace%]); gVEbegPos[aTrace%] := ChanValue(chVE%[aTrace%],gVEonsetTime[aTrace%]); gVEendPos[aTrace%] := ChanValue(chVE%[aTrace%],gVEoffsetTime[aTrace%]); gVEamp[aTrace%] := gVEendPos[aTrace%] - gVEbegPos[aTrace%]; gVEDuration[aTrace%] := gVEoffsetTime[aTrace%] - gVEonsetTime[aTrace%]; else gPeakVEvelocity[aTrace%] := 0; gVEamp[aTrace%] := 0; gVEDuration[aTrace%] := 0; if gHEsaccadeExist%[aTrace%] = 1 then gVEbegPos[aTrace%] := ChanValue(chVE%[aTrace%],gHEonsetTime[aTrace%]); 'Set both these values at the onset of H saccade if no V saccade. gVEendPos[aTrace%] := gVEbegPos[aTrace%]; endif endif 'Create polar data if (gHEsaccadeExist%[aTrace%] + gVEsaccadeExist%[aTrace%]) > 0 then 'At least one comp saccade exist 'Check for atan singularity at 90 and -90 if gHEamp[aTrace%] = 0 then if gVEamp[aTrace%] > 0 then gPolarTheta[aTrace%] := 90; endif if gVEamp[aTrace%] < 0 then gPolarTheta[aTrace%] := -90; endif else gPolarTheta[aTrace%] := (180*ATan(gVEamp[aTrace%],gHEamp[aTrace%]))/pi; endif if gPolarTheta[aTrace%] <0 then gPolarTheta[aTrace%] := 360+gPolarTheta[aTrace%]; endif gPolarRadius[aTrace%] := Sqrt((gVEamp[aTrace%]*gVEamp[aTrace%]) + (gHEamp[aTrace%]*gHEamp[aTrace%])); '------------------------------------------- 'Compute polar velocity peak, mean and time gMeanPeakPolarVel := gPolarRadius[aTrace%]/gSaccadeDuration; 'Create polar trace aTempDataLength% := (gSaccadeDuration/BinSize(chHE%[aTrace%])) + (2*k20ms*kMS);'40; 'Add 40ms length var tempH[aTempDataLength%], tempV[aTempDataLength%], aPeakIndex, aPolarOnsetIndex, aPolarOffsetIndex, i%; ChanData(chHE%[aTrace%],tempH[],gEarliestOnset-k20ms,gLatestOffset+k20ms); 'Read 20ms earlier and later ChanData(chVE%[aTrace%],tempV[],gEarliestOnset-k20ms,gLatestOffset+k20ms); ArrSub(tempH[],tempH[0]); 'Start from zero by substracting with first element ArrSub(tempV[],tempV[0]); ArrMul(tempH[],tempH[]); ArrMul(tempV[],tempV[]); 'Pythagorean ArrAdd(tempH[],tempV[]); 'result in tempH Sqrt(tempH[]); 'Polar trajectory in tempH ArrDiffRobi(tempH[], BinSize(chHE%[aTrace%])); 'tempH is velocity, because both H V start from zero, vel is always pos aPeakIndex := Max(tempH[]); gPeakPolarVel[aTrace%] := tempH[aPeakIndex]; gPeakPolarVelTime[aTrace%] := gEarliestOnset - k20ms + (aPeakIndex*BinSize(chHE%[aTrace%])); 'locate the polar vel ONset here i% := aPeakIndex; aPolarOnsetIndex := NaN; while (i% >= 0) and (aPolarOnsetIndex = NaN) do if tempH[i%] <= pHVonOffSaccadeThreshold then aPolarOnsetIndex := i%; gPolarVelPrePeakAccel[aTrace%] := ((gPeakPolarVel[aTrace%]-tempH[i%])/(aPeakIndex-aPolarOnsetIndex))*kMS; 'results in d/s/s endif i% := i% - 1; wend 'locate the polar vel OFFset here i% := aPeakIndex; aPolarOffsetIndex := NaN; while (i% < aTempDataLength%) and (aPolarOffsetIndex = NaN) do if tempH[i%] <= pHVonOffSaccadeThreshold then aPolarOffsetIndex := i%; gPolarVelPostPeakAccel[aTrace%] := ((gPeakPolarVel[aTrace%]-tempH[i%])/(aPolarOnsetIndex-aPeakIndex))*kMS; 'results in d/s/s endif i% := i% + 1; wend '------------------------------------------- 'Compute error rel to target aNumPosData% := ChanData(chHE%[aTrace%],aHEposData[],gLatestOffset + gTimeToCheckEyeError, gLatestOffset + gTimeToCheckEyeError + 0.008); avgHEpos := ArrSum(aHEposData[:aNumPosData%])/aNumPosData%; aNumPosData% := ChanData(chHT%[1],aHTposData[],gLatestOffset + gTimeToCheckEyeError, gLatestOffset + gTimeToCheckEyeError + 0.008); avgHTpos := ArrSum(aHTposData[:aNumPosData%])/aNumPosData%; gHEerror[aTrace%] := avgHEpos - avgHTpos; aNumPosData% := ChanData(chVE%[aTrace%],aVEposData[],gLatestOffset + gTimeToCheckEyeError, gLatestOffset + gTimeToCheckEyeError + 0.008); avgVEpos := ArrSum(aVEposData[:aNumPosData%])/aNumPosData%; aNumPosData% := ChanData(chVT%[1],aVTposData[],gLatestOffset + gTimeToCheckEyeError, gLatestOffset + gTimeToCheckEyeError + 0.008); avgVTpos := ArrSum(aVTposData[:aNumPosData%])/aNumPosData%; gVEerror[aTrace%] := avgVEpos - avgVTpos; gPolarError[aTrace%] := sqrt((gHEerror[aTrace%]*gHEerror[aTrace%]) + (gVEerror[aTrace%]*gVEerror[aTrace%])); 'Gain useful for adaptation if gTarget%=1 then if Abs(gHTargetStepAmp) < 0.001 then gHGain[aTrace%] := NaN; else gHGain[aTrace%] := gHEamp[aTrace%]/gHTargetStepAmp; endif if Abs(gVTargetStepAmp) < 0.001 then gVGain[aTrace%] := NaN; else gVGain[aTrace%] := gVEamp[aTrace%]/gVTargetStepAmp; endif if Abs(gTargetRadius) < 0.001 then gPolarGain[aTrace%] :=NaN; else gPolarGain[aTrace%] := gPolarRadius[aTrace%]/gTargetRadius; endif else 'No Target, no gain gHGain[aTrace%] := NaN; gVGain[aTrace%] := NaN; gPolarGain[aTrace%] := NaN; endif else 'No saccade gPolarTheta[aTrace%] := NaN; gPolarRadius[aTrace%] := 0; gSaccadeDuration := NaN; endif 'the end of the bigger if loop. end 'MetricsSaccade '---------------------------------------------------- ' HighlightPrimary 'Set marks and optimize ranges ' '< 3/10/04 '---------------------------------------------------- proc HighlightPrimary() var aMinVal, aMaxVal, aMax[7+1], aMin[7+1], aIndex, aShown%, a,b,i%, a%; View(gViewData%); XRange(gEarlyTime,gLateTime); if gTarget%=1 then MemSetItem(chmMarkerHTarget%,0,gTargetStepTime-0.017,gHTargetBegPos); 'Mark HE target start MemSetItem(chmMarkerHTarget%,0,gTargetStepTime,ChanValue(chHT%[1],gTargetStepTime)); 'Mark HE Target Start Time MemSetItem(chmMarkerHTarget%,0,gTargetStepTime+0.017,gHTargetEndPos); 'Mark HE target end MemSetItem(chmMarkerVTarget%,0,gTargetStepTime-0.017,gVTargetBegPos); 'Mark VE target start MemSetItem(chmMarkerVTarget%,0,gTargetStepTime,ChanValue(chVT%[1],gTargetStepTime)); 'Mark HE Target Start Time MemSetItem(chmMarkerVTarget%,0,gTargetStepTime+0.017,gVTargetEndPos); 'Mark VE target end endif 'Don't mark target if none for i% := 1 to kCh2Analyze do '3 do if gHEsaccadeExist%[i%] = 1 then MemSetItem(chmMarkerHEye%[i%],0,gHEonsetTime[i%],gHEbegPos[i%]); 'Mark HE start MemSetItem(chmMarkerHEye%[i%],0,gHEoffsetTime[i%],gHEendPos[i%]); 'Mark HE end MemSetItem(chmHEpeakVel%[i%],0,gPeakHEvelTime[i%],gPeakHEvelocity[i%]); 'Mark Peak HE vel endif 'Don't mark if no HE saccade or HE second eye if gVEsaccadeExist%[i%] = 1 then MemSetItem(chmMarkerVEye%[i%],0,gVEonsetTime[i%],gVEbegPos[i%]); 'Mark VE start MemSetItem(chmMarkerVEye%[i%],0,gVEoffsetTime[i%],gVEendPos[i%]); 'Mark VE end MemSetItem(chmVEpeakVel%[i%],0,gPeakVEvelTime[i%],gPeakVEvelocity[i%]); 'Mark Peak VE vel endif 'Don't mark if no HE saccade or HE second eye next if pOptimize = 1 then var aTempData[round((gLateTime-gEarlyTime))/BinSize(chHE%[1])];' gTempDataLength% := 0 + ((gLateTime-gEarlyTime))/aBinSizeData; 'Adjust Yrange for horizontal position traces arrconst(aMin[],0); arrconst(aMax[],0); MinMax(chHE%[1], gEarlyTime, gLateTime, aMin[1], aMax[1]); 'find the min and max over a specified range of a trace MinMax(chHT%[1], gEarlyTime, gLateTime, aMin[2], aMax[2]); if chHE%[2] > 0 then MinMax(chHE%[2], gEarlyTime, gLateTime, aMin[3], aMax[3]); endif if chHE%[3] > 0 then MinMax(chHE%[3], gEarlyTime, gLateTime, aMin[4], aMax[4]); endif aMinVal := Min(aMin[1],aMin[2],aMin[3],aMin[4])-3; aMaxVal := Max(aMax[1],aMax[2],aMax[3],aMax[4])+3; for i% := 1 to kCh2Analyze do '3 do if chHE%[i%] > 0 then YRange(chHE%[i%],aMinVal,aMaxVal); YRange(chmMarkerHEye%[i%],aMinVal,aMaxVal); endif next YRange(chHT%[1],aMinVal,aMaxVal); YRange(chmMarkerHTarget%,aMinVal,aMaxVal); 'Adjust Yrange for horizonal velocity traces if (pAnalysisType% = kGazeAnalysis%) then 'set the velocity traces to a common optimized scale arrconst(aMin[],0); arrconst(aMax[],0); for i% := 1 to kCh2Analyze do '3 do if chmHEvel%[i%] > 0 then MinMax(chmHEvel%[i%], gEarlyTime, gLateTime, aMin[i%], aMax[i%]); 'find the min and max over a specified range of a trace endif next aMinVal := Min(aMin[1],aMin[2],aMin[3])-100; aMaxVal := Max(aMax[1],aMax[2],aMax[3])+100; for i% := 1 to kCh2Analyze do '3 do if chmHEvel%[i%] > 0 then YRange(chmHEvel%[i%],aMinVal,aMaxVal); YRange(chmHEpeakVel%[i%],aMinVal,aMaxVal); endif next else 'each velocity trace is set to its own optimized scale for i% := 1 to kCh2Analyze do '3 do if chmHEvel%[i%] > 0 then ChanData(chmHEvel%[i%],aTempData[],gEarlyTime, gLateTime); YRange(chmHEvel%[i%],aTempData[Min(aTempData[])]-100,aTempData[Max(aTempData[])]+100); YRange(chmHEpeakVel%[i%],aTempData[Min(aTempData[])]-100,aTempData[Max(aTempData[])]+100); endif next endif 'Adjust Yrange for vertical position traces arrconst(aMin[],0); arrconst(aMax[],0); MinMax(chVE%[1], gEarlyTime, gLateTime, aMin[1], aMax[1]); 'find the min and max over a specified range of a trace MinMax(chVT%[1], gEarlyTime, gLateTime, aMin[2], aMax[2]); if chVE%[2] > 0 then MinMax(chVE%[2], gEarlyTime, gLateTime, aMin[3], aMax[3]); endif if chVE%[3] > 0 then MinMax(chVE%[3], gEarlyTime, gLateTime, aMin[4], aMax[4]); endif aMinVal := Min(aMin[1],aMin[2],aMin[3],aMin[4])-3; aMaxVal := Max(aMax[1],aMax[2],aMax[3],aMax[4])+3; for i% := 1 to kCh2Analyze do '3 do if chVE%[i%] > 0 then YRange(chVE%[i%],aMinVal,aMaxVal); YRange(chmMarkerVEye%[i%],aMinVal,aMaxVal); endif next YRange(chVT%[1],aMinVal,aMaxVal); YRange(chmMarkerVTarget%,aMinVal,aMaxVal); 'Adjust Yrange for vertical velocity traces if (pAnalysisType% = kGazeAnalysis%) then 'set the velocity traces to a common optimized scale arrconst(aMin[],0); arrconst(aMax[],0); for i% := 1 to kCh2Analyze do '3 do if chmVEvel%[i%] > 0 then MinMax(chmVEvel%[i%], gEarlyTime, gLateTime, aMin[i%], aMax[i%]); 'find the min and max over a specified range of a trace endif next aMinVal := Min(aMin[1],aMin[2],aMin[3])-100; aMaxVal := Max(aMax[1],aMax[2],aMax[3])+100; for i% := 1 to kCh2Analyze do '3 do if chmVEvel%[i%] > 0 then YRange(chmVEvel%[i%],aMinVal,aMaxVal); YRange(chmVEpeakVel%[i%],aMinVal,aMaxVal); endif next else 'each velocity trace is set to its own optimized scale for i% := 1 to kCh2Analyze do '3 do if chmVEvel%[i%] > 0 then ChanData(chmVEvel%[i%],aTempData[],gEarlyTime, gLateTime); YRange(chmVEvel%[i%],aTempData[Min(aTempData[])]-100,aTempData[Max(aTempData[])]+100); YRange(chmVEpeakVel%[i%],aTempData[Min(aTempData[])]-100,aTempData[Max(aTempData[])]+100); endif next endif endif 'S A V E 'Yield(); 'allows the traces to be drawn during automatic analysis mode 'S A V E end 'HighlightPrimary '---------------------------------------------------- ' CursorOnsetOffset 'Display the onset and offset of the saccade by using 'vertical cursors 8 and 9. ' ' 10/3/05 '---------------------------------------------------- proc CursorOnsetOffset() if (gAutoAnalysis% = 0) and (gEditMode% = 0) then CursorVisible(-1,0); Cursor(8,gEarliestOnset); Cursor(9,gLatestOffset); CursorVisible(8,1); CursorVisible(9,1); endif end 'CursorOnsetOffset '---------------------------------------------------- ' HighlightSecondary 'Put the second event analysis marks on the trace. ' '< 3/10/04 '---------------------------------------------------- proc HighlightSecondary() View(gViewData%); XRange(gEarlyTime,gLateTime); 'adjust the width of time displayed (2/7/06 necessary?) if zTarget%=1 then MemSetItem(chmMarkerHTarget%, 0, zTargetStepTime-0.017, zHTargetBegPos); 'Mark HE target start MemSetItem(chmMarkerHTarget%, 0, zTargetStepTime, ChanValue(chHT%[1], zTargetStepTime)); 'Mark HE Target Start Time MemSetItem(chmMarkerHTarget%, 0, zTargetStepTime+0.017, zHTargetEndPos); 'Mark HE target end MemSetItem(chmMarkerVTarget%, 0, zTargetStepTime-0.017, zVTargetBegPos); 'Mark Vtarget start MemSetItem(chmMarkerVTarget%, 0, zTargetStepTime, ChanValue(chVT%[1], zTargetStepTime)); 'Mark HTarget Start Time MemSetItem(chmMarkerVTarget%, 0, zTargetStepTime+0.017, zVTargetEndPos); 'Mark Vtarget end endif 'Don't mark target if none 'Add Horizontal analysis marks if gHESaccadeExist%[5] = 1 then MemSetItem(chmMarkerHEye%[1], 0, gHEonsetTime[5], gHEbegPos[5]); 'Mark HE start MemSetItem(chmMarkerHEye%[1], 0, gHEoffsetTime[5], gHEendPos[5]); 'Mark HE end MemSetItem(chmHEpeakVel%[1], 0, gPeakHEvelTime[5], gPeakHEvelocity[5]); 'Mark Peak HE vel endif 'Don't mark if no HE saccade 'Add Vertical analysis marks if gVESaccadeExist%[5]=1 then MemSetItem(chmMarkerVEye%[1], 0, gVEonsetTime[5], gVEbegPos[5]); 'Mark VE start MemSetItem(chmMarkerVEye%[1], 0, gVEoffsetTime[5], gVEendPos[5]); 'Mark VE end MemSetItem(chmVEpeakVel%[1], 0, gPeakVEvelTime[5], gPeakVEvelocity[5]); 'Mark Peak VE vel endif 'Don't mark if no VE saccade 'Add Horizontal analysis marks if gHESaccadeExist%[6] = 1 then MemSetItem(chmMarkerHEye%[2], 0, gHEonsetTime[6], gHEbegPos[6]); 'Mark HE start MemSetItem(chmMarkerHEye%[2], 0, gHEoffsetTime[6], gHEendPos[6]); 'Mark HE end MemSetItem(chmHEpeakVel%[2], 0, gPeakHEvelTime[6], gPeakHEvelocity[6]); 'Mark Peak HE vel endif 'Don't mark if no HE saccade 'Add Vertical analysis marks if gVESaccadeExist%[6]=1 then MemSetItem(chmMarkerVEye%[2], 0, gVEonsetTime[6], gVEbegPos[6]); 'Mark VE start MemSetItem(chmMarkerVEye%[2], 0, gVEoffsetTime[6], gVEendPos[6]); 'Mark VE end MemSetItem(chmVEpeakVel%[2], 0, gPeakVEvelTime[6], gPeakVEvelocity[6]); 'Mark Peak VE vel endif 'Don't mark if no VE saccade end 'HighlightSecondary '---------------------------------------------------- ' Abs2Rel 'Tests if in-coming argument is NaN, if not it will 'convert the absolute time to time relative to the 'earliest saccade onset time. ' ' 11/2/05 '---------------------------------------------------- func Abs2Rel(aValue); if aValue = NaN then return aValue; else return (aValue-gEarliestOnset) * kMS; endif end 'Abs2Rel '---------------------------------------------------- ' Dec2Msec 'Tests if in-coming argument is NaN, if not it will 'convert a decimal time to time in MS. ' 11/2/05 '---------------------------------------------------- func Dec2Msec(aValue); if aValue = NaN then return aValue; else return aValue * kMS; endif end 'Dec2Msec '---------------------------------------------------- ' RelBurst 'Tests if in-coming argument is NaN or if the burst 'start time is valid. If all is okay it will compute 'latency relative to burst. ' 11/2/05 '---------------------------------------------------- func RelBurst(aValue); docase case aValue = NaN then return NaN; case gBurstStartTime = NaN then return NaN else return aValue - Abs2Rel(gBurstStartTime);; endcase end 'RelBurst '---------------------------------------------------- ' AttributeName 'Load the attribute labels. These labels are used in 'this program and passed on to the Graph program for 'use there. ' '1. The list of attribute names will not change 'except to get longer. New attributes as 'they are added, will be tacked on the end of the 'list. ' '2. There will be only one list of attributes. All 'analysis types will share this list so there 'clusters of related attributes may be spread over 'the list. No effort will be made to organize the 'list according to analysis type since this sets up 'future incompatibilities. ' '< 3/10/04 '---------------------------------------------------- proc AttributeName() var AB$ := "AB", CD$ := "CD", EF$ := "EF"; docase case (pAnalysisType% = kVergenceAnalysis%) then AB$ := "Eye"; CD$ := "Eye2"; EF$ := "Vergence"; case (pAnalysisType% = kGazeAnalysis%) then AB$ := "Gaze"; CD$ := "Head"; EF$ := "EIH"; else AB$ := "Eye"; CD$ := "CD"; EF$ := "EF"; endcase '--------------------------------------------------------------------------- ' beg of AB attributes gAttrNam$[000] := "Target: absolute step time"; gAttrNam$[001] := AB$+": horz start time"; gAttrNam$[002] := AB$+": horz start pos"; gAttrNam$[003] := AB$+": horz end time"; gAttrNam$[004] := AB$+": horz end pos"; gAttrNam$[005] := AB$+": vert start time"; gAttrNam$[006] := AB$+": vert start pos"; gAttrNam$[007] := AB$+": vert end time"; gAttrNam$[008] := AB$+": vert end pos"; gAttrNam$[009] := AB$+": horz peak velocity time"; gAttrNam$[010] := AB$+": horz peak velocity"; gAttrNam$[011] := AB$+": vert peak velocity time"; gAttrNam$[012] := AB$+": vert peak velocity"; gAttrNam$[013] := "Burst: start time"; gAttrNam$[014] := "Burst: end time"; gAttrNam$[015] := AB$+": horz amp"; gAttrNam$[016] := AB$+": vert amp"; gAttrNam$[017] := AB$+": HV R"; gAttrNam$[018] := AB$+": HV theta"; gAttrNam$[019] := "Burst: duration"; gAttrNam$[020] := AB$+"-burst: horz latency"; gAttrNam$[021] := AB$+"-burst: vert latency"; gAttrNam$[022] := "Saccade: absolute onset"; gAttrNam$[023] := "Burst: num spikes"; gAttrNam$[024] := AB$+": horz duration"; gAttrNam$[025] := AB$+": vert duration"; gAttrNam$[026] := "Saccade: total duration"; gAttrNam$[027] := "Burst: average frequency"; gAttrNam$[028] := "Burst: peak 2-spike frequency time"; gAttrNam$[029] := "Burst: peak 2-spike frequency"; gAttrNam$[030] := AB$+": Peak polar velocity time"; gAttrNam$[031] := AB$+": Peak polar velocity"; gAttrNam$[032] := "Burst: max 5-spike average frequency"; gAttrNam$[033] := "Saccade: start time"; gAttrNam$[034] := "Burst: max 5-spike average frequency time"; gAttrNam$[035] := "Tonic: frequency before burst"; gAttrNam$[036] := "Tonic: first spike time"; gAttrNam$[037] := "Peak frequency minus pre-frequency"; gAttrNam$[038] := "Tonic: frequency after burst"; gAttrNam$[039] := "Display: left edge of screen time"; gAttrNam$[040] := "Burst: hand analyzed (> 0 means yes)"; gAttrNam$[041] := "Tonic: num spikes before burst"; gAttrNam$[042] := "Tonic: num spikes after burst"; gAttrNam$[043] := "Horiz &/or Vert target start time (-reaction time)"; gAttrNam$[044] := "Target: horz start pos"; gAttrNam$[045] := "Target: horz end pos"; gAttrNam$[046] := "Target: vert start pos"; gAttrNam$[047] := "Target: vert end pos"; gAttrNam$[048] := "Tonic: duration before burst"; gAttrNam$[049] := "Tonic: duration after burst"; gAttrNam$[050] := AB$+": horz degrees off-target before step"; gAttrNam$[051] := AB$+": vert degrees off-target before step"; gAttrNam$[052] := "u n a s s i g n e d"; gAttrNam$[053] := "u n a s s i g n e d"; gAttrNam$[054] := "Target: horz step amp"; gAttrNam$[055] := "Target: vert step amp"; gAttrNam$[056] := "Target: HV R"; gAttrNam$[057] := "Target: theta"; gAttrNam$[058] := "Gain "+AB$+": horz"; gAttrNam$[059] := "Gain "+AB$+": vert"; gAttrNam$[060] := "Gain "+AB$+": polar"; gAttrNam$[061] := "Display: right edge of screen time"; gAttrNam$[062] := "Burst: peak spike density"; gAttrNam$[063] := "Burst: peak spike density time"; gAttrNam$[064] := "Tonic: end time"; gAttrNam$[065] := "Visual: burst latency"; gAttrNam$[066] := "Visual: burst duration"; gAttrNam$[067] := "Visual: burst spike num"; gAttrNam$[068] := "Visual: burst peak frequency"; gAttrNam$[069] := "Visual: burst peak frequency latency"; gAttrNam$[070] := "Burst: num spikes between visual and saccadic burst onset"; gAttrNam$[071] := "Analysis tag (bookmark feature in Graph)"; gAttrNam$[072] := "Error "+AB$+": horz"; gAttrNam$[073] := "Error "+AB$+": vert"; gAttrNam$[074] := "Error "+AB$+": polar"; gAttrNam$[075] := "Second Saccade "+AB$+": start time"; gAttrNam$[076] := "Second Saccade "+AB$+": end time"; gAttrNam$[077] := "Second Saccade "+AB$+": horz amp"; gAttrNam$[078] := "Second Saccade "+AB$+": horz start pos"; gAttrNam$[079] := "Second Saccade "+AB$+": horz start time"; gAttrNam$[080] := "Second Saccade "+AB$+": horz end pos"; gAttrNam$[081] := "Second Saccade "+AB$+": horz end time"; gAttrNam$[082] := "Second Saccade "+AB$+": horz duration"; gAttrNam$[083] := "Second Saccade "+AB$+": horz peak velocity"; gAttrNam$[084] := "Second Saccade "+AB$+": horz peak velocity time"; gAttrNam$[085] := "Second Saccade "+AB$+": vert amp"; gAttrNam$[086] := "Second Saccade "+AB$+": vert start pos"; gAttrNam$[087] := "Second Saccade "+AB$+": vert start time"; gAttrNam$[088] := "Second Saccade "+AB$+": vert end pos"; gAttrNam$[089] := "Second Saccade "+AB$+": vert end time"; gAttrNam$[090] := "Second Saccade "+AB$+": vert duration"; gAttrNam$[091] := "Second Saccade "+AB$+": vert peak velocity"; gAttrNam$[092] := "Second Saccade "+AB$+": vert peak velocity time"; gAttrNam$[093] := "Second Saccade "+AB$+": HV R"; gAttrNam$[094] := "Second Saccade "+AB$+": HV theta"; gAttrNam$[095] := "Second Saccade "+AB$+": polar peak velocity"; gAttrNam$[096] := "Second Saccade "+AB$+": polar peak velocity time"; gAttrNam$[097] := "Second Step Target: step time"; gAttrNam$[098] := "Second Step Target: horz amp"; gAttrNam$[099] := "Second Step Target: horz start pos"; gAttrNam$[100] := "Second Step Target: horz end pos"; gAttrNam$[101] := "Second Step Target: vert amp"; gAttrNam$[102] := "Second Step Target: vert start pos"; gAttrNam$[103] := "Second Step Target: vert end pos"; gAttrNam$[104] := "Second Step Target: HV R"; gAttrNam$[105] := "Second Step Target: HV theta"; gAttrNam$[106] := "Second Saccade "+AB$+": horz error"; gAttrNam$[107] := "Second Saccade "+AB$+": vert error"; gAttrNam$[108] := "Second Saccade "+AB$+": polar error"; gAttrNam$[109] := "Second Saccade "+AB$+": interval between first and second saccade"; gAttrNam$[110] := "RatePos: num spikes before"; gAttrNam$[111] := "RatePos: firing duration before"; gAttrNam$[112] := "RatePos: frequency before"; gAttrNam$[113] := "RatePos "+AB$+": avg horz pos before burst"; gAttrNam$[114] := "RatePos "+AB$+": avg vert pos before burst"; gAttrNam$[115] := "RatePos: num spikes after"; gAttrNam$[116] := "RatePos: firing duration after"; gAttrNam$[117] := "RatePos: frequency after"; gAttrNam$[118] := "RatePos "+AB$+": avg horz pos after burst"; gAttrNam$[119] := "RatePos "+AB$+": avg vert pos after burst"; gAttrNam$[120] := "Tonic: last spike time"; gAttrNam$[121] := "Analysis code: (traces | search | analysis | cell)"; gAttrNam$[122] := "User-specified end-of-analysis time"; gAttrNam$[123] := AB$+": horz pos pre-target step"; gAttrNam$[124] := AB$+": vert pos pre-target step"; ' end of AB attributes '--------------------------------------------------------------------------- '--------------------------------------------------------------------------- ' beg of CD attributes gAttrNam$[125] := CD$+": horz start time"; gAttrNam$[126] := CD$+": horz start pos"; gAttrNam$[127] := CD$+": horz end time"; gAttrNam$[128] := CD$+": horz end pos"; gAttrNam$[129] := CD$+": vert start time"; gAttrNam$[130] := CD$+": vert start pos"; gAttrNam$[131] := CD$+": vert end time"; gAttrNam$[132] := CD$+": vert end pos"; gAttrNam$[133] := CD$+": horz peak velocity time"; gAttrNam$[134] := CD$+": horz peak velocity"; gAttrNam$[135] := CD$+": vert peak velocity time"; gAttrNam$[136] := CD$+": vert peak velocity"; gAttrNam$[137] := CD$+": horz amp"; gAttrNam$[138] := CD$+": vert amp"; gAttrNam$[139] := CD$+": HV R"; gAttrNam$[140] := CD$+": HV theta"; gAttrNam$[141] := CD$+"-burst horz latency"; gAttrNam$[142] := CD$+"-burst vert latency"; gAttrNam$[143] := CD$+": horz duration"; gAttrNam$[144] := CD$+": vert duration"; gAttrNam$[145] := CD$+": peak polar velocity time"; gAttrNam$[146] := CD$+": peak polar velocity"; gAttrNam$[147] := "RatePos "+CD$+": avg horz pos before burst"; gAttrNam$[148] := "RatePos "+CD$+": avg vert pos before burst"; gAttrNam$[149] := "RatePos "+CD$+": avg horz pos after burst"; gAttrNam$[150] := "RatePos "+CD$+": avg vert pos after burst"; gAttrNam$[151] := "Gain "+CD$+": horz"; gAttrNam$[152] := "Gain "+CD$+": vert"; gAttrNam$[153] := "Gain "+CD$+": polar"; gAttrNam$[154] := "Error "+CD$+": horz"; gAttrNam$[155] := "Error "+CD$+": vert"; gAttrNam$[156] := "Error "+CD$+": polar"; gAttrNam$[157] := "Second Saccade "+CD$+": start time"; gAttrNam$[158] := "Second Saccade "+CD$+": end time"; gAttrNam$[159] := "Second Saccade "+CD$+": horz amp"; gAttrNam$[160] := "Second Saccade "+CD$+": horz eye start pos"; gAttrNam$[161] := "Second Saccade "+CD$+": horz eye start time"; gAttrNam$[162] := "Second Saccade "+CD$+": horz eye end pos"; gAttrNam$[163] := "Second Saccade "+CD$+": horz eye end time"; gAttrNam$[164] := "Second Saccade "+CD$+": horz duration"; gAttrNam$[165] := "Second Saccade "+CD$+": horz peak eye velocity"; gAttrNam$[166] := "Second Saccade "+CD$+": horz peak eye velocity time"; gAttrNam$[167] := "Second Saccade "+CD$+": vert amp"; gAttrNam$[168] := "Second Saccade "+CD$+": vert eye start pos"; gAttrNam$[169] := "Second Saccade "+CD$+": vert eye start time"; gAttrNam$[170] := "Second Saccade "+CD$+": vert eye end pos"; gAttrNam$[171] := "Second Saccade "+CD$+": vert eye end time"; gAttrNam$[172] := "Second Saccade "+CD$+": vert duration"; gAttrNam$[173] := "Second Saccade "+CD$+": vert peak eye velocity"; gAttrNam$[174] := "Second Saccade "+CD$+": vert peak eye velocity time"; gAttrNam$[175] := "Second Saccade "+CD$+": HV R"; gAttrNam$[176] := "Second Saccade "+CD$+": HV theta"; gAttrNam$[177] := "Second Saccade "+CD$+": polar peak velocity"; gAttrNam$[178] := "Second Saccade "+CD$+": polar peak velocity time"; gAttrNam$[179] := "Second Saccade "+CD$+": horz error"; gAttrNam$[180] := "Second Saccade "+CD$+": vert error"; gAttrNam$[181] := "Second Saccade "+CD$+": polar error"; ' end of CD attributes '--------------------------------------------------------------------------- '--------------------------------------------------------------------------- ' beg of EF attributes gAttrNam$[182] := EF$+": horz start time"; gAttrNam$[183] := EF$+": horz start pos"; gAttrNam$[184] := EF$+": horz end time"; gAttrNam$[185] := EF$+": horz end pos"; gAttrNam$[186] := EF$+": vert start time"; gAttrNam$[187] := EF$+": vert start pos"; gAttrNam$[188] := EF$+": vert end time"; gAttrNam$[189] := EF$+": vert end pos"; gAttrNam$[190] := EF$+": horz peak velocity time"; gAttrNam$[191] := EF$+": horz peak velocity"; gAttrNam$[192] := EF$+": vert peak velocity time"; gAttrNam$[193] := EF$+": vert peak velocity"; gAttrNam$[194] := EF$+": horz amp"; gAttrNam$[195] := EF$+": vert amp"; gAttrNam$[196] := EF$+": HV R"; gAttrNam$[197] := EF$+": HV theta"; gAttrNam$[198] := EF$+"-burst horz latency"; gAttrNam$[199] := EF$+"-burst vert latency"; gAttrNam$[200] := EF$+": horz duration"; gAttrNam$[201] := EF$+": vert duration"; gAttrNam$[202] := EF$+": Peak polar velocity time"; gAttrNam$[203] := EF$+": Peak polar velocity"; gAttrNam$[204] := "RatePos "+EF$+": avg horz pos before burst"; gAttrNam$[205] := "RatePos "+EF$+": avg vert pos before burst"; gAttrNam$[206] := "RatePos "+EF$+": avg horz pos after burst"; gAttrNam$[207] := "RatePos "+EF$+": avg vert pos after burst"; gAttrNam$[208] := "Gain "+EF$+": horz"; gAttrNam$[209] := "Gain "+EF$+": vert"; gAttrNam$[210] := "Gain "+EF$+": polar"; gAttrNam$[211] := "Error "+EF$+": horz"; gAttrNam$[212] := "Error "+EF$+": vert"; gAttrNam$[213] := "Error "+EF$+": polar"; gAttrNam$[214] := "Second Saccade "+EF$+": start time"; gAttrNam$[215] := "Second Saccade "+EF$+": end time"; gAttrNam$[216] := "Second Saccade "+EF$+": horz amp"; gAttrNam$[217] := "Second Saccade "+EF$+": horz eye start pos"; gAttrNam$[218] := "Second Saccade "+EF$+": horz eye start time"; gAttrNam$[219] := "Second Saccade "+EF$+": horz eye end pos"; gAttrNam$[220] := "Second Saccade "+EF$+": horz eye end time"; gAttrNam$[221] := "Second Saccade "+EF$+": horz duration"; gAttrNam$[222] := "Second Saccade "+EF$+": horz peak eye velocity"; gAttrNam$[223] := "Second Saccade "+EF$+": horz peak eye velocity time"; gAttrNam$[224] := "Second Saccade "+EF$+": vert amp"; gAttrNam$[225] := "Second Saccade "+EF$+": vert eye start pos"; gAttrNam$[226] := "Second Saccade "+EF$+": vert eye start time"; gAttrNam$[227] := "Second Saccade "+EF$+": vert eye end pos"; gAttrNam$[228] := "Second Saccade "+EF$+": vert eye end time"; gAttrNam$[229] := "Second Saccade "+EF$+": vert duration"; gAttrNam$[230] := "Second Saccade "+EF$+": vert peak eye velocity"; gAttrNam$[231] := "Second Saccade "+EF$+": vert peak eye velocity time"; gAttrNam$[232] := "Second Saccade "+EF$+": HV R"; gAttrNam$[233] := "Second Saccade "+EF$+": HV theta"; gAttrNam$[234] := "Second Saccade "+EF$+": polar peak velocity"; gAttrNam$[235] := "Second Saccade "+EF$+": polar peak velocity time"; gAttrNam$[236] := "Second Saccade "+EF$+": horz error"; gAttrNam$[237] := "Second Saccade "+EF$+": vert error"; gAttrNam$[238] := "Second Saccade "+EF$+": polar error"; ' end of EF attributes '--------------------------------------------------------------------------- '--------------------------------------------------------------------------- ' beg of AB CD EF comparison attributes gAttrNam$[239] := "Horz "+AB$+" at start of "+CD$; gAttrNam$[240] := "Horz "+AB$+" at end of "+CD$; gAttrNam$[241] := "Horz "+AB$+" at start of "+EF$; gAttrNam$[242] := "Horz "+AB$+" at end of "+EF$; gAttrNam$[243] := "Vert "+AB$+" at start of "+CD$; gAttrNam$[244] := "Vert "+AB$+" at end of "+CD$; gAttrNam$[245] := "Vert "+AB$+" at start of "+EF$; gAttrNam$[246] := "Vert "+AB$+" at end of "+EF$; gAttrNam$[247] := "Horz "+CD$+" at start of "+AB$; gAttrNam$[248] := "Horz "+CD$+" at end of "+AB$; gAttrNam$[249] := "Horz "+CD$+" at start of "+EF$; gAttrNam$[250] := "Horz "+CD$+" at end of "+EF$; gAttrNam$[251] := "Vert "+CD$+" at start of "+AB$; gAttrNam$[252] := "Vert "+CD$+" at end of "+AB$; gAttrNam$[253] := "Vert "+CD$+" at start of "+EF$; gAttrNam$[254] := "Vert "+CD$+" at end of "+EF$; gAttrNam$[255] := "Horz "+EF$+" at start of "+AB$; gAttrNam$[256] := "Horz "+EF$+" at end of "+AB$; gAttrNam$[257] := "Horz "+EF$+" at start of "+CD$; gAttrNam$[258] := "Horz "+EF$+" at end of "+CD$; gAttrNam$[259] := "Vert "+EF$+" at start of "+AB$; gAttrNam$[260] := "Vert "+EF$+" at end of "+AB$; gAttrNam$[261] := "Vert "+EF$+" at start of "+CD$; gAttrNam$[262] := "Vert "+EF$+" at end of "+CD$; gAttrNam$[263] := AB$+": Peak polar velocity pre peak acceleration"; 'initial saccade gAttrNam$[264] := AB$+": Peak polar velocity post peak acceleration"; gAttrNam$[265] := CD$+": Peak polar velocity pre peak acceleration"; gAttrNam$[266] := CD$+": Peak polar velocity post peak acceleration"; gAttrNam$[267] := EF$+": Peak polar velocity pre peak acceleration"; gAttrNam$[268] := EF$+": Peak polar velocity post peak acceleration"; gAttrNam$[269] := AB$+": Peak polar velocity pre peak acceleration"; 'adaptive saccade gAttrNam$[270] := AB$+": Peak polar velocity post peak acceleration"; gAttrNam$[271] := CD$+": Peak polar velocity pre peak acceleration"; gAttrNam$[272] := CD$+": Peak polar velocity post peak acceleration"; gAttrNam$[273] := EF$+": Peak polar velocity pre peak acceleration"; gAttrNam$[274] := EF$+": Peak polar velocity post peak acceleration"; ' end of ABCDEF comparison attributes '--------------------------------------------------------------------------- end 'AttributeName '---------------------------------------------------- ' AttributeComputeAndShow '< 3/10/04 '---------------------------------------------------- proc AttributeComputeAndShow() 'initialize all the attributes to an invalid value arrconst(gAttrVal[gTrialAccepted%][],NaN); gAttrVal[gTrialAccepted%][000] := gTargetStepTime; gAttrVal[gTrialAccepted%][001] := Abs2Rel(gHEonsetTime[1]); gAttrVal[gTrialAccepted%][002] := gHEbegPos[1]; gAttrVal[gTrialAccepted%][003] := Abs2Rel(gHEoffsetTime[1]); gAttrVal[gTrialAccepted%][004] := gHEendPos[1]; gAttrVal[gTrialAccepted%][005] := Abs2Rel(gVEonsetTime[1]); gAttrVal[gTrialAccepted%][006] := gVEbegPos[1]; gAttrVal[gTrialAccepted%][007] := Abs2Rel(gVEoffsetTime[1]); gAttrVal[gTrialAccepted%][008] := gVEendPos[1]; gAttrVal[gTrialAccepted%][009] := Abs2Rel(gPeakHEvelTime[1]); gAttrVal[gTrialAccepted%][010] := gPeakHEvelocity[1]; gAttrVal[gTrialAccepted%][011] := Abs2Rel(gPeakVEvelTime[1]); gAttrVal[gTrialAccepted%][012] := gPeakVEvelocity[1]; gAttrVal[gTrialAccepted%][015] := gHEamp[1]; gAttrVal[gTrialAccepted%][016] := gVEamp[1]; gAttrVal[gTrialAccepted%][017] := gPolarRadius[1]; gAttrVal[gTrialAccepted%][018] := gPolarTheta[1]; gAttrVal[gTrialAccepted%][022] := gEarliestOnset; 'so I know when the saccade start in absolute time in second gAttrVal[gTrialAccepted%][024] := Dec2Msec(gHEDuration[1]); gAttrVal[gTrialAccepted%][025] := Dec2Msec(gVEDuration[1]); gAttrVal[gTrialAccepted%][026] := Dec2Msec(gSaccadeDuration); gAttrVal[gTrialAccepted%][030] := Abs2Rel(gPeakPolarVelTime[1]); gAttrVal[gTrialAccepted%][031] := gPeakPolarVel[1]; gAttrVal[gTrialAccepted%][033] := 0; 'always ZERO ! gAttrVal[gTrialAccepted%][039] := gEarlyTime; 'For display purposes gAttrVal[gTrialAccepted%][043] := Abs2Rel(gTargetStepTime); 'Target step time re. saccade onset (-rx time) gAttrVal[gTrialAccepted%][044] := gHTargetBegPos; gAttrVal[gTrialAccepted%][045] := gHTargetEndPos; gAttrVal[gTrialAccepted%][046] := gVTargetBegPos; gAttrVal[gTrialAccepted%][047] := gVTargetEndPos; gAttrVal[gTrialAccepted%][050] := gHEyePreTargetStepPos - gHTargetBegPos; gAttrVal[gTrialAccepted%][051] := gVEyePreTargetStepPos - gVTargetBegPos; '[052] unassigned '[053] unassigned gAttrVal[gTrialAccepted%][054] := gHTargetStepAmp; gAttrVal[gTrialAccepted%][055] := gVTargetStepAmp; gAttrVal[gTrialAccepted%][056] := gTargetRadius; gAttrVal[gTrialAccepted%][057] := gTargetTheta; gAttrVal[gTrialAccepted%][058] := gHGain[1]; gAttrVal[gTrialAccepted%][059] := gVGain[1]; gAttrVal[gTrialAccepted%][060] := gPolarGain[1]; gAttrVal[gTrialAccepted%][061] := gLateTime; gAttrVal[gTrialAccepted%][062] := gPeakSpikeDensity; gAttrVal[gTrialAccepted%][063] := Abs2Rel(gPeakSpikeDensityTime); gAttrVal[gTrialAccepted%][064] := Abs2Rel(gPostTonicEndTime); '[065] computed in Visual%() after the file has been analyzed '[066] computed in Visual%() after the file has been analyzed '[067] computed in Visual%() after the file has been analyzed '[068] computed in Visual%() after the file has been analyzed '[069] computed in Visual%() after the file has been analyzed '[070] computed in Visual%() after the file has been analyzed gAttrVal[gTrialAccepted%][071] := 0; 'initialize to zero Analysis Tag (Graph booking set by user in Graph) gAttrVal[gTrialAccepted%][072] := gHEerror[1]; gAttrVal[gTrialAccepted%][073] := gVEerror[1]; gAttrVal[gTrialAccepted%][074] := gPolarError[1]; gAttrVal[gTrialAccepted%][263] := gPolarVelPrePeakAccel[1]; 'AB gAttrVal[gTrialAccepted%][264] := gPolarVelPostPeakAccel[1]; if pAdaptType% > 0 then gAttrVal[gTrialAccepted%][075] := Abs2Rel(zEarliestOnset); gAttrVal[gTrialAccepted%][076] := Abs2Rel(zLatestOffset); gAttrVal[gTrialAccepted%][077] := gHEAmp[5]; gAttrVal[gTrialAccepted%][078] := gHEbegPos[5]; gAttrVal[gTrialAccepted%][079] := Abs2Rel(gHEonsetTime[5]); gAttrVal[gTrialAccepted%][080] := gHEendPos[5]; gAttrVal[gTrialAccepted%][081] := Abs2Rel(gHEoffsetTime[5]); gAttrVal[gTrialAccepted%][082] := Dec2Msec(gHEDuration[5]); gAttrVal[gTrialAccepted%][083] := gPeakHEvelocity[5]; gAttrVal[gTrialAccepted%][084] := Abs2Rel(gPeakHEvelTime[5]); gAttrVal[gTrialAccepted%][085] := gVEamp[5]; gAttrVal[gTrialAccepted%][086] := gVEbegPos[5]; gAttrVal[gTrialAccepted%][087] := Abs2Rel(gVEonsetTime[5]); gAttrVal[gTrialAccepted%][088] := gVEendPos[5]; gAttrVal[gTrialAccepted%][089] := Abs2Rel(gVEoffsetTime[5]); gAttrVal[gTrialAccepted%][090] := Dec2Msec(gVEDuration[5]); gAttrVal[gTrialAccepted%][091] := gPeakVEvelocity[5]; gAttrVal[gTrialAccepted%][092] := Abs2Rel(gPeakVEvelTime[5]); gAttrVal[gTrialAccepted%][093] := gPolarRadius[5]; gAttrVal[gTrialAccepted%][094] := gPolarTheta[5]; gAttrVal[gTrialAccepted%][095] := gPeakPolarVel[5]; gAttrVal[gTrialAccepted%][096] := Abs2Rel(gPeakPolarVelTime[5]); gAttrVal[gTrialAccepted%][097] := Abs2Rel(zTargetStepTime); gAttrVal[gTrialAccepted%][098] := zHTargetStepAmp; gAttrVal[gTrialAccepted%][099] := zHTargetBegPos; gAttrVal[gTrialAccepted%][100] := zHTargetEndPos; gAttrVal[gTrialAccepted%][101] := zVTargetStepAmp; gAttrVal[gTrialAccepted%][102] := zVTargetBegPos; gAttrVal[gTrialAccepted%][103] := zVTargetEndPos; gAttrVal[gTrialAccepted%][104] := zTargetRadius; gAttrVal[gTrialAccepted%][105] := zTargetTheta; gAttrVal[gTrialAccepted%][106] := gHEerror[5]; gAttrVal[gTrialAccepted%][107] := gVEerror[5]; gAttrVal[gTrialAccepted%][108] := gPolarError[5]; gAttrVal[gTrialAccepted%][109] := Dec2Msec(zEarliestOnset - gLatestOffset); gAttrVal[gTrialAccepted%][269] := gPolarVelPrePeakAccel[5]; 'AB adapt gAttrVal[gTrialAccepted%][270] := gPolarVelPostPeakAccel[5]; endif gAttrVal[gTrialAccepted%][121] := pAnalysisType%*10000 + pWriteTraces%*1000 + pSearchScheme%*100 + pAdaptType%*10 + pCellType%; gAttrVal[gTrialAccepted%][122] := gWhereToStopAnalysis; gAttrVal[gTrialAccepted%][123] := gHEyePreTargetStepPos; gAttrVal[gTrialAccepted%][124] := gVEyePreTargetStepPos; if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then 'anal CD attributes '--------------------------------------------------------------------------- gAttrVal[gTrialAccepted%][125] := Abs2Rel(gHEonsetTime[2]); '~[001] gAttrVal[gTrialAccepted%][126] := gHEbegPos[2]; '~[002] gAttrVal[gTrialAccepted%][127] := Abs2Rel(gHEoffsetTime[2]); '~[003] gAttrVal[gTrialAccepted%][128] := gHEendPos[2]; '~[004] gAttrVal[gTrialAccepted%][129] := Abs2Rel(gVEonsetTime[2]); '~[005] gAttrVal[gTrialAccepted%][130] := gVEbegPos[2]; '~[006] gAttrVal[gTrialAccepted%][131] := Abs2Rel(gVEoffsetTime[2]); '~[007] gAttrVal[gTrialAccepted%][132] := gVEendPos[2]; '~[008] gAttrVal[gTrialAccepted%][133] := Abs2Rel(gPeakHEvelTime[2]); '~[009] gAttrVal[gTrialAccepted%][134] := gPeakHEvelocity[2]; '~[010] gAttrVal[gTrialAccepted%][135] := Abs2Rel(gPeakVEvelTime[2]); '~[011] gAttrVal[gTrialAccepted%][136] := gPeakVEvelocity[2]; '~[012] gAttrVal[gTrialAccepted%][137] := gHEamp[2]; '~[015] gAttrVal[gTrialAccepted%][138] := gVEamp[2]; '~[016] gAttrVal[gTrialAccepted%][139] := gPolarRadius[2]; '~[017] gAttrVal[gTrialAccepted%][140] := gPolarTheta[2]; '~[018] gAttrVal[gTrialAccepted%][143] := Dec2Msec(gHEDuration[2]); '~[024] gAttrVal[gTrialAccepted%][144] := Dec2Msec(gVEDuration[2]); '~[025] gAttrVal[gTrialAccepted%][145] := Abs2Rel(gPeakPolarVelTime[2]);'~[030] gAttrVal[gTrialAccepted%][146] := gPeakPolarVel[2]; '~[031] gAttrVal[gTrialAccepted%][151] := gHGain[2]; '~[058] gAttrVal[gTrialAccepted%][152] := gVGain[2]; '~[059] gAttrVal[gTrialAccepted%][153] := gPolarGain[2]; '~[060] gAttrVal[gTrialAccepted%][154] := gHEerror[2]; '~[072] gAttrVal[gTrialAccepted%][155] := gVEerror[2]; '~[071] gAttrVal[gTrialAccepted%][156] := gPolarError[2]; '~[074] gAttrVal[gTrialAccepted%][265] := gPolarVelPrePeakAccel[2];'~[263] gAttrVal[gTrialAccepted%][266] := gPolarVelPostPeakAccel[2];'~[264] 'anal EF attributes '--------------------------------------------------------------------------- gAttrVal[gTrialAccepted%][182] := Abs2Rel(gHEonsetTime[3]); '~[001] gAttrVal[gTrialAccepted%][183] := gHEbegPos[3]; '~[002] gAttrVal[gTrialAccepted%][184] := Abs2Rel(gHEoffsetTime[3]); '~[003] gAttrVal[gTrialAccepted%][185] := gHEendPos[3]; '~[004] gAttrVal[gTrialAccepted%][186] := Abs2Rel(gVEonsetTime[3]); '~[005] gAttrVal[gTrialAccepted%][187] := gVEbegPos[3]; '~[006] gAttrVal[gTrialAccepted%][188] := Abs2Rel(gVEoffsetTime[3]); '~[007] gAttrVal[gTrialAccepted%][189] := gVEendPos[3]; '~[008] gAttrVal[gTrialAccepted%][190] := Abs2Rel(gPeakHEvelTime[3]); '~[009] gAttrVal[gTrialAccepted%][191] := gPeakHEvelocity[3]; '~[010] gAttrVal[gTrialAccepted%][192] := Abs2Rel(gPeakVEvelTime[3]); '~[011] gAttrVal[gTrialAccepted%][193] := gPeakVEvelocity[3]; '~[012] gAttrVal[gTrialAccepted%][194] := gHEamp[3]; '~[015] gAttrVal[gTrialAccepted%][195] := gVEamp[3]; '~[016] gAttrVal[gTrialAccepted%][196] := gPolarRadius[3]; '~[017] gAttrVal[gTrialAccepted%][197] := gPolarTheta[3]; '~[018] gAttrVal[gTrialAccepted%][200] := Dec2Msec(gHEDuration[3]); '~[024] gAttrVal[gTrialAccepted%][201] := Dec2Msec(gVEDuration[3]); '~[025] gAttrVal[gTrialAccepted%][202] := Abs2Rel(gPeakPolarVelTime[3]);'~[030] gAttrVal[gTrialAccepted%][203] := gPeakPolarVel[3]; '~[031] gAttrVal[gTrialAccepted%][208] := gHGain[3]; '~[058] gAttrVal[gTrialAccepted%][209] := gVGain[3]; '~[059] gAttrVal[gTrialAccepted%][210] := gPolarGain[3]; '~[060] gAttrVal[gTrialAccepted%][211] := gHEerror[3]; '~[072] gAttrVal[gTrialAccepted%][212] := gVEerror[3]; '~[073] gAttrVal[gTrialAccepted%][213] := gPolarError[3]; '~[074] gAttrVal[gTrialAccepted%][267] := gPolarVelPrePeakAccel[3];'~[263] gAttrVal[gTrialAccepted%][268] := gPolarVelPostPeakAccel[3];'~[264] if pAdaptType% > 0 then 'anal CD attributes '--------------------------------------------------------------------------- gAttrVal[gTrialAccepted%][157] := Abs2Rel(zEarliestOnset); '~[075] gAttrVal[gTrialAccepted%][158] := Abs2Rel(zLatestOffset); '~[076] gAttrVal[gTrialAccepted%][159] := gHEAmp[6]; '~[077] gAttrVal[gTrialAccepted%][160] := gHEbegPos[6]; '~[078] gAttrVal[gTrialAccepted%][161] := Abs2Rel(gHEonsetTime[6]); '~[079] gAttrVal[gTrialAccepted%][162] := gHEendPos[6]; '~[080] gAttrVal[gTrialAccepted%][163] := Abs2Rel(gHEoffsetTime[6]); '~[081] gAttrVal[gTrialAccepted%][164] := Dec2Msec(gHEDuration[6]); '~[082] gAttrVal[gTrialAccepted%][165] := gPeakHEvelocity[6]; '~[083] gAttrVal[gTrialAccepted%][166] := Abs2Rel(gPeakHEvelTime[6]); '~[084] gAttrVal[gTrialAccepted%][167] := gVEamp[6]; '~[085] gAttrVal[gTrialAccepted%][168] := gVEbegPos[6]; '~[086] gAttrVal[gTrialAccepted%][169] := Abs2Rel(gVEonsetTime[6]); '~[087] gAttrVal[gTrialAccepted%][170] := gVEendPos[6]; '~[088] gAttrVal[gTrialAccepted%][171] := Abs2Rel(gVEoffsetTime[6]); '~[089] gAttrVal[gTrialAccepted%][172] := Dec2Msec(gVEDuration[6]); '~[090] gAttrVal[gTrialAccepted%][173] := gPeakVEvelocity[6]; '~[091] gAttrVal[gTrialAccepted%][174] := Abs2Rel(gPeakVEvelTime[6]); '~[092] gAttrVal[gTrialAccepted%][175] := gPolarRadius[6]; '~[093] gAttrVal[gTrialAccepted%][176] := gPolarTheta[6]; '~[094] gAttrVal[gTrialAccepted%][177] := gPeakPolarVel[6]; '~[095] gAttrVal[gTrialAccepted%][178] := Abs2Rel(gPeakPolarVelTime[6]);'~[096] gAttrVal[gTrialAccepted%][179] := gHEerror[6]; '~[106] gAttrVal[gTrialAccepted%][180] := gVEerror[6]; '~[107] gAttrVal[gTrialAccepted%][181] := gPolarError[6]; '~[108] gAttrVal[gTrialAccepted%][271] := gPolarVelPrePeakAccel[6];'~[269] gAttrVal[gTrialAccepted%][272] := gPolarVelPostPeakAccel[6];'~[270] 'anal EF attributes '--------------------------------------------------------------------------- gAttrVal[gTrialAccepted%][214] := Abs2Rel(zEarliestOnset); '~[075] gAttrVal[gTrialAccepted%][215] := Abs2Rel(zLatestOffset); '~[076] gAttrVal[gTrialAccepted%][216] := gHEAmp[7]; '~[077] gAttrVal[gTrialAccepted%][217] := gHEbegPos[7]; '~[078] gAttrVal[gTrialAccepted%][218] := Abs2Rel(gHEonsetTime[7]); '~[079] gAttrVal[gTrialAccepted%][219] := gHEendPos[7]; '~[080] gAttrVal[gTrialAccepted%][220] := Abs2Rel(gHEoffsetTime[7]); '~[081] gAttrVal[gTrialAccepted%][221] := Dec2Msec(gHEDuration[7]); '~[082] gAttrVal[gTrialAccepted%][222] := gPeakHEvelocity[7]; '~[083] gAttrVal[gTrialAccepted%][223] := Abs2Rel(gPeakHEvelTime[7]); '~[084] gAttrVal[gTrialAccepted%][224] := gVEamp[7]; '~[085] gAttrVal[gTrialAccepted%][225] := gVEbegPos[7]; '~[086] gAttrVal[gTrialAccepted%][226] := Abs2Rel(gVEonsetTime[7]); '~[087] gAttrVal[gTrialAccepted%][227] := gVEendPos[7]; '~[088] gAttrVal[gTrialAccepted%][228] := Abs2Rel(gVEoffsetTime[7]); '~[089] gAttrVal[gTrialAccepted%][229] := Dec2Msec(gVEDuration[7]); '~[090] gAttrVal[gTrialAccepted%][230] := gPeakVEvelocity[7]; '~[091] gAttrVal[gTrialAccepted%][231] := Abs2Rel(gPeakVEvelTime[7]); '~[092] gAttrVal[gTrialAccepted%][232] := gPolarRadius[7]; '~[093] gAttrVal[gTrialAccepted%][233] := gPolarTheta[7]; '~[094] gAttrVal[gTrialAccepted%][234] := gPeakPolarVel[7]; '~[095] gAttrVal[gTrialAccepted%][235] := Abs2Rel(gPeakPolarVelTime[7]);'~[096] gAttrVal[gTrialAccepted%][236] := gHEerror[7]; '~[106] gAttrVal[gTrialAccepted%][237] := gVEerror[7]; '~[107] gAttrVal[gTrialAccepted%][238] := gPolarError[7]; '~[108] gAttrVal[gTrialAccepted%][273] := gPolarVelPrePeakAccel[7];'~[269] gAttrVal[gTrialAccepted%][274] := gPolarVelPostPeakAccel[7];'~[270] endif gAttrVal[gTrialAccepted%][239] := ChanValue(chHE%[1], gHVonsetTime [2]); 'A at CD beg time gAttrVal[gTrialAccepted%][240] := ChanValue(chHE%[1], gHVoffsetTime[2]); 'A at CD end time gAttrVal[gTrialAccepted%][241] := ChanValue(chHE%[1], gHVonsetTime [3]); 'A at EF beg time gAttrVal[gTrialAccepted%][242] := ChanValue(chHE%[1], gHVoffsetTime[3]); 'A at EF end time gAttrVal[gTrialAccepted%][243] := ChanValue(chVE%[1], gHVonsetTime [2]); 'B at CD beg time gAttrVal[gTrialAccepted%][244] := ChanValue(chVE%[1], gHVoffsetTime[2]); 'B at CD end time gAttrVal[gTrialAccepted%][245] := ChanValue(chVE%[1], gHVonsetTime [3]); 'B at EF beg time gAttrVal[gTrialAccepted%][246] := ChanValue(chVE%[1], gHVoffsetTime[3]); 'B at EF end time gAttrVal[gTrialAccepted%][247] := ChanValue(chHE%[2], gHVonsetTime [1]); 'C at AB beg time gAttrVal[gTrialAccepted%][248] := ChanValue(chHE%[2], gHVoffsetTime[1]); 'C at AB end time gAttrVal[gTrialAccepted%][249] := ChanValue(chHE%[2], gHVonsetTime [3]); 'C at EF beg time gAttrVal[gTrialAccepted%][250] := ChanValue(chHE%[2], gHVoffsetTime[3]); 'C at EF end time gAttrVal[gTrialAccepted%][251] := ChanValue(chVE%[2], gHVonsetTime [1]); 'D at AB beg time gAttrVal[gTrialAccepted%][252] := ChanValue(chVE%[2], gHVoffsetTime[1]); 'D at AB end time gAttrVal[gTrialAccepted%][253] := ChanValue(chVE%[2], gHVonsetTime [3]); 'D at EF beg time gAttrVal[gTrialAccepted%][254] := ChanValue(chVE%[2], gHVoffsetTime[3]); 'D at EF end time gAttrVal[gTrialAccepted%][255] := ChanValue(chHE%[3], gHVonsetTime [1]); 'E at AB beg time gAttrVal[gTrialAccepted%][256] := ChanValue(chHE%[3], gHVoffsetTime[1]); 'E at AB end time gAttrVal[gTrialAccepted%][257] := ChanValue(chHE%[3], gHVonsetTime [2]); 'E at CD beg time gAttrVal[gTrialAccepted%][258] := ChanValue(chHE%[3], gHVoffsetTime[2]); 'E at CD end time gAttrVal[gTrialAccepted%][259] := ChanValue(chVE%[3], gHVonsetTime [1]); 'F at AB beg time gAttrVal[gTrialAccepted%][260] := ChanValue(chVE%[3], gHVoffsetTime[1]); 'F at AB end time gAttrVal[gTrialAccepted%][261] := ChanValue(chVE%[3], gHVonsetTime [2]); 'F at CD beg time gAttrVal[gTrialAccepted%][262] := ChanValue(chVE%[3], gHVoffsetTime[2]); 'F at CD end time endif 'vergence docase case pCellType% = kModeBehavior% then 'Behavior 'nothing case pCellType% = kModePause% then 'Pause 'nothing yet case pCellType% = kModeBurst% then 'Burst gAttrVal[gTrialAccepted%][013] := Abs2Rel(gBurstStartTime); gAttrVal[gTrialAccepted%][014] := Abs2Rel(gBurstEndTime); gAttrVal[gTrialAccepted%][019] := Dec2Msec(gBurstDuration); gAttrVal[gTrialAccepted%][020] := RelBurst(Abs2Rel(gHEonsetTime[1])); gAttrVal[gTrialAccepted%][021] := RelBurst(Abs2Rel(gVEonsetTime[1])); gAttrVal[gTrialAccepted%][023] := gBurstSpikeNumber%; gAttrVal[gTrialAccepted%][027] := gBurstMeanFreq; gAttrVal[gTrialAccepted%][028] := Abs2Rel(gBurstPeakTime); gAttrVal[gTrialAccepted%][029] := gBurstPeakFreq; gAttrVal[gTrialAccepted%][032] := gBurstMax5spikeAvgFreq; gAttrVal[gTrialAccepted%][034] := Abs2Rel(gBurstMax5spikeAvgFreqTime); gAttrVal[gTrialAccepted%][035] := gPreTonicFreq; 'last 5 spike freq ave in pre burst gAttrVal[gTrialAccepted%][036] := Abs2Rel(gPreTonicStartTime); if (gBurstPeakFreq <> NaN) and (gPreTonicFreq <> NaN) then gAttrVal[gTrialAccepted%][037]:= gBurstPeakFreq - gPreTonicFreq; endif gAttrVal[gTrialAccepted%][038] := gPostTonicFreq; 'first 5 spike freq ave in post-burst gAttrVal[gTrialAccepted%][040] := gBurstManuallyMarked%; '0=auto, 1=manually correction gAttrVal[gTrialAccepted%][041] := gPreTonicNumSpk%; gAttrVal[gTrialAccepted%][042] := gPostTonicNumSpk%; gAttrVal[gTrialAccepted%][048] := Dec2Msec(gPreTonicDuration); gAttrVal[gTrialAccepted%][049] := Dec2Msec(gPostTonicDuration); gAttrVal[gTrialAccepted%][110] := gPreRateNumSpk%; gAttrVal[gTrialAccepted%][111] := Dec2Msec(gPreRateDuration); gAttrVal[gTrialAccepted%][112] := gPreRateFreq; gAttrVal[gTrialAccepted%][113] := gPreRateMeanHPos[1]; gAttrVal[gTrialAccepted%][114] := gPreRateMeanVPos[1]; gAttrVal[gTrialAccepted%][115] := gPostRateNumSpk%; gAttrVal[gTrialAccepted%][116] := Dec2Msec(gPostRateDuration); gAttrVal[gTrialAccepted%][117] := gPostRateFreq; gAttrVal[gTrialAccepted%][118] := gPostRateMeanHPos[1]; gAttrVal[gTrialAccepted%][119] := gPostRateMeanVPos[1]; gAttrVal[gTrialAccepted%][120] := Abs2Rel(gPostTonicEndTime); if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then 'anal CD attributes '--------------------------------------------------------------------------- gAttrVal[gTrialAccepted%][141]:= RelBurst(Abs2Rel(gHEonsetTime[2])); '~[020] gAttrVal[gTrialAccepted%][142]:= RelBurst(Abs2Rel(gVEonsetTime[2])); '~[021] gAttrVal[gTrialAccepted%][147]:= gPreRateMeanHPos[2]; '~[113] gAttrVal[gTrialAccepted%][148]:= gPreRateMeanVPos[2]; '~[114] gAttrVal[gTrialAccepted%][149]:= gPostRateMeanHPos[2]; '~[118] gAttrVal[gTrialAccepted%][150]:= gPostRateMeanVPos[2]; '~[119] 'anal EF attributes '--------------------------------------------------------------------------- gAttrVal[gTrialAccepted%][198]:= RelBurst(Abs2Rel(gHEonsetTime[3])); '~[020] gAttrVal[gTrialAccepted%][199]:= RelBurst(Abs2Rel(gVEonsetTime[3])); '~[021] gAttrVal[gTrialAccepted%][204]:= gPreRateMeanHPos[3]; '~[113] gAttrVal[gTrialAccepted%][205]:= gPreRateMeanVPos[3]; '~[114] gAttrVal[gTrialAccepted%][206]:= gPostRateMeanHPos[3]; '~[118] gAttrVal[gTrialAccepted%][207]:= gPostRateMeanVPos[3]; '~[119] endif endcase 'the attributes have been computed, now display them in the log window if gAutoAnalysis% = 0 then AttributeShowSelected(); endif end 'AttributeComputeAndShow '---------------------------------------------------- ' ManualTargetAnalysis '< 3/10/04 '---------------------------------------------------- proc ManualTargetAnalysis() var aResponse := 0; 'initialize to no choice repeat CursorVisible(-1,0); 'hide cursors if gTargetStepTime = NaN then aResponse := Interact("",1023,0,"Next (Enter)|0x0d","Add &Target"); 'wait for the user to do something if aResponse = 1 then 'no target marked, save it this way endif if aResponse = 2 then gTargetStepTime := (Xlow()+Xhigh())/2; 're-appear cursor in the middle gTarget% := 1; endif else Cursor(1,gTargetStepTime); 'position the cursor CursorLabel(4,1,"mid-Target step"); 'label the cursor CursorVisible(1,1); 'make it visible aResponse := Interact("",1023,0,"Next (Enter)|0x0d","Remove &Target"); 'wait for the user to do something if aResponse = 1 then gTargetStepTime := Cursor(1); gTarget% := 1; endif if aResponse = 2 then gTargetStepTime := NaN; gTarget% := 0; endif endif until aResponse = 1; 'delete old marks and add the new ones CursorVisible(-1,0); 'hide cursors end 'ManualTargetAnalysis '---------------------------------------------------- ' ManualSaccadeAnalysis 'Properly reset '< 3/10/04 '---------------------------------------------------- proc ManualSaccadeAnalysis() var aH1$,aHH1$, aV1$,aVV1$, aH2$,aHH2$, aV2$,aVV2$, aH3$,aHH3$, aV3$,aVV3$; docase case pAnalysisType% = kVergenceAnalysis% then aH1$ := "HE1"; aHH1$ := "Horizontal &Eye1"; aV1$ := "VE1"; aVV1$ := "Vertical &Eye1"; aH2$ := "HE2"; aHH2$ := "Horizontal &Eye2"; aV2$ := "VE2"; aVV2$ := "Vertical &Eye2"; aH3$ := "H Verg"; aHH3$ := "Horizontal &Eye3"; aV3$ := "V Verg"; aVV3$ := "Vertical &Eye3"; case pAnalysisType% = kGazeAnalysis% then aH1$ := "H Gaze"; aHH1$ := "Horizontal &Gaze"; aV1$ := "V Gaze"; aVV1$ := "Vertical &Gaze"; aH2$ := "H Head"; aHH2$ := "Horizontal &Head"; aV2$ := "V Head"; aVV2$ := "Vertical &Head"; aH3$ := "H EIH"; aHH3$ := "Horizontal &EIH"; aV3$ := "V EIH"; aVV3$ := "Vertical &EIH"; else aH1$ := "HE"; aHH1$ := "Horizontal &Eye"; aV1$ := "VE"; aVV1$ := "Vertical &Eye"; aH2$ := "HE2"; aHH2$ := "Horizontal &Eye2"; aV2$ := "VE2"; aVV2$ := "Vertical &Eye2"; aH3$ := "HE3"; aHH3$ := "Horizontal &Eye3"; aV3$ := "VE3"; aVV3$ := "Vertical &Eye3"; endcase ManualEyeCursors(gPeakHEvelTime[1],gHEonsetTime[1],gHEoffsetTime[1],gHEsaccadeExist%[1],aH1$,aHH1$); ManualEyeCursors(gPeakVEvelTime[1],gVEonsetTime[1],gVEoffsetTime[1],gVEsaccadeExist%[1],aV1$,aVV1$); gSaccadeExist%[1] := gHEsaccadeExist%[1] + gVEsaccadeExist%[1]; 'Saccade exists if value > 0 if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then ManualEyeCursors(gPeakHEvelTime[2],gHEonsetTime[2],gHEoffsetTime[2],gHEsaccadeExist%[2],aH2$,aHH2$); ManualEyeCursors(gPeakVEvelTime[2],gVEonsetTime[2],gVEoffsetTime[2],gVEsaccadeExist%[2],aV2$,aVV2$); gSaccadeExist%[2] := gHEsaccadeExist%[2] + gVEsaccadeExist%[2]; 'Saccade exists if value > 0 ManualEyeCursors(gPeakHEvelTime[3],gHEonsetTime[3],gHEoffsetTime[3],gHEsaccadeExist%[3],aH3$,aHH3$); ManualEyeCursors(gPeakVEvelTime[3],gVEonsetTime[3],gVEoffsetTime[3],gVEsaccadeExist%[3],aV3$,aVV3$); gSaccadeExist%[3] := gHEsaccadeExist%[3] + gVEsaccadeExist%[3]; 'Saccade exists if value > 0 endif CursorVisible(-1,0); 'hide cursors ComputeEarliestAndLatest(1); COMPAREearliestAndLatest(1); if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then ComputeEarliestAndLatest(2); COMPAREearliestAndLatest(2); endif gSaccadeDuration := NaN; if gSaccadeExist%[1]+gSaccadeExist%[2]+gSaccadeExist%[3]+gSaccadeExist%[4] > 0 then gSaccadeDuration := gLatestOffset - gEarliestOnset; gCursorZeroTime := gLatestOffset; 'start the next search just past the saccade offset endif end 'ManualSaccadeAnalysis '---------------------------------------------------- ' ManualEyeCursors 'Properly reset ' 2/14/06 '---------------------------------------------------- proc ManualEyeCursors(&aPeakVelTime,&aOnsetTime,&aOffsetTime,&aSaccadeExist%,aStr$,bStr$) var aResponse; repeat CursorVisible(-1,0); 'hide cursors if aPeakVelTime = NaN then aResponse := Interact("",1023,0,"Next (Enter)|0x0d","Add "+bStr$); 'wait for the user to do something if aResponse = 1 then 'no eye marked, so save it that way endif if aResponse = 2 then aOnsetTime := ((Xlow() + Xhigh()) / 2) - k20ms; 're-appear cursor in the middle aPeakVelTime:= (Xlow() + Xhigh()) / 2; 're-appear cursor in the middle aOffsetTime := ((Xlow() + Xhigh()) / 2) + k20ms; 're-appear cursor in the middle aResponse := ManualBegPeakEnd(aPeakVelTime,aOnsetTime,aOffsetTime,aSaccadeExist%,aStr$,bStr$) endif else aResponse := ManualBegPeakEnd(aPeakVelTime,aOnsetTime,aOffsetTime,aSaccadeExist%,aStr$,bStr$) endif until aResponse = 1; end 'ManualEyeCursors '---------------------------------------------------- ' ManualBegPeakEnd 'Properly reset ' 2/14/06 '---------------------------------------------------- func ManualBegPeakEnd(&aPeakVelTime,&aOnsetTime,&aOffsetTime,&aSaccadeExist%,aStr$,bStr$) var aResponse; CursorVisible(1,1); CursorVisible(2,1); CursorVisible(3,1); CursorLabel(4,1,"beg "+ aStr$); CursorLabel(4,2,"pk " + aStr$); CursorLabel(4,3,"end "+ aStr$); Cursor(1,aOnsetTime); Cursor(2,aPeakVelTime); Cursor(3,aOffsetTime); aResponse := Interact("",1023,0,"Next (Enter)|0x0d","Remove "+bStr$); 'wait for the user to do something if aResponse = 1 then aOnsetTime := Cursor(1); aPeakVelTime := Cursor(2); aOffsetTime := Cursor(3); aSaccadeExist% := 1; endif if aResponse = 2 then aOnsetTime := NaN; aPeakVelTime := NaN; aOffsetTime := NaN; aSaccadeExist% := 0; endif return aResponse; end 'ManualBegPeakEnd '---------------------------------------------------- ' GaussKernelGen 'Generate gaussian kernel '< 3/10/04 '---------------------------------------------------- proc GaussKernelGen(gausskernel[]) var indexg%, spi, tt, expfiller; spi := 1/(pSigma*Sqrt(2*pi)); for indexg% := 0 to 4*pSigma*8 do tt := indexg%/8; expfiller := -0.5 * (tt * tt)/(pSigma * pSigma); gausskernel[indexg%] := spi * Exp(expfiller); next; end 'GaussKernelGen '---------------------------------------------------- ' MetricsBurstAutoGaussian 'Function returns: ' -1 error: can't find peak ' -2 error: can't find burst start ' -3 error: can't find burst end ' set burst start and end times, duration and # spike in burst ' '< 3/10/04 '---------------------------------------------------- func MetricsBurstAutoGaussian() var aDummyPeak, aJunk%, aNum%, aDummyPeakIndex; aNum% := (gLatestOffset + pBurstPeakRangePlus - (gEarliestOnset - pBurstPeakRangeMinus)) / BinSize(chUnitSmooth%); var aJunkarray[aNum%]; 'first find out whether there are spikes within the interval if ChanMeasure(chmSpikeEventDeletable%,4,gEarliestOnset-pBurstPeakRangeMinus,gLatestOffset + pBurstPeakRangePlus,aJunk%,2) < 1 then ResetGaussian(); return -1; endif 'Find PEAK SPIKE DENSITY from saccade onset - xx to saccade offset + yy ChanData(chUnitSmooth%, aJunkarray[], gEarliestOnset - pBurstPeakRangeMinus, gLatestOffset + pBurstPeakRangePlus); aDummyPeakIndex := Max(aJunkarray[]); 'this tells how many ms from search start time the peak is located aDummyPeak := aJunkarray[aDummyPeakIndex]; 'need at least one spike to get a value for these two procedures gPeakSpikeDensityTime := gEarliestOnset - pBurstPeakRangeMinus + (aDummyPeakIndex/kMS); gPeakSpikeDensity := ChanValue(chUnitSmooth%, gPeakSpikeDensityTime); 'finding START and END of burst gStartLevelThreshold := gPeakSpikeDensity * pStartPercentThreshold / 100; gEndLevelThreshold := gPeakSpikeDensity * pEndPercentThreshold / 100; 'gSpikeDensityStartTime := ChanSearch(chUnitSmooth%,8, gPeakSpikeDensityTime, gPeakSpikeDensityTime - 0.300, gStartLevelThreshold); 'search from pk back in time to find beginning of burst gSpikeDensityStartTime := ChanSearch(chUnitSmooth%,8, gPeakSpikeDensityTime, gPeakSpikeDensityTime - 0.0, gStartLevelThreshold); '5/8/07 search from pk back in time to find beginning of burst if gSpikeDensityStartTime < 0 then ResetGaussian(); return -2; endif 'gSpikeDensityEndTime := ChanSearch(chUnitSmooth%,8, gPeakSpikeDensityTime, gPeakSpikeDensityTime + 0.300, gEndLevelThreshold); 'search from pk forward in time to find end of burst gSpikeDensityEndTime := ChanSearch(chUnitSmooth%,8, gPeakSpikeDensityTime, gPeakSpikeDensityTime + maxtime(), gEndLevelThreshold); '5/8/07 search from pk forward in time to find end of burst if gSpikeDensityEndTime < 0 then ResetGaussian(); return -3; endif end 'MetricsBurstAutoGaussian '---------------------------------------------------- ' DrawColoredSpikes '01:blue, 02:green, 03:light blue, 04:red, 05: pink, 06:yellow '< 3/10/04 '---------------------------------------------------- proc DrawColoredSpikes(source%,dest%,sTime,Spike%,colorcode%) var n%, time, nspk%, code%[4], 'only code%[0] is used data[2]; code%[0] := colorcode%; data[0] := -4; data[1] := 4; time := sTime - 0.00000; 'be faithful to the time passed to the routine nspk% := 0; repeat time := NextTime(source%,time); MemSetItem(dest%,0,time,code%[],data[]); nspk% := nspk%+1; until nspk% = Spike%; end 'DrawColoredSpikes '---------------------------------------------------- ' ManualBurstModeAnalysis ' 'Only used for hand analysis. '< 3/10/04 '---------------------------------------------------- proc ManualBurstModeAnalysis() CursorVisible(-1,0); 'make all cursors invisible if gBurstStartTime <> NaN then 'not a location, but rather a search point Cursor(2,gBurstStartTime - 0.001); 'add a little more so that it can find spike at that location else Cursor(2,gEarliestOnset); endif if gBurstEndTime <> NaN then 'not a location, but rather a search point Cursor(3,gBurstEndTime + 0.001); 'add a little more so that it can find spike at that location else Cursor(3,gLatestOffset); endif CursorVisible(2,1); CursorVisible(3,1); CursorLabel(4,2,"Burst >"); CursorLabel(4,3,"< Burst"); Interact("",1023,0,"Next (Enter)|0x0d"); FrontView(gViewData%); gBurstStartTime := Cursor(2); gBurstEndTime := Cursor(3); 'it is already known if there is a burst, don't mark any units if no burst exist '-------------------------------------------- if (gTargetStepTime <> NaN) and (gBurstSpikeNumber% <> 0) then MemDeleteTime(chmColoredPrePostBurstTemp%,3,gEarlyTime,gLateTime); 'erase all the spikes on the colored trace MetricsBurst(gBurstStartTime, gBurstEndTime); ' MetricsBurst(Cursor(2), Cursor(3)); MetricsBurstPreTonic(gTargetStepTime,gBurstStartTime); MetricsBurstPreRate(); MetricsBurstPostTonic(gBurstEndTime,gLateTime); MetricsBurstPostRate(); else ResetPreBurst(); ResetPostBurst(); endif gBurstManuallyMarked% := 1; HighlightBurst(); end 'ManualBurstModeAnalysis '---------------------------------------------------- ' MetricsBurst ' 10/6/05 '---------------------------------------------------- proc MetricsBurst(aBeg, aEnd) var aJunk%; '2/16/06 to increase reliability, continue concentrating where variables are reset to one place ResetBurst(); if (aBeg > 0) and (aEnd > 0) and (aBeg <> NaN) and (aEnd <> NaN) then 'proceed only if a burst beginning and end were found aBeg := aBeg - 0.0001; 'extend the regions a teeny bit so the first and last spikes can be found aEnd := aEnd + 0.0001; 'with NextTime and LastTime 'protect against invalid values if aBeg < 0 then aBeg := 0; endif if aEnd > MaxTime() then aEnd := MaxTime(); endif gBurstSpikeNumber% := ChanMeasure(chmSpikeEventDeletable%,4,aBeg,aEnd,aJunk%,2); if gBurstSpikeNumber% <> 0 then gBurstStartTime := NextTime(chmSpikeEventDeletable%,aBeg); gBurstEndTime := LastTime(chmSpikeEventDeletable%,aEnd); gBurstDuration := gBurstEndTime-gBurstStartTime; MetricsBurstFrequency(); endif endif end 'MetricsBurst '---------------------------------------------------- ' MetricsBurstPreTonic 'This computes attributes related to pre-tonic rate 'and the rate-position ' 10/7/05 '---------------------------------------------------- proc MetricsBurstPreTonic(aBeg, aEnd) var aJunk%; '2/16/06 to increase reliability, continue concentrating where variables are reset to one place ResetPreBurst(); if (aBeg > 0) and (aEnd > 0) and (aBeg <> NaN) and (aEnd <> NaN) and (aBeg < aEnd)then 'pre-tonic aBeg := aBeg - 0.0001; 'include the time before the pre-burst so it gets the first spike aEnd := aEnd - 0.0001; 'don't include the time the burst starts or else it marks as a pre-burst instead of a burst 'protect against invalid values if aBeg > 0 then gPreTonicNumSpk% := ChanMeasure(chmSpikeEventDeletable%,4,aBeg,aEnd,aJunk%,2); if gPreTonicNumSpk% > 0 then gPreTonicStartTime := NextTime(chmSpikeEventDeletable%,aBeg); ' 'if gPreTonicStartTime > 1326 then ' a$ := a$ + print$("%13.5f",aBeg) + " = aBeg" + Chr$(13); ' a$ := a$ + print$("%13.5f",gPreTonicStartTime) + " = gPreTonicStartTime" + Chr$(13); ' a$ := a$ + print$("%13.5f",aEnd) + " = aEnd" + Chr$(13); ' a$ := a$ + print$("%13.5f",gBurstStartTime) + " = gBurstStartTime" + Chr$(13); ' View(LogHandle()); ' Print(a$); ' View(gViewData%); ' 'endif if gPreTonicStartTime > aEnd then ResetPreBurst(); 'gPreTonicStartTime very close to gBurstStartTime and found a spike in the burst area else gPreTonicDuration := gBurstStartTime-gPreTonicStartTime; gPreTonicFreq := gPreTonicNumSpk%/gPreTonicDuration; endif endif endif endif end 'MetricsBurstPreTonic '---------------------------------------------------- ' MetricsBurstPreRate 'This computes attributes related to pre-tonic rate 'and the rate-position ' ' 10/7/05 '---------------------------------------------------- proc MetricsBurstPreRate() var aBeg, aEnd, aSize%, aResult; '2/16/06 to increase reliability, continue concentrating where variables are reset to one place ResetPreRate(); 'pre-rate if gEarliestOnset <> NaN then aEnd := gEarliestOnset - kRatePositionDelay; 'end 50ms before the saccade onset aBeg := aEnd - kRatePositionSampleDur; '100ms of time sampled if (aBeg > 0) and (aEnd > 0) then gPreRateNumSpk% := ChanMeasure(chmSpikeEventDeletable%,4,aBeg,aEnd,aSize%,2); if gPreRateNumSpk% > 0 then gPreRateDuration := kRatePositionSampleDur; gPreRateFreq := gPreRateNumSpk%/gPreRateDuration; aSize% := gPreRateDuration*kMS; var aData[aSize%]; aSize% := aSize% - 1; 'adjust for use with array[0] ChanData(chHE%[1],aData[], aBeg, aEnd); 'Read H eye aResult := ArrSum(aData[0:aSize%],gPreRateMeanHPos[1]); 'Average area ChanData(chVE%[1],aData[], aBeg, aEnd); 'Read V eye aResult := ArrSum(aData[0:aSize%],gPreRateMeanVPos[1]); 'Average area if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then ChanData(chHE%[2],aData[], aBeg, aEnd); 'Read H eye aResult := ArrSum(aData[0:aSize%],gPreRateMeanHPos[2]); 'Average area ChanData(chVE%[2],aData[], aBeg, aEnd); 'Read V eye aResult := ArrSum(aData[0:aSize%],gPreRateMeanVPos[2]); 'Average area endif endif endif endif end 'MetricsBurstPreRate '---------------------------------------------------- ' MetricsBurstPostTonic 'This computes attributes related to post-tonic rate 'and the rate-position ' 10/7/05 '---------------------------------------------------- proc MetricsBurstPostTonic(aBeg, aEnd) var aSize%; '2/16/06 to increase reliability, continue concentrating where variables are reset to one place gPostTonicNumSpk% := 0; gPostTonicEndTime := NaN; gPostTonicDuration := NaN; gPostTonicFreq := NaN; if (aBeg > 0) and (aEnd > 0) and (aBeg <> NaN) and (aEnd <> NaN) then 'post-tonic aBeg := aBeg + 0.0001; 'don't include the time the burst ends or else it marks as a post-burst instead of a burst aEnd := aEnd + 0.0001; 'incude time after the post-burst so it gets the last spike 'protect against invalid values if aEnd < Maxtime() then gPostTonicNumSpk% := ChanMeasure(chmSpikeEventDeletable%,4,aBeg,aEnd,aSize%,2); if gPostTonicNumSpk% > 0 then gPostTonicEndTime := LastTime(chmSpikeEventDeletable%,aEnd); gPostTonicDuration := gPostTonicEndTime-gBurstEndTime; gPostTonicFreq := gPostTonicNumSpk%/gPostTonicDuration; endif endif endif end 'MetricsBurstPostTonic '---------------------------------------------------- ' MetricsBurstPostRate 'This computes attributes related to post-tonic rate 'and the rate-position ' ' 10/7/05 '---------------------------------------------------- proc MetricsBurstPostRate() var aBeg, aEnd, aSize%, aResult; '2/16/06 to increase reliability, continue concentrating where variables are reset to one place ResetPostRate(); if gLatestOffset <> NaN then aBeg := gLatestOffset + kRatePositionDelay; 'start 50ms after the saccade offset aEnd := aBeg + kRatePositionSampleDur; '100ms of time sampled if (aBeg < MaxTime()) and (aEnd < MaxTime()) then gPostRateNumSpk% := ChanMeasure(chmSpikeEventDeletable%,4,aBeg,aEnd,aSize%,2); if gPostRateNumSpk% > 0 then gPostRateDuration := kRatePositionSampleDur; gPostRateFreq := gPostRateNumSpk%/gPostRateDuration; aSize% := gPostRateDuration*kMS; var aData[aSize%]; aSize% := aSize% - 1; 'adjust for use with array[0] ChanData(chHE%[1],aData[], aBeg, aEnd); 'Read H eye aResult := ArrSum(aData[0:aSize%],gPostRateMeanHPos[1]); 'Average area ChanData(chVE%[1],aData[], aBeg, aEnd); 'Read V eye aResult := ArrSum(aData[0:aSize%],gPostRateMeanVPos[1]); 'Average area if (pAnalysisType% = kVergenceAnalysis%) or (pAnalysisType% = kGazeAnalysis%) then ChanData(chHE%[2],aData[], aBeg, aEnd); 'Read H eye aResult := ArrSum(aData[0:aSize%],gPostRateMeanHPos[2]); 'Average area ChanData(chVE%[2],aData[], aBeg, aEnd); 'Read V eye aResult := ArrSum(aData[0:aSize%],gPostRateMeanVPos[2]); 'Average area endif endif endif endif end 'MetricsBurstPostRate '---------------------------------------------------- ' HighlightBurst 'Set marks on the unit trace ' 10/06/05 '---------------------------------------------------- proc HighlightBurst() View(gViewData%); if (gBurstStartTime <> NaN) and (gBurstSpikeNumber% > 0) then DrawColoredSpikes(chmSpikeEventDeletable%,chmColoredEvent%, gBurstStartTime-0.00001, gBurstSpikeNumber%,4); 'red=burst endif if (gTargetStepTime <> NaN) and (gPreTonicNumSpk% > 0) then DrawColoredSpikes(chmSpikeEventDeletable%,chmColoredEvent%, gTargetStepTime-0.00001, gPreTonicNumSpk%,1);'blue endif if (gBurstEndTime <> NaN) and (gPostTonicNumSpk% > 0) then DrawColoredSpikes(chmSpikeEventDeletable%,chmColoredEvent%, gBurstEndTime+0.00000, gPostTonicNumSpk%,1);'blue endif 'put markers on spd if gSpikeDensityStartTime <> NaN then MemSetItem(chmMarkerSpd%,0,gSpikeDensityStartTime,ChanValue(chUnitSmooth%,gSpikeDensityStartTime)); endif if gSpikeDensityEndTime <> NaN then MemSetItem(chmMarkerSpd%,0,gSpikeDensityEndTime,ChanValue(chUnitSmooth%,gSpikeDensityEndTime)); endif if gPeakSpikeDensityTime <> NaN then MemSetItem(chmMarkerSpd%,0,gPeakSpikeDensityTime,ChanValue(chUnitSmooth%,gPeakSpikeDensityTime)); endif var aTempData[round((gLateTime-gEarlyTime))/BinSize(chHE%[1])]; ChanData(chUnitSmooth%,aTempData[],gEarlyTime,gLateTime); YRange(chUnitSmooth%,0,aTempData[Max(aTempData[])] + 10); YRange(chmMarkerSpd%,0,aTempData[Max(aTempData[])] + 10); end 'HighlightBurst '---------------------------------------------------- ' MetricsBurstFrequency '< 3/10/04 '---------------------------------------------------- proc MetricsBurstFrequency() var n%, aTime, aValue, aShortestInterval, aShortestIntervalStartTime; aTime := gBurstStartTime - 0.00001; n% := 0; 'initialize the var gBurstMax5spikeAvgFreq := NaN; gBurstMax5spikeAvgFreqTime := NaN; gBurstPeakFreq := NaN; gBurstPeakTime := NaN; gBurstMeanFreq := NaN; if gBurstSpikeNumber% > 1 then 'only need one ISI to compute some attributes gBurstPeakFreq := 0; repeat 'find the peak and mean freq for any burst with at least 1 spike aTime := NextTime(chmInstantRate%, aTime); aValue := ChanValue(chmInstantRate%, aTime); if gBurstPeakFreq < aValue then gBurstPeakFreq := aValue; gBurstPeakTime := aTime; endif n% := n% + 1; until n% = gBurstSpikeNumber%; gBurstMeanFreq := (gBurstSpikeNumber%-1) / gBurstDuration; if gBurstSpikeNumber% >= 6 then var aEventTime[gBurstSpikeNumber%], 'room to load all the ISI event times from the entire burst aIntervals[gBurstSpikeNumber% - (6-1)]; 'the number of groups of 6-spike or 5-ISI boxcars that can be measured ChanData(chmSpikeEventDeletable%, aEventTime[], gBurstStartTime - 0.000000, gBurstEndTime + 0.000000); for n% := 0 to (gBurstSpikeNumber%-6) do aIntervals[n%] := aEventTime[n% + (6-1)] - aEventTime[n%]; 'compute duration of each 6-spike or 5-ISI boxcars next; aShortestInterval := aIntervals[Min(aIntervals[])]; aShortestIntervalStartTime := aEventTime[Min(aIntervals[])]; gBurstMax5spikeAvgFreq := (6-1) / aShortestInterval; ' gBurstMax5spikeAvgFreqTime := aShortestIntervalStartTime + 0.5 * aShortestInterval; 'record the center of the interval endif endif end 'MetricsBurstFrequency '---------------------------------------------------- ' MetricsBurstAutoPrePost '< 3/10/04 '---------------------------------------------------- proc MetricsBurstAutoPrePost(); gBurstManuallyMarked% := 0; MemDeleteTime(chmColoredPrePostBurstTemp%, 3, gEarlyTime, gLateTime); MetricsBurst(gSpikeDensityStartTime, gSpikeDensityEndTime); if (gTargetStepTime <> NaN) and (gBurstSpikeNumber% <> 0) then MetricsBurstPreTonic(gTargetStepTime, gBurstStartTime); MetricsBurstPreRate(); MetricsBurstPostTonic(gBurstEndTime, gLateTime - 0.002); '0.002 like ManualBurstModeAnalysis MetricsBurstPostRate(); else ResetPreBurst(); ResetPostBurst(); endif end 'MetricsBurstAutoPrePost '---------------------------------------------------- ' ComputeScreenWidth 'Compute the display width ' '< 3/10/04 '---------------------------------------------------- proc ComputeScreenWidth() gEarlyTime := gEarliestOnset-pPreOnsetSaveTime; 'first eye move - 0.650 (left edge of screen) gLateTime := gEarlyTime+(pScreenWidth%/kMS); 'left edge + screen width (right edge of screen)) 'check is it close to the end of file if gLateTime >= MaxTime() then gLateTime := MaxTime(); '7/16/04 The next line could potentially cause trouble when displaying traces in Graph. Please confirm. gEarlyTime := gLateTime-(pScreenWidth%/kMS); endif end 'ComputeScreenWidth '---------------------------------------------------- ' HighlightSaccadeAndBurstForPSTH '< 3/10/04 '---------------------------------------------------- proc HighlightSaccadeAndBurstForPSTH() View(gViewData%); if MemSetItem(chmPSTHsaccadeOnset%,0,gEarliestOnset) < 0 then Message("Error in marking event channel"); halt; endif if MemSetItem(chmPSTHsaccadeOffset%,0,gLatestOffset) < 0 then Message("Error in marking event channel"); halt; endif if (gBurstSpikeNumber% <> 0) and (gUnitData% = 1) then if MemSetItem(chmPSTHburstOnset%,0,gBurstStartTime) < 0 then Message("Error in marking event channel"); halt; endif if MemSetItem(chmPSTHburstOffset%,0,gBurstEndTime) < 0 then Message("Error in marking event channel"); halt; endif endif end 'HighlightSaccadeAndBurstForPSTH '---------------------------------------------------- ' AttributeShowSelected '< 3/10/04 '---------------------------------------------------- proc AttributeShowSelected() var i%, n%, aStr$, aView%, aLen%, aLenMax%, aPrefix$ := "XXX_", 'three character positions for up to attribute 999 and a space aSuffix$ := ": "; View(gViewAttr%); 'Make log view the current view EditSelectAll(); 'Select all text in log view EditClear(); 'Delete it aLenMax% := 0; n% := 0; repeat if gAttrShow%[n%] = 1 then aLen% := len(aPrefix$ + gAttrNam$[n%] + aSuffix$); if aLen% > aLenMax% then aLenMax% := aLen%; endif endif n% := n% + 1; until gAttrNam$[n%] = ""; n% := 0; repeat if gAttrShow%[n%] = 1 then aPrefix$ := Str$(n%) + " "; aLen% := len(aPrefix$); for i% := aLen% to 4 do aPrefix$ := " " + aPrefix$; next aStr$ := aPrefix$ + gAttrNam$[n%] + aSuffix$; aLen% := len(aStr$); for i% := aLen% to aLenMax% do aStr$ := aStr$ + " "; next if Abs(gAttrVal[gTrialAccepted%][n%]) = NaN then aStr$ := aStr$ + " NaN\n"; Print(aStr$); else aStr$ := aStr$ + "%7.2f" + "\n"; Print(aStr$, gAttrVal[gTrialAccepted%][n%]); endif endif n% := n% + 1; until gAttrNam$[n%] = ""; Print("\n"); end 'AttributeShowSelected '---------------------------------------------------- ' WriteFileAttributes 'Write to the output *.txt attribute file for display 'in Matlab Graph. '< 3/10/04 '---------------------------------------------------- proc WriteFileAttributes() var i%, j%, aNumAttr%, aAttrFilehandle%, aAttrFilename$; aAttrFilename$ := Mid$(gDatafilename$,1,Len(gDatafilename$)-3) + "txt"; aAttrFilehandle% := FileOpen(aAttrFilename$,8,1); ',"Type result file name"); if aAttrFilehandle% >= 0 then View(aAttrFilehandle%); 'Write the attribute names in the first row Print("%s\t","Trial Number"); 'first column (trial number) not a natural attribute aNumAttr% := 0; repeat Print("%s\t",gAttrNam$[aNumAttr%]); aNumAttr% := aNumAttr% + 1; until gAttrNam$[aNumAttr%] = ""; aNumAttr% := aNumAttr% - 1; Print("\n"); 'next row 'Now write the attributes ProgressBar("Saving Attributes",1,0); 'toggle the ProgressBar open for j% := 0 to (gTrialAccepted%-1) do ProgressBar("Saving Attributes",0,(100*(j%+1))/gTrialAccepted%); View(aAttrFilehandle%); Print("%d\t",j%+1); 'trial number for i% := 0 to (aNumAttr%) do if Abs(gAttrVal[j%][i%]) = NaN then Print("%s\t",Chr$(0)); 'NaN is Chr$(0) else Print("%13.6f\t",gAttrVal[j%][i%]); endif next; Print("\n"); 'next row next; ProgressBar("Saving Attributes",1,0); 'toggle the ProgressBar closed endif end 'WriteFileAttributes '---------------------------------------------------- ' SavePSTHChan '< 3/10/04 '---------------------------------------------------- proc SavePSTHChan() View(gViewData%); MemSave(chmPSTHsaccadeOnset%,chSaccadeOnset%); ChanTitle$(chSaccadeOnset%,"Saccade Onset Event"); MemSave(chmPSTHsaccadeOffset%,chSaccadeOffset%); ChanTitle$(chSaccadeOffset%,"Saccade End Event"); if gUnitData% = 1 then MemSave(chmPSTHburstOnset%,chBurstOnset%); ChanTitle$(chBurstOnset%,"Burst Onset Event"); MemSave(chmPSTHburstOffset%,chBurstOffset%); ChanTitle$(chBurstOffset%,"Burst End Event"); endif MemSave(chmPSTHtargetTime%,chTargetTime%); ChanTitle$(chTargetTime%,"Target Time Event"); end 'SavePSTHChan '---------------------------------------------------- ' Save1msBinRaster 'Makes raster in 1ms bin for exporting to the drawing 'program the source channel is chmSpikeEventDeletable% 'the destination real channel is ch1msBinEvent% := 27; '< 3/10/04 '---------------------------------------------------- proc Save1msBinRaster(); var LastView%; LastView% := View(gViewData%); MemSave(chmSpikeEventDeletable%,ch1msBinEvent%,0,1); DrawMode(ch1msBinEvent%,5,0.001,1); ChanShow(ch1msBinEvent%); YRange(ch1msBinEvent%,0,3); View(LastView%); end 'Save1msRaster '---------------------------------------------------- ' Visual 'In Burst mode the user is offered a chance to mark 'a visual burst area. '< 3/10/04 '---------------------------------------------------- func Visual%(); const kBinSize := 0.005, 'seconds kBinNum := 140; 'each var aTimeEnd, aPSTHVisualView%, aCu1%, aCu2%, aCurPos1, aCurPos2, sTime, aCount%, aVisSpikeNum%, aVisPeakFreq, aVisPeakFreqTime, aVisBurstOnset, aVisBurstEnd, aVisBurstDur, aVisSacSpk%, aTime, aPeakTime, aValue, aPeakValue, n%,numch%, x[200],y[200], aResult%, aBinDur%, aGuassianView%; FrontView(gViewData%); aBinDur% := (kBinNum * kBinSize) * 1000; var aGaussAccum[aBinDur%], aGaussTemp[aBinDur%]; 'bob 11/21/05 insert the PSTH event markers by reading the Target ABS step time for aCount% := 0 to gTrialAccepted%-1 do aResult% := MemSetItem(chmPSTHtargetTime%, 0, gAttrVal[aCount%][0]); ChanData(chUnitSmooth%, aGaussTemp, gAttrVal[aCount%][0], gAttrVal[aCount%][0] + aBinDur%); arrAdd(aGaussAccum[], aGaussTemp[]); if aResult% < 0 then Message("Error in marking event channel with attribute[0] = Target absolute step time"); endif next arrDiv(aGaussAccum[], gTrialAccepted%); aGuassianView% := FileNew(12); XYsetChan(0); XYaddData(1,aGaussAccum[],0.001); Xrange(0,kBinNum*kBinSize); WindowVisible(1); 'now show the window with all of its changes FrontView(gViewData%); 'psth analysis must be aimed at this WindowVisible(0); aTimeEnd := MaxTime(); aPSTHVisualView% := SetPsth(chmSpikeEventDeletable%, kBinNum, kBinSize, 0, chmPSTHtargetTime%, 2); 'spike ch, num bins, bin size, offset, trigger ch, 2=enables raster disp Process(0, aTimeEnd, 0, 1); View(aPSTHVisualView%); FrontView(aPSTHVisualView%); WindowVisible(3); 'make PSTH fill the screen Window(0,0,100,50); View(aPSTHVisualView%); WindowSize(100,50); View(aGuassianView%); Window(0,50,100,100); WindowTitle$("Gaussian(" + view(gViewData%).FileName$(3) + ")"); View(aPSTHVisualView%); aResult% := DupChan(1,1); DrawMode(aResult%,9,2,16,0); 'make raster dots large FrontView(aGuassianView%); aCu1% := CursorNew(0.07, 1); aCu2% := CursorNew(0.1, 2); CursorVisible(aCu1%, 1); CursorVisible(aCu2%, 1); CursorLabel(4,1,"onset Visual Burst"); CursorLabel(4,2,"offset Visual Burst"); CursorLabelPos(1, 1); CursorLabelPos(2, 3); aResult% := Query("\nMark a Visual Burst Region?\n"); if aResult% = 0 then View(aPSTHVisualView%); FileClose(0, -1); 'close psth window View(aGuassianView%); FileClose(0, -1); 'close guassian window return; 'no endif aResult% := Interact("Place cursor 1 at the beginning of the visual burst region and cursor 2 at the end",1023,0,"Cancel, There is No Visual Burst Region","Cursors are Properly Positioned Around the Visual Burst Region"); if aResult% = 1 then View(aPSTHVisualView%); FileClose(0, -1); 'close psth window View(aGuassianView%); FileClose(0, -1); 'close guassian window return; 'no endif aCurPos1 := Cursor(aCu1%); aCurPos2 := Cursor(aCu2%); 'this pos is re zero time if aCurPos1 > aCurPos2 then aCurPos1 := Cursor(aCu2%); aCurPos2 := Cursor(aCu1%); endif View(aPSTHVisualView%); FileClose(0, -1); 'close psth window View(aGuassianView%); FileClose(0, -1); 'close guassian window FrontView(gViewData%); sTime := -0.001; aCount% := 0; for aCount% := 0 to gTrialAccepted%-1 do sTime := gAttrVal[aCount%][0]; 'index 0 is abs target step time if sTime < aTimeEnd then aVisSpikeNum% := ChanMeasure(chmSpikeEventDeletable%,4,sTime+aCurPos1+0.000000,sTime+aCurPos2-0.000000); 'Count visual spikes 'do all of these only when spike > 0 if aVisSpikeNum% > 0 then aVisBurstOnset := NextTime(chmSpikeEventDeletable%,sTime+aCurPos1+0.000000); 'VisBurstOnset is the first spike after cursor 1 aVisBurstEnd := LastTime(chmSpikeEventDeletable%,sTime+aCurPos2-0.000000); 'VisBurstEnd is the first spike before cursor 2 'that small number to make sure not to pick the spike coincide with the time if aVisSpikeNum% > 1 then aVisBurstDur := aVisBurstEnd-aVisBurstOnset; else aVisBurstDur := NaN; endif 'finding peak burst if spike nr > 1 if aVisSpikeNum% > 1 then aPeakValue := 0; aTime := sTime+aCurPos1; n% := 0; repeat aTime := NextTime(chmInstantRate%,aTime); aValue := ChanValue(chmInstantRate%,aTime); if aPeakValue < aValue then aPeakValue := aValue; aPeakTime := aTime; endif n% := n%+1; aVisPeakFreq := aPeakValue; aVisPeakFreqTime := aPeakTime; until n% = aVisSpikeNum%; else aVisPeakFreq := NaN; aVisPeakFreqTime := NaN; endif else aVisSpikeNum% := 0; aVisburstOnset := NaN; aVisBurstEnd := NaN; aVisBurstDur := NaN; aVisPeakFreq := NaN; aVisPeakFreqTime := NaN; endif if aVisBurstOnset > (NaN-3000) then gAttrVal[aCount%][65] := NaN; else gAttrVal[aCount%][65] := (aVisBurstOnset-sTime) * kMS; 'Vis latency endif gAttrVal[aCount%][66] := aVisBurstDur*kMS; 'Vis burst dur gAttrVal[aCount%][67] := aVisSpikeNum%; 'Vis spike nr gAttrVal[aCount%][68] := aVisPeakFreq; 'Vis Peak freq if aVisPeakFreqTime > (NaN-3000) then gAttrVal[aCount%][69] := NaN; else gAttrVal[aCount%][69] := (aVisPeakFreqTime-sTime) * kMS; 'Vis peak freq latency endif 'Compute number of spikes between end of vis burst and saccadic burst start if (aVisBurstEnd > (NaN-3000)) then gAttrVal[aCount%][70] := NaN; else if (gAttrVal[aCount%][23] > 0) and (aVisBurstEnd < (gAttrVal[aCount%][22]+(gAttrVal[aCount%][13]/kMS))) then aVisSacSpk% := ChanMeasure(chmSpikeEventDeletable%,4,aVisBurstEnd+0.00001,gAttrVal[aCount%][22]+(gAttrVal[aCount%][13]/kMS)-0.00001); if aVisSacSpk% > 0 then gAttrVal[aCount%][70] := aVisSacSpk%; else gAttrVal[aCount%][70] := NaN; endif else gAttrVal[aCount%][70] := NaN; endif endif aVisSacSpk% := 0; else 'No Target, so everything is NaN gAttrVal[aCount%][65] := NaN; gAttrVal[aCount%][66] := NaN; gAttrVal[aCount%][67] := NaN; gAttrVal[aCount%][68] := NaN; gAttrVal[aCount%][69] := NaN; gAttrVal[aCount%][70] := NaN; endif next; end 'Visual '---------------------------------------------------- ' WriteFileTraces 'Writes heye, veye, hevel, vevel, htarget, vtarget, 'spikes in 1ms resolution for each traces ' '3/30/06 REPLACED with DialogSelectTraces so user 'can choose which traces are written. ' '< 3/10/04 '---------------------------------------------------- proc WriteFileTraces(); var aResult%, i%, k%, aTime, bTime, aFreq, aBinNum%, NoSpk%[4], PadArray%[8], headerB$, version%, endian%, datatype%, numofbytes%, arrayflagsheader1%, arrayflagsheader2%, arrayflags1%, arrayflags2%, dimarrayheader1%, dimarrayheader2%, arrayrow%, arraycolumn%, arraynameheader1%, arraynameheader2%, arrayname$, numtype%, numofelementbytes%, aDatfilename$, aFileNum%, aNumOfVars%; if gUnitData% = 1 then aNumOfVars% := 7; 'include Raster & IFR channels for unit data else aNumOfVars% := 6; 'exclude Raster & IFR channels for behavioral data endif var VarName$[aNumOfVars%], LabelName$[aNumOfVars%], ResOfVars[aNumOfVars%], VTypes[aNumOfVars%]; View(gViewData%); ArrConst(NoSpk%[],0); ArrConst(PadArray%[],0); var DataArray[pScreenWidth%], TempAlignment[pScreenWidth%], DataArrayInt%[pScreenWidth%]; 'Initialization for *.mat file starts here headerB$ := "Matlab 5 mat-file created by spike2 "; version% := 0x0100; '0x0100, must be written as int16 endian% := 0x4d49; 'MI endian check 'write the init to file aDatfilename$ := Mid$(gDatafilename$,1,Len(gDatafilename$)-3) + "mat"; 'save with same name as data, but with mat extension aFileNum% := FileOpen(aDatfilename$,9,1); if aFileNum% < 0 then halt; endif View(aFileNum%); BWriteSize(124,headerB$); BWriteSize(2,version%); BWriteSize(2,endian%); 'end writing init 'write each trace to a Matlab array variable 'HORIZONTAL EYE -- Writing horiz eye pos trace as single precision floating point variable he '-------------------------- WriteTrace(chHE%[1], "t01", "HE", aFileNum%); 'VERTICAL EYE -- Writing vert eye pos trace as single precision floating point variable ve '-------------------------- WriteTrace(chVE%[1], "t02", "VE", aFileNum%); 'HORIZONTAL EYE VELOCITY -- Writing horiz eye velocity trace as single precision floating point variable hvel '-------------------------- WriteTrace(chmHEvel%[1], "t03", "HE Velocity", aFileNum%); 'VERTICAL EYE VELOCITY -- Writing vert eye velocity trace as single precision floating point variable vvel '-------------------------- WriteTrace(chmVEvel%[1], "t04", "VE Velocity", aFileNum%); 'HORIZONTAL TARGET -- Writing horiz target trace as single precision floating point variable ht '-------------------------- WriteTrace(chHT%[1], "t05", "HT", aFileNum%); 'VERTICAL TARGET -- Writing vert target trace as single precision floating point variable vt '-------------------------- WriteTrace(chVT%[1], "t06", "VT", aFileNum%); if gUnitData% = 1 then 'FREQUENCY '-------------------------- 'Preparing to write spike as frequency...Man..this is tough! 'variable name is spf, in single precision float, in 0.5ms resolution var DataArrayx2[pScreenWidth%*2]; ArrConst(DataArrayx2[],0);'Init DataArrayx2 with zeros ProgressBar("Writing Frequency Traces", 1, 0); 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040007; 'global and single precision arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := pScreenWidth%*2; 'times 2 because of 0.5ms resolution arraycolumn% := gTrialAccepted%; 'Num of trials is # of columns 'end arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000003; arrayname$ := "t07"; 'max 4 characters to avoid complication numtype% := 0x00000007; 'single precision 4 byte worth 'if the program analyzes behavior only, then it will only write [0 0] in spf, each is 4 bytes if gUnitData% = 0 then arrayrow% := 1; arraycolumn% := 2; endif numofelementbytes% := 4*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(2,arraynameheader1%); BWriteSize(2,arraynameheader2%); BWriteSize(4,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of spf tag initialization 'if the program analyzes behavior only, then it will only write [0 0] in spf if gUnitData% = 0 then BWriteSize(4,NoSpk%[:2]); else 'loop through the attribute data to get spike 1010 traces for i% := 0 to gTrialAccepted%-1 do View(gViewData%); aTime := gAttrVal[i%][39]; bTime := gAttrVal[i%][39]; repeat bTime := NextTime(chmInstantRate%,bTime); if bTime > 0 then aFreq := ChanValue(chmInstantRate%,bTime); 'How many 0.5ms bin before bTime?? aBinNum% := Trunc((bTime-aTime)*2000); if bTime<=gAttrVal[i%][61] then DataArrayx2[aBinNum%] := aFreq; 'because array index starts from zero, only when bTime < right edge endif endif until (bTime>=gAttrVal[i%][61]) or (bTime<0); View(aFileNum%); BWriteSize(4,DataArrayx2[]); ArrConst(DataArrayx2[],0); 'reset DataArrayx2 to zeros ProgressBar("Writing Frequency Traces", 0, (100*(i%+1))/gTrialAccepted%); next; 'done writing spf 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif endif ProgressBar("Writing Frequency Traces", 1, 0); endif 'if gUnitData% = 1 'TRACE NAMES '-------------------------- 'Prepare to write variable names 'string Length 12345678901234567890123456789 = 29 characters VarName$[00] := "Horizontal Eye Position "; VarName$[01] := "Vertical Eye Position "; VarName$[02] := "Horizontal Eye Velocity "; VarName$[03] := "Vertical Eye Velocity "; VarName$[04] := "Horizontal Target Position "; VarName$[05] := "Vertical Target Position "; if gUnitData% = 1 then VarName$[06] := "Spike Instantaneous Frequency"; endif 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040004; 'global and character arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := aNumOfVars%; arraycolumn% := Len(VarName$[00]); 'check string length arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000008; arrayname$ := "TraceNam"; 'max 8 characters to avoid complication numtype% := 0x00000004; 'character as 16 bit unsigned int 2 byte worth numofelementbytes% := 2*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(4,arraynameheader1%); BWriteSize(4,arraynameheader2%); BWriteSize(8,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of VarNames initialization 'Write to mat for i% := 1 to arraycolumn% do for k% := 0 to aNumOfVars%-1 do BWriteSize(2,Asc(Mid$(VarName$[k%],i%,1))); next; next; 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif 'done writing VarNames 'TRACE LABELS '-------------------------- 'string Length 1234567890 LabelName$[00] := "HE deg "; LabelName$[01] := "VE deg "; LabelName$[02] := "Hvel deg/s"; LabelName$[03] := "Vvel deg/s"; LabelName$[04] := "HT deg "; LabelName$[05] := "VT deg "; if gUnitData% = 1 then LabelName$[06] := "InsFr sp/s"; endif 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040004; 'global and character arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := aNumOfVars%; arraycolumn% := Len(LabelName$[00]); 'check string length 'end arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000008; arrayname$ := "TraceLbl"; 'max 8 characters to avoid complication numtype% := 0x00000004; 'character as 16 bit unsigned int 2 byte worth numofelementbytes% := 2*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(4,arraynameheader1%); BWriteSize(4,arraynameheader2%); BWriteSize(8,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of VarLabel initialization 'Write to mat for i% := 1 to arraycolumn% do for k% := 0 to aNumOfVars%-1 do BWriteSize(2,Asc(Mid$(LabelName$[k%],i%,1))); next; next; 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif 'done writing VarNames 'Writing Resolution and type var '-------------------------- ResOfVars[00] := 1; VTypes[00] := 7; ResOfVars[01] := 1; VTypes[01] := 7; ResOfVars[02] := 1; VTypes[02] := 7; ResOfVars[03] := 1; VTypes[03] := 7; ResOfVars[04] := 1; VTypes[04] := 7; ResOfVars[05] := 1; VTypes[05] := 7; if gUnitData% = 1 then ResOfVars[06] := 0.5; VTypes[06] := 7; endif 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040007; 'global and single precision arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := aNumOfVars%; arraycolumn% := 2; 'end arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000008; arrayname$ := "ResTypes"; 'max 8 characters to avoid complication numtype% := 0x00000007; 'single precision 4 byte worth numofelementbytes% := 4*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(4,arraynameheader1%); BWriteSize(4,arraynameheader2%); BWriteSize(8,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of ResTypes initializationn 'Write to mat BWriteSize(4,ResOfVars[]); BWriteSize(4,VTypes[]); 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif View(aFileNum%); FileClose(); end 'WriteFileTraces '---------------------------------------------------- ' WriteArrayofNumbersDimX2 'Writes the trace resolutions to a Matlab-formatted 'file. ' 3/30/06 '---------------------------------------------------- proc WriteArrayofNumbersDimX2(accepted%, aVarName$, aResOfVars[], aVTypes[], aFileNum%); var i%,k%, aResult%, datatype%, PadArray%[8], arrayflagsheader1%, arrayflagsheader2%, arrayflags1%, arrayflags2%, dimarrayheader1%, dimarrayheader2%, arrayrow%, arraycolumn%, arraynameheader1%, arraynameheader2%, arrayname$, numtype%, numofelementbytes%, numofbytes%; var dataArrayA[accepted%], dataArrayB[accepted%]; for i% := 0 to accepted%-1 do dataArrayA[i%] := aResOfVars[i%]; dataArrayB[i%] := aVTypes[i%]; next 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040007; 'global and single precision arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := accepted%; arraycolumn% := 2; 'end arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000008; arrayname$ := aVarName$; 'max 8 characters to avoid complication numtype% := 0x00000007; 'single precision 4 byte worth numofelementbytes% := 4*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(4,arraynameheader1%); BWriteSize(4,arraynameheader2%); BWriteSize(8,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of ResTypes initialization 'Write to mat BWriteSize(4,aResOfVars[]); BWriteSize(4,aVTypes[]); 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif end 'WriteArrayofNumbersDimX2 '---------------------------------------------------- ' WriteArrayOfStringsX1 'Writes the names to a Matlab-formatted file. ' 3/30/06 '---------------------------------------------------- proc WriteArrayOfStringsX1(accepted%, aVarName$, aName$[], aFileNum%); var i%,k%, aResult%, datatype%, PadArray%[8], arrayflagsheader1%, arrayflagsheader2%, arrayflags1%, arrayflags2%, dimarrayheader1%, dimarrayheader2%, arrayrow%, arraycolumn%, arraynameheader1%, arraynameheader2%, arrayname$, numtype%, numofelementbytes%, numofbytes%; 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040004; 'global and character arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := accepted%; arraycolumn% := Len(aName$[00]); 'check string length arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000008; arrayname$ := aVarName$; 'max 8 characters to avoid complication numtype% := 0x00000004; 'character as 16 bit unsigned int 2 byte worth numofelementbytes% := 2*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(4,arraynameheader1%); BWriteSize(4,arraynameheader2%); BWriteSize(8,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of aNames initialization 'Write to mat for i% := 1 to arraycolumn% do for k% := 0 to accepted%-1 do BWriteSize(2,Asc(Mid$(aName$[k%],i%,1))); next; next; 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif end 'WriteArrayOfStringsX1 '---------------------------------------------------- ' WriteTrace 'Writes trace data to a Matlab-formatted file. ' 10/27/05 '---------------------------------------------------- proc WriteTrace(aCh%, anArrayName$, aTraceLabel$, aFileNum%) var aResult%, DataLength%, PadArray%[8], datatype%, numofbytes%, arrayflagsheader1%, arrayflagsheader2%, arrayflags1%, arrayflags2%, dimarrayheader1%, dimarrayheader2%, arrayrow%, arraycolumn%, arraynameheader1%, arraynameheader2%, arrayname$, numtype%, numofelementbytes%, i%, aTime; var DataArray[pScreenWidth%], TempAlignment[pScreenWidth%], DataArrayInt%[pScreenWidth%]; ArrConst(PadArray%[],0); ProgressBar("Writing "+ aTracelabel$ + " Traces", 1, 0); 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040007; 'global and single precision array arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := pScreenWidth%; 'aTraceLength% # of rows arraycolumn% := gTrialAccepted%; 'Num of trials is # of columns 'end arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000003; arrayname$ := anArrayName$; 'max 4 characters to avoid complication numtype% := 0x00000007; 'single precision numofelementbytes% := 4*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(2,arraynameheader1%); BWriteSize(2,arraynameheader2%); BWriteSize(4,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of tag initialization 'loop through the attribute data to get horiz eye pos traces for i% := 0 to gTrialAccepted%-1 do View(gViewData%); aTime := gAttrVal[i%][39]; DataLength% := ChanData(aCh%,DataArray[],aTime,aTime+(pScreenWidth%/kMS)); ProgressBar("Writing "+ aTracelabel$ + " Traces", 0, (100*(i%+1))/gTrialAccepted%); View(aFileNum%); BWriteSize(4,DataArray[]); next; 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif ProgressBar("Writing "+ aTracelabel$ + " Traces", 1, 0); end 'WriteTrace '---------------------------------------------------- ' WriteBlockUnit 'Writes unit data to a Matlab-formatted file. ' 3/30/06 '---------------------------------------------------- proc WriteBlockUnit(anArrayName$, aTraceLabel$, aFileNum%) var aResult%, DataLength%, bTime, aFreq, aBinNum%, NoSpk%[4], '3/30/06 I believe this is unused and can be deleted at a stable time PadArray%[8], datatype%, numofbytes%, arrayflagsheader1%, arrayflagsheader2%, arrayflags1%, arrayflags2%, dimarrayheader1%, dimarrayheader2%, arrayrow%, arraycolumn%, arraynameheader1%, arraynameheader2%, arrayname$, numtype%, numofelementbytes%, i%, aTime; var DataArray[pScreenWidth%], TempAlignment[pScreenWidth%], DataArrayInt%[pScreenWidth%]; ArrConst(NoSpk%[],0); ArrConst(PadArray%[],0); 'FREQUENCY '-------------------------- 'Preparing to write spike as frequency...Man..this is tough! 'variable name is spf, in single precision float, in 0.5ms resolution var DataArrayx2[pScreenWidth%*2]; ArrConst(DataArrayx2[],0);'Init DataArrayx2 with zeros ProgressBar("Writing "+ aTracelabel$ + " Traces", 1, 0); 'Data Tags below are fix datatype% := 0x0000000e; 'matrix arrayflagsheader1% := 0x00000006; arrayflagsheader2% := 0x00000008; arrayflags1% := 0x00040007; 'global and single precision arrayflags2% := 0x00000000; dimarrayheader1% := 0x00000005; dimarrayheader2% := 0x00000008; arrayrow% := pScreenWidth%*2; 'times 2 because of 0.5ms resolution arraycolumn% := gTrialAccepted%; 'Num of trials is # of columns 'end arraynameheader1% := 0x00000001; arraynameheader2% := 0x00000003; arrayname$ := anArrayName$; 'max 4 characters to avoid complication numtype% := 0x00000007; 'single precision 4 byte worth numofelementbytes% := 4*arrayrow%*arraycolumn%; 'calculate this if (numofelementbytes% mod 8) <> 0 then numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8 + (8-(numofelementbytes% mod 8)); 'the last term calculate the nr of padding bytes else numofbytes% := numofelementbytes% + 8 + 8 + 8 + 8 + 8 + 8; endif 'Write Data Tag View(aFileNum%); BWriteSize(4,datatype%); BWriteSize(4,numofbytes%); BWriteSize(4,arrayflagsheader1%); BWriteSize(4,arrayflagsheader2%); BWriteSize(4,arrayflags1%); BWriteSize(4,arrayflags2%); BWriteSize(4,dimarrayheader1%); BWriteSize(4,dimarrayheader2%); BWriteSize(4,arrayrow%); BWriteSize(4,arraycolumn%); BWriteSize(2,arraynameheader1%); BWriteSize(2,arraynameheader2%); BWriteSize(4,arrayname$); BWriteSize(4,numtype%); BWriteSize(4,numofelementbytes%); 'end of spf tag initialization 'loop through the attribute data to get spike 1010 traces for i% := 0 to gTrialAccepted%-1 do View(gViewData%); aTime := gAttrVal[i%][39]; bTime := gAttrVal[i%][39]; repeat bTime := NextTime(chmInstantRate%,bTime); if bTime > 0 then aFreq := ChanValue(chmInstantRate%,bTime); 'How many 0.5ms bin before bTime?? aBinNum% := Trunc((bTime-aTime)*2000); 'if bTime <= gAttrVal[i%][61] then if (bTime <= gAttrVal[i%][61]) and (aBinNum% <= pScreenWidth%*2-1) then DataArrayx2[aBinNum%] := aFreq; 'because array index starts from zero, only when bTime < right edge endif endif 'until (bTime >= gAttrVal[i%][61]) or (bTime < 0); until (bTime >= gAttrVal[i%][61]) or (bTime < 0) or (aBinNum% >= pScreenWidth%*2-1); View(aFileNum%); BWriteSize(4,DataArrayx2[]); ArrConst(DataArrayx2[],0); 'reset DataArrayx2 to zeros ProgressBar("Writing "+ aTracelabel$ + " Traces", 0, (100*(i%+1))/gTrialAccepted%); next; 'done writing spf 'Need padding? if (numofelementbytes% mod 8) <> 0 then aResult% := BWriteSize(1,PadArray%[:(8-(numofelementbytes% mod 8))]); if aResult% < 0 then message("The result value is = %d \n", aResult%); endif endif ProgressBar("Writing "+ aTracelabel$ + " Traces", 1, 0); end 'WriteBlockUnit '---------------------------------------------------- ' DeleteMarks ' 5/17/07 changed routine to delete marks anywhere on ' the trace, from beginning to end. ; '< 3/10/04 '---------------------------------------------------- proc DeleteMarks() var i%; View(gViewData%); 'MemDeleteTime(chmMarkerHTarget%,3,gEarlyTime,gLateTime); 'MemDeleteTime(chmMarkerVTarget%,3,gEarlyTime,gLateTime); MemDeleteTime(chmMarkerHTarget%,3,0,maxtime()); 'delete ALL marks MemDeleteTime(chmMarkerVTarget%,3,0,maxtime()); 'delete ALL marks for i% := 1 to kCh2Analyze do '3 do if ChanKind(chmHEpeakVel%[i%]) > 0 then 'MemDeleteTime(chmHEpeakVel%[i%],3,gEarlyTime,gLateTime); 'MemDeleteTime(chmVEpeakVel%[i%],3,gEarlyTime,gLateTime); 'MemDeleteTime(chmMarkerHEye%[i%],3,gEarlyTime,gLateTime); 'MemDeleteTime(chmMarkerVEye%[i%],3,gEarlyTime,gLateTime); MemDeleteTime(chmHEpeakVel%[i%],3,0,maxtime()); 'delete ALL marks MemDeleteTime(chmVEpeakVel%[i%],3,0,maxtime()); 'delete ALL marks MemDeleteTime(chmMarkerHEye%[i%],3,0,maxtime()); 'delete ALL marks MemDeleteTime(chmMarkerVEye%[i%],3,0,maxtime()); 'delete ALL marks endif next if pCellType% <> kModeBehavior% then 'MemDeleteTime(chmColoredEvent%,3,gEarlyTime,gLateTime); 'MemDeleteTime(chmColoredPrePostBurstTemp%,3,gEarlyTime,gLateTime); 'MemDeleteTime(chmMarkerSpd%,3,gEarlyTime,gLateTime); MemDeleteTime(chmColoredEvent%,3,0,maxtime()); 'delete ALL marks MemDeleteTime(chmColoredPrePostBurstTemp%,3,0,maxtime()); 'delete ALL marks MemDeleteTime(chmMarkerSpd%,3,0,maxtime()); 'delete ALL marks endif end 'DeleteMarks '---------------------------------------------------- ' ProgressBar 'Gives the user a visual way to observe how a process 'is progressing. '3/29/04 '---------------------------------------------------- proc ProgressBar(aTitle$, aToggle, aPercent) var x[4], y[4], hMargin := 0.9, 'area above and below the bar wMargin := 5, 'area left and right of the bar h := 1, 'height of bar w := 100, 'length of bar aOffcenter := 0.25, 'three bars are used, one is centered the others are offset aResult; x[0] := wMargin - 1 ; 'load the data to draw the box y[0] := hMargin; x[1] := wMargin + w; y[1] := hMargin; x[2] := wMargin + w; y[2] := hMargin + h; x[3] := wMargin - 1; y[3] := hMargin + h; 'open or close the view if aToggle = 1 then if ViewKind(gProgressView%) <> 12 then 'if the view does not exist create it gProgressView% := FileNew(12); 'keep window hidden Window(35,46,65,53); 'using percent units WindowTitle$(aTitle$); XRange(0,wMargin*2 + w); 'progress bar plus margins YRange(1,0,hMargin*2 + h); 'progress bar plus margins XYColour(1,kBlack%); 'black lines XAxis(0); 'no axis marks YAxis(0); XYJoin(1,2); 'connect the dots XYDrawMode(1,2,0); 'no points XYDrawMode(1,4,1); 'line thickness 1 XYSetChan(0); 'channel one XYSetChan(0); 'channel two XYSetChan(0); 'channel three XYColour(2,kRed2%); XYColour(3,kRed2%); XYColour(4,kRed2%); 'make all the bars red aResult := XYAddData(1,x[],y[]); 'draw the box; WindowVisible(1); 'now show the window with all of its changes else view(gProgressView%); FileClose(0,-1); 'if the view exists, close it endif 'advance the bar else 'added for safety, but doesn't seem to be required since I can't click away the progress bar window until it is done if ViewKind(gProgressView%) = 12 then 'only if the progress bar window is present, not clicked away var i, aCount, aCenter; FrontView(gProgressView%); 'aim at the progress bar view View(gProgressView%); WindowTitle$(aTitle$); 'refresh the window title in case it was changed Yield(); 'required to update video display aCenter := (y[0] + y[2]) / 2; if aPercent > 0 then 'protect against negative percent aPercent := aPercent - 1; 'one percent really draws a box from 0 up to 1, 99 up to 100 aCount := XYCount(2); 'only add new data, do not over draw anything for i := aCount to aPercent do aResult := XYAddData(2, i+wMargin, aCenter-aOffcenter); 'draw the progress bars aResult := XYAddData(3, i+wMargin, aCenter); aResult := XYAddData(4, i+wMargin, aCenter+aOffcenter); next endif endif endif Yield(); 'required to update video display end 'ProgressBar '---------------------------------------------------- 'NOT USED, WAITING FOR SOMEONE TO REQUEST ITS FUNCTION ' DeleteSpike ' It was agreed with Robi that this routine would ' remain unconnected and unavailable until a user ' asked for it ' '< 3/10/04 '---------------------------------------------------- proc zzDeleteSpike() var aResonse%, aCur1, aCur2, gausskernel[4*pSigma*8+1]; CursorVisible(-1,0); 'All cursor invisible Cursor(1,gEarliestOnset); CursorVisible(1,1); Cursor(2,gEarliestOnset+0.03); CursorVisible(2,1); '30ms apart CursorLabel(4,1,"beg Spk Del"); CursorLabel(4,2,"end Spk Del"); aResonse% := Interact("Place spike(s) to be deleted between Cursor 1 and 2. Use magnifier button if necessary.",1023,0,"Enter|0x0d"); FrontView(gViewData%); aCur1 := Cursor(1); aCur2 := Cursor(2); if aCur1 < aCur2 then MemDeleteTime(chmSpikeEventDeletable%,3,aCur1,aCur2); MemDeleteTime(chmInstantRate%,3,aCur1,aCur2); DrawMode(chmInstantRate%,2,1); DrawMode(chmInstantRate%,7,3); 'recompute instant freq else MemDeleteTime(chmSpikeEventDeletable%,3,aCur2,aCur1); MemDeleteTime(chmInstantRate%,3,aCur2,aCur1); DrawMode(chmInstantRate%,2,1); DrawMode(chmInstantRate%,7,3); 'recompute instant freq endif 'Recompute gaussian spd GaussKernelGen(gausskernel[]); EventToWaveform(0.001*pSigma*4,chmSpikeEventDeletable%,chTempSpd%,BinSize(chHE%[1]),gEarlyTime,gLateTime,4095,0,1,gausskernel[]); var TempSpdArray[(gLateTime-gEarlyTime)/BinSize(chTempSpd%)]; ChanData(chTempSpd%,TempSpdArray[],gEarlyTime,gLateTime); ChanTitle$(chTempSpd%,"Guassian"); 'redraw gaussian spd ChanWriteWave(chUnitSmooth%,TempSpdArray[],gEarlyTime); CursorVisible(-1,0); 'All cursor invisible CursorVisible(8,1); CursorVisible(9,1); end 'DeleteSpike '---------------------------------------------------- 'NOT USED, WAITING FOR SOMEONE TO REQUEST ITS FUNCTION ' AddSpike ' It was agreed with Robi that this routine would ' remain unconnected and unavailable until a user ' asked for it ' '< 3/10/04 '---------------------------------------------------- proc zzAddSpike() var aResonse%, aCur1, gausskernel[4*pSigma*8+1]; CursorVisible(-1,0); 'All cursor invisible Cursor(1,gEarliestOnset); CursorVisible(1,1); CursorLabel(4,1,"Add Spk here"); aResonse% := Interact("Place Cursor 1 at where you want a spike added. Use magnifier button if necessary.",1023,0,"Enter|0x0d"); FrontView(gViewData%); aCur1 := Cursor(1); MemSetItem(chmSpikeEventDeletable%,0,aCur1); 'fix instant rate MemSetItem(chmInstantRate%,0,aCur1); DrawMode(chmInstantRate%,2,1); DrawMode(chmInstantRate%,7,3); 'recompute instant freq 'Recompute gaussian spd GaussKernelGen(gausskernel[]); EventToWaveform(0.001*pSigma*4,chmSpikeEventDeletable%,chTempSpd%,BinSize(chHE%[1]),gEarlyTime,gLateTime,4095,0,1,gausskernel[]); var TempSpdArray[(gLateTime-gEarlyTime)/BinSize(chTempSpd%)]; ChanData(chTempSpd%,TempSpdArray[],gEarlyTime,gLateTime); ChanTitle$(chTempSpd%,"Guassian"); 'redraw gaussian spd ChanWriteWave(chUnitSmooth%,TempSpdArray[],gEarlyTime); CursorVisible(-1,0); 'All cursor invisible CursorVisible(8,1); CursorVisible(9,1); end 'AddSpike 'Light travels faster than sound... 'This is why some people appear bright until you hear them speak