|
Size: 1937
Comment:
|
Size: 18591
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 1: | Line 1: |
When using E-Prime with a SMI eye tracker, E-Prime should communicate with iView X, the eye tracking software, to stop and stop the recording, indicate the start of each trial and save the data. The way SMI prefer to do this is using an ethernet connection and the UDP protocol, but E-Prime cannot handle this. The only way, at the moment, is by using the serial port. To do this you wil have to add the following things to your E-Prime script: 1 - Create a 'Serial' device, by going to 'Experiment object' properties, then selecting the 'Devices' tab, then 'Add' and 'Serial'. The default settings should work. 2 - At the start of your experiment, when you want the eye tracker to start recording, add these lines, in an inline object: ' Flush serial connection and clear eye tracker recording buffer |
= SMI now has a toolkit which makes using their eye trackers with E-Prime much easier, so the following is outdated = = Ask Maarten van Casteren for details if you need to know more = == Running an Eye tracking experiment with E-Prime == When using E-Prime with a SMI eye tracker, E-Prime should communicate with iView X, the eye tracking software, to start and stop the recording, indicate the start of each trial, specify the stimulus used and finally save the data. The way SMI prefer to do this is by using an ethernet connection and the UDP protocol, but E-Prime cannot handle this. For this reason SMI have developed a toolkit that can take care of the communication with the eye tracker. The toolkit consists of two parts: first a dll file that contains the actual executable code, and second an E-Prime package file that makes sure the functionality in the dll is available within an E-Prime script in a user friendly way. To be able to use an eye tracker with this toolkit you need to do the following: 1 - Add the package to your E-Prime script. In the 'structure' window double-click on 'Experiment' and then select the 'Packages' tab. Press 'Add' and select the 'iView_X_SDK_CBU' package. If this is not available you'll have to install it: the file 'iViewXAPI_CBU.epk2' should be in 'Program Files\PST\E-Prime 2.0\Program\Packages'. If the Packages folder doesn't exist, it should be created. 2 - At the start of your experiment, add these lines, in an inline object: {{{ ' Connect to the Eye Tracker over the ethernet. The IP adresses are the ' ones we usually use, so this should work at the CBU without modification if not iView_X_SDK_CBU_Connect("192.168.1.1", 4444, "192.168.1.2", 5555) then Mouse.ShowCursor True MsgBox "Connect failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if }}} 3 - You need to calibrate the eye tracker before you can use it. Put this code in an inline object to do so. {{{ ' Use 13 targets for calibration iView_X_SDK_CBU_SetCalMethod 13 if not iView_X_SDK_CBU_Calibrate then Mouse.ShowCursor True MsgBox "Calibration failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if }}} 4 - You then should check the calibration to see if it was sufficiently precise. This is called validation. You should repeat calibration and validation until you have the required precision. {{{ ' Do the validation if not iView_X_SDK_CBU_Validate( DeviationXL, DeviationYL, DeviationXR, DeviationYR) Then Mouse.ShowCursor True MsgBox "Validation Failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if ' Present the results Mouse.ShowCursor true MsgBox "MeanDeviation: "& DeviationXL &" " & DeviationYL &" " & DeviationXR &" " & DeviationYR Mouse.ShowCursor false }}} 5 - Just before you start presenting your stimuli you should start the eye tracking recording {{{ ' Start a recording on the Eye Tracking computer if not iView_X_SDK_CBU_StartRecording then Mouse.ShowCursor True MsgBox "StartRecording failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if }}} 6 - At the start of each trial, or just before your main stimulus is being presented, add a 'message line', preferably with your stimulus name as an argument (NB if you are presenting images, sending the name of the image file you are presenting will greatly facilitate analysis using the BeGaze software, as the associations between the trial and image will then be made automatically by the software. For more info, see BeGaze): {{{ ' Send a message to be included in the Eye Tracking recording. ' This will normally be a trial number, or a condition code or ' something like that. if not iView_X_SDK_CBU_SendMessage("msg") then Mouse.ShowCursor True MsgBox "SendMessage 5 failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort ListA.Terminate end if }}} 7 - Finally, at the end of th experiment put these lines in an inline object: {{{ ' First stop the current recording if not iView_X_SDK_CBU_StopRecording then Mouse.ShowCursor True MsgBox "StopRecording failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if ' Then save the data. Get the filename that E-Prime uses for its output dim fullfilename as string fullfilename = c.datafile.filename ' Split the filename in its parts dim fileroot as string fileroot = FileParse$(fullfilename, 4) ' Eye tracking data will now be saved under the same name as the E-Prime data, in the iViewX folder ' If you want it to go to your own folder then add this to the filerootname. if not iView_X_SDK_CBU_SaveData(fileroot, "", "", 1) then Mouse.ShowCursor True MsgBox "SaveData failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if ' And finally close the connection with the eye tracker. if not iView_X_SDK_CBU_Disconnect then Mouse.ShowCursor True MsgBox "Disconnect failed: " & iView_X_SDK_CBU_GetErrorString iView_X_SDK_CBU_Abort End end if }}} Obviously, the filename can be changed to whatever is best for you. Note that iView X cannot save to a directory that doesn't exist, so make sure to either create the correct directory, or write to root. == Running the script == When running the script you should go through these steps: 1 - Switch on the eye tracking hardware and install your subject. 2 - Start the iView X program on the eye tracking computer. 3 - Make sure the eye picture looks good and the eye gaze is correctly tracked. Verify this by asking the subject to look at all 4 corners of the screen. 4 - Run your E-Prime script. == Calibration from within E-Prime == The calibration can also be performed by E-Prime. To be able to do this you need to incorporate a bit of inline code in your E-Prime script. This code will communicate with the eye tracker software and put targets on the screen in response to requests from iView X. All of the calibration code is in a single inline object, and the only other thing that needs to be done is to define a serial port device in the 'Devices' tab of the 'Experimental Object Properties' dialogue. Make sure to give this the name 'Serial', which is actually the default name that E-Prime will suggest. The first bit of inline code should be inserted in the E-Prime script at the point where the calibration is to be performed. To start the recording, mark the trials, and to close and save the recording the same bits of code should be inserted as used in the previous section. The calibration uses the settings specified in iView X, which means that you will have to specify 'auto accept' or other settings there. The only thing that the script sets is the number of calibration points used. This is set to 13, but can easily be changed to another value. One warning: this code hasn't been tested much yet, so might not always work as expected. Be careful and please report any problems to Maarten van Casteren. {{{ ' Flush serial connection |
| Line 11: | Line 178: |
| dim strData as string strData = "ET_CLR" & Chr(10) & Chr(13) Serial.WriteString strData ' Start eye tracker recording strData = "ET_REC" & Chr(10) & Chr(13) Serial.WriteString strData 3 - at the start of each trial, or just before your main stimulus is being presented, add this: Dim strData As String strData = "ET_REM " & c.GetAttrib("facestim") & Chr(10) & Chr(13) Serial.WriteString strData 4 - Finally, at the end of th experiment put these lines in an inline object: ' Stop eye tracking recording strData = "ET_STP" & Chr(10) & Chr(13) Serial.WriteString strData ' save eyetracking data in a file with a subject, session, and scan run-dependent filename: dim filename as string fileName = str(c.GetAttrib("Subject")) & "_" & str(c.GetAttrib("Session")) & ".idf" strData = "ET_SAV C:\\" & fileName & Chr(10) & Chr(13) Serial.WriteString strData Obviously, the filename can be changed to whatever is best for you. Note that iView X cannot save to a directory that doesn't exist, so make sure to either create the correct directory, or write to root. |
Const strENDL as String = Chr$(13) & Chr$(10) ' Clear eye tracker recording buffer Dim strData as String ' Start the calibration Const NumPoints as Integer = 13 Const ScreenWidth as integer = 1280 Const ScreenHeight as integer = 1024 Const CalWidth as integer = 640 Const CalHeight as integer = 512 ' Wait for valid = 0 is no; 1 is yes strData = "ET_CPA " & "0 " & "1" & strENDL Serial.WriteString strData ' Randomised point order = 0 is no; 1 is yes strData = "ET_CPA " & "1 " & "1" & strENDL Serial.WriteString strData ' Accept points automatically = 0 is no; 1 is yes strData = "ET_CPA " & "2 " & "1" & strENDL Serial.WriteString strData ' Check level of fixation = from 0 to 3 (how stringent it is with "wait for valid") strData = "ET_LEV " & "2" & strENDL Serial.WriteString strData ' Set calibration area (i.e. screen resolution) strData = "ET_CSZ " & str(ScreenWidth) & " " & str(ScreenHeight) & strENDL Serial.WriteString strData '' Default points in eye tracker are 13. We can tweak dim standardPoints(2, 13) as integer dim shiftedPoints(2, 13) as integer standardPoints(1,1) = 640 standardPoints(2,1) = 512 standardPoints(1,2) = 64 standardPoints(2,2) = 51 standardPoints(1,3) = 1216 standardPoints(2,3) = 51 standardPoints(1,4) = 64 standardPoints(2,4) = 973 standardPoints(1,5) = 1216 standardPoints(2,5) = 973 standardPoints(1,6) = 64 standardPoints(2,6) = 512 standardPoints(1,7) = 640 standardPoints(2,7) = 51 standardPoints(1,8) = 1216 standardPoints(2,8) = 512 standardPoints(1,9) = 640 standardPoints(2,9) = 973 standardPoints(1,10) = 352 standardPoints(2,10) = 282 standardPoints(1,11) = 928 standardPoints(2,11) = 282 standardPoints(1,12) = 352 standardPoints(2,12) = 743 standardPoints(1,13) = 928 standardPoints(2,13) = 743 'Scale up/down to match calibration area Dim b as integer For b = 1 To 13 shiftedPoints(1,b) = standardPoints(1,b) / screenWidth * CalWidth + (screenWidth - CalWidth)/2 shiftedPoints(2,b) = standardPoints(2,b) / screenHeight * CalHeight + (screenHeight - CalHeight)/2 strData = "ET_PNT " & str(b) & " " & str(shiftedPoints(1,b)) & " " & str(shiftedPoints(2,b)) & strENDL Serial.WriteString strData Next strData = "ET_CAL " & NumPoints & strENDL Serial.WriteString strData ' Get the current canvas, set to gray and clear it Dim Cvs as Canvas Set Cvs = Display.Canvas Cvs.FillColor = CColor("gray") ' Yes, 'gray' Cvs.Clear Cvs.PenWidth = 8 Cvs.PenColor = CColor("0,0,0") Keyboard.History.RemoveAll ' Process iView X commands Dim points(NumPoints) as String ' Array for the calibration points Dim bReady as Boolean bReady = False Dim strRead as String Dim strBuf as String Dim strComLine as String Dim strCom as String Dim strPnt as String Dim nRead as Long Dim bWait as Boolean bWait = false Dim bPointOnShow as Boolean bPointOnShow = false Dim nPos as Long Dim nLimit as Integer nLimit = 0 While Not bReady nLimit = nLimit + 1 if nLimit > 500 then MsgBox("Communication failure, time-out after 500 attempts") Stop end if ' Check the keyboard for presses on space, to force the current ' point to be accepted. This might be needed, sometimes if bPointOnShow and KeyBoard.History.Count > 0 then Dim nIndex As Long Dim theResponseData As ResponseData For nIndex = 1 To Keyboard.History.Count ' Retrieve a single ResponseData object from the ' collection of ResponseData objects stored in the ' InputHistoryManager Set theResponseData = Keyboard.History(nIndex) If Not theResponseData Is Nothing Then If theResponseData.RESP = "{SPACE}" Then strData = "ET_ACC" & strENDL Serial.WriteString strData End If End If Next Keyboard.History.RemoveAll end if nRead = Serial.ReadString(strRead) if nRead = 0 and bWait then ' Nothing read from port and nothing in buffer to process Sleep(50) else strBuf = strBuf & strRead ' Add newly read input to buffer nPos = InStr(strBuf, strENDL) if nPos = 0 then bWait = true else bWait = false strComLine = Left(strBuf, nPos - 1) ' Extract command and arguments strBuf = Mid(strBuf, nPos + 2) ' Remove from input buffer Debug.print strComLine strCom = Item$(strComLine, 1, 1, " ") ' Extract command itself 'if strCom = "ET_CSZ" then ' Screen size verification 'if CInt(Item$(strComLine, 2, 2, " \t")) <> Display.xres then 'MsgBox("X Resolution error, iView X assumes:\n" & strComLine) 'Stop 'e'nd if 'if CInt(Item$(strComLine, 3, 3, " \t")) <> Display.yres then 'MsgBox("Y Resolution error, iView X assumes:\n" & strComLine) 'Stop 'end if if strCom = "ET_PNT" then ' Calibration point definition points(CInt(Item$(strComLine, 2, 2, " \t"))) = Item$(strComLine, 3, 4, " \t") elseif strCom = "ET_CHG" then ' Change calibration point bPointOnShow = true nLimit = 0 ' Create some extra time strPnt = points(CInt(Item$(strComLine, 2, 2, " \t"))) Cvs.Clear Cvs.Circle Cint(Item$(strPnt, 1, 1, " \t")), Cint(Item$(strPnt, 2, 2, " \t")), 8 elseif strCom = "ET_FIN" then ' Calibration finished bReady = True elseif strCom <> "ET_CPA" and strCom <> "ET_ACC" and strCom <> "ET_BRK" and strCom <> "ET_CLR" and strCom <> "ET_REC" and strCom <> "ET_CAL" and strCom <> "ET_LEV" and strCom <> "ET_CSZ" then MsgBox("Error in communications with iView X, received:\n" & strComLine) Stop end if end if end if Wend Cvs.Clear Set Cvs = Nothing }}} == Validation == You can also validate (check) your calibration using the following script: {{{ '' Variables already declared in Calibration AVG & JC ' Start validation strData = "ET_VLS" & strENDL Serial.WriteString strData ' Set randomise point order to ON 'strData = "ET_CPA 1 1" & strENDL 'Serial.WriteString strData ' Turn Auto accept ON 'strData = "ET_CPA 2 1" & strENDL 'Serial.WriteString strData ' Get the current canvas, set to gray and clear it Set Cvs = Display.Canvas Cvs.FillColor = CColor("gray") ' Yes, 'gray' Cvs.Clear Cvs.PenWidth = 8 Cvs.PenColor = CColor("0,0,0") Keyboard.History.RemoveAll ' Process iView X commands bReady = False bWait = false bPointOnShow = false nLimit = 0 While Not bReady nLimit = nLimit + 1 if nLimit > 500 then MsgBox("Communication failure, time-out after 500 attempts") Stop end if ' Check the keyboard for presses on space, to force the current ' point to be accepted. This might be needed, sometimes if bPointOnShow and KeyBoard.History.Count > 0 then For nIndex = 1 To Keyboard.History.Count ' Retrieve a single ResponseData object from the ' collection of ResponseData objects stored in the ' InputHistoryManager Set theResponseData = Keyboard.History(nIndex) If Not theResponseData Is Nothing Then If theResponseData.RESP = "{SPACE}" Then strData = "ET_ACC" & strENDL Serial.WriteString strData End If End If Next Keyboard.History.RemoveAll end if nRead = Serial.ReadString(strRead) if nRead = 0 and bWait then ' Nothing read from port and nothing in buffer to process Sleep(50) else strBuf = strBuf & strRead ' Add newly read input to buffer nPos = InStr(strBuf, strENDL) if nPos = 0 then bWait = true else bWait = false strComLine = Left(strBuf, nPos - 1) ' Extract command and arguments strBuf = Mid(strBuf, nPos + 2) ' Remove from input buffer Debug.print strComLine strCom = Item$(strComLine, 1, 1, " ") ' Extract command itself if strCom = "ET_CSZ" then ' Screen size verification if CInt(Item$(strComLine, 2, 2, " \t")) <> Display.xres then MsgBox("X Resolution error, iView X assumes:\n" & strComLine) Stop end if if CInt(Item$(strComLine, 3, 3, " \t")) <> Display.yres then MsgBox("Y Resolution error, iView X assumes:\n" & strComLine) Stop end if elseif strCom = "ET_PNT" then ' Calibration point definition points(CInt(Item$(strComLine, 2, 2, " \t"))) = Item$(strComLine, 3, 4, " \t") elseif strCom = "ET_CHG" then ' Change calibration point bPointOnShow = true nLimit = 0 ' Create some extra time strPnt = points(CInt(Item$(strComLine, 2, 2, " \t"))) Cvs.Clear Cvs.Circle Cint(Item$(strPnt, 1, 1, " \t")), Cint(Item$(strPnt, 2, 2, " \t")), 8 elseif strCom = "ET_FIN" then ' Calibration finished bReady = True elseif strCom <> "ET_CPA" and strCom <> "ET_ACC" and strCom <> "ET_BRK" and strCom <> "ET_CLR" and strCom <> "ET_REC" and strCom <> "ET_CAL" then MsgBox("Error in communications with iView X, received:\n" & strComLine) Stop end if end if end if Wend Cvs.Clear Set Cvs = Nothing }}} == Drift correction == And you can do drift correction using this script: {{{ ' Start drift correction strData = "ET_RCL" & strENDL Serial.WriteString strData ' Get the current canvas, set to gray and clear it Set Cvs = Display.Canvas Cvs.FillColor = CColor("gray") ' Yes, 'gray' Cvs.Clear Cvs.PenWidth = 8 Cvs.PenColor = CColor("0,0,0") ' Process iView X commands bReady = False bWait = false nLimit = 0 ' Put calibration point bPointOnShow = true 'strPnt = points(CInt(Item$(strComLine, 2, 2, " \t"))) strPnt = points(CInt(Item$("ET_CHG 1", 2, 2, " \t"))) Cvs.Clear Cvs.Circle Cint(Item$(strPnt, 1, 1, " \t")), Cint(Item$(strPnt, 2, 2, " \t")), 8 While Not bReady nLimit = nLimit + 1 if nLimit > 500 then MsgBox("Communication failure, time-out after 500 attempts") Stop end if ' Check the keyboard for presses on space, to force the current ' point to be accepted. This might be needed, sometimes if bPointOnShow and KeyBoard.History.Count > 0 then For nIndex = 1 To Keyboard.History.Count ' Retrieve a single ResponseData object from the ' collection of ResponseData objects stored in the ' InputHistoryManager Set theResponseData = Keyboard.History(nIndex) If Not theResponseData Is Nothing Then If theResponseData.RESP = "{SPACE}" Then strData = "ET_ACC" & strENDL Serial.WriteString strData End If End If Next Keyboard.History.RemoveAll end if nRead = Serial.ReadString(strRead) if nRead = 0 and bWait then ' Nothing read from port and nothing in buffer to process Sleep(50) else strBuf = strBuf & strRead ' Add newly read input to buffer nPos = InStr(strBuf, strENDL) if nPos = 0 then bWait = true else bWait = false strComLine = Left(strBuf, nPos - 1) ' Extract command and arguments strBuf = Mid(strBuf, nPos + 2) ' Remove from input buffer Debug.print strComLine strCom = Item$(strComLine, 1, 1, " ") ' Extract command itself if strCom = "ET_FIN" then ' Calibration finished bReady = True end if end if end if Wend }}} The main advantage of letting E-Prime take care of the calibration is that you don't have to use !WinCal any more. Combine these E-Prime scripts to start the recording, do the calibration, validation, drift correction, mark the trials, stop the recording and save the results to disk. |
SMI now has a toolkit which makes using their eye trackers with E-Prime much easier, so the following is outdated
Ask Maarten van Casteren for details if you need to know more
Running an Eye tracking experiment with E-Prime
When using E-Prime with a SMI eye tracker, E-Prime should communicate with iView X, the eye tracking software, to start and stop the recording, indicate the start of each trial, specify the stimulus used and finally save the data. The way SMI prefer to do this is by using an ethernet connection and the UDP protocol, but E-Prime cannot handle this. For this reason SMI have developed a toolkit that can take care of the communication with the eye tracker. The toolkit consists of two parts: first a dll file that contains the actual executable code, and second an E-Prime package file that makes sure the functionality in the dll is available within an E-Prime script in a user friendly way.
To be able to use an eye tracker with this toolkit you need to do the following:
1 - Add the package to your E-Prime script. In the 'structure' window double-click on 'Experiment' and then select the 'Packages' tab. Press 'Add' and select the 'iView_X_SDK_CBU' package. If this is not available you'll have to install it: the file 'iViewXAPI_CBU.epk2' should be in 'Program Files\PST\E-Prime 2.0\Program\Packages'. If the Packages folder doesn't exist, it should be created.
2 - At the start of your experiment, add these lines, in an inline object:
' Connect to the Eye Tracker over the ethernet. The IP adresses are the
' ones we usually use, so this should work at the CBU without modification
if not iView_X_SDK_CBU_Connect("192.168.1.1", 4444, "192.168.1.2", 5555) then
Mouse.ShowCursor True
MsgBox "Connect failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end if3 - You need to calibrate the eye tracker before you can use it. Put this code in an inline object to do so.
' Use 13 targets for calibration
iView_X_SDK_CBU_SetCalMethod 13
if not iView_X_SDK_CBU_Calibrate then
Mouse.ShowCursor True
MsgBox "Calibration failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end if4 - You then should check the calibration to see if it was sufficiently precise. This is called validation. You should repeat calibration and validation until you have the required precision.
' Do the validation
if not iView_X_SDK_CBU_Validate( DeviationXL, DeviationYL, DeviationXR, DeviationYR) Then
Mouse.ShowCursor True
MsgBox "Validation Failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end if
' Present the results
Mouse.ShowCursor true
MsgBox "MeanDeviation: "& DeviationXL &" " & DeviationYL &" " & DeviationXR &" " & DeviationYR
Mouse.ShowCursor false5 - Just before you start presenting your stimuli you should start the eye tracking recording
' Start a recording on the Eye Tracking computer
if not iView_X_SDK_CBU_StartRecording then
Mouse.ShowCursor True
MsgBox "StartRecording failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end if6 - At the start of each trial, or just before your main stimulus is being presented, add a 'message line', preferably with your stimulus name as an argument (NB if you are presenting images, sending the name of the image file you are presenting will greatly facilitate analysis using the BeGaze software, as the associations between the trial and image will then be made automatically by the software. For more info, see BeGaze):
' Send a message to be included in the Eye Tracking recording.
' This will normally be a trial number, or a condition code or
' something like that.
if not iView_X_SDK_CBU_SendMessage("msg") then
Mouse.ShowCursor True
MsgBox "SendMessage 5 failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
ListA.Terminate
end if7 - Finally, at the end of th experiment put these lines in an inline object:
' First stop the current recording
if not iView_X_SDK_CBU_StopRecording then
Mouse.ShowCursor True
MsgBox "StopRecording failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end if
' Then save the data. Get the filename that E-Prime uses for its output
dim fullfilename as string
fullfilename = c.datafile.filename
' Split the filename in its parts
dim fileroot as string
fileroot = FileParse$(fullfilename, 4)
' Eye tracking data will now be saved under the same name as the E-Prime data, in the iViewX folder
' If you want it to go to your own folder then add this to the filerootname.
if not iView_X_SDK_CBU_SaveData(fileroot, "", "", 1) then
Mouse.ShowCursor True
MsgBox "SaveData failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end if
' And finally close the connection with the eye tracker.
if not iView_X_SDK_CBU_Disconnect then
Mouse.ShowCursor True
MsgBox "Disconnect failed: " & iView_X_SDK_CBU_GetErrorString
iView_X_SDK_CBU_Abort
End
end ifObviously, the filename can be changed to whatever is best for you. Note that iView X cannot save to a directory that doesn't exist, so make sure to either create the correct directory, or write to root.
Running the script
When running the script you should go through these steps:
1 - Switch on the eye tracking hardware and install your subject.
2 - Start the iView X program on the eye tracking computer.
3 - Make sure the eye picture looks good and the eye gaze is correctly tracked. Verify this by asking the subject to look at all 4 corners of the screen.
4 - Run your E-Prime script.
Calibration from within E-Prime
The calibration can also be performed by E-Prime. To be able to do this you need to incorporate a bit of inline code in your E-Prime script. This code will communicate with the eye tracker software and put targets on the screen in response to requests from iView X.
All of the calibration code is in a single inline object, and the only other thing that needs to be done is to define a serial port device in the 'Devices' tab of the 'Experimental Object Properties' dialogue. Make sure to give this the name 'Serial', which is actually the default name that E-Prime will suggest.
The first bit of inline code should be inserted in the E-Prime script at the point where the calibration is to be performed. To start the recording, mark the trials, and to close and save the recording the same bits of code should be inserted as used in the previous section.
The calibration uses the settings specified in iView X, which means that you will have to specify 'auto accept' or other settings there. The only thing that the script sets is the number of calibration points used. This is set to 13, but can easily be changed to another value.
One warning: this code hasn't been tested much yet, so might not always work as expected. Be careful and please report any problems to Maarten van Casteren.
' Flush serial connection
Serial.FlushOutBuffer
Const strENDL as String = Chr$(13) & Chr$(10)
' Clear eye tracker recording buffer
Dim strData as String
' Start the calibration
Const NumPoints as Integer = 13
Const ScreenWidth as integer = 1280
Const ScreenHeight as integer = 1024
Const CalWidth as integer = 640
Const CalHeight as integer = 512
' Wait for valid = 0 is no; 1 is yes
strData = "ET_CPA " & "0 " & "1" & strENDL
Serial.WriteString strData
' Randomised point order = 0 is no; 1 is yes
strData = "ET_CPA " & "1 " & "1" & strENDL
Serial.WriteString strData
' Accept points automatically = 0 is no; 1 is yes
strData = "ET_CPA " & "2 " & "1" & strENDL
Serial.WriteString strData
' Check level of fixation = from 0 to 3 (how stringent it is with "wait for valid")
strData = "ET_LEV " & "2" & strENDL
Serial.WriteString strData
' Set calibration area (i.e. screen resolution)
strData = "ET_CSZ " & str(ScreenWidth) & " " & str(ScreenHeight) & strENDL
Serial.WriteString strData
'' Default points in eye tracker are 13. We can tweak
dim standardPoints(2, 13) as integer
dim shiftedPoints(2, 13) as integer
standardPoints(1,1) = 640
standardPoints(2,1) = 512
standardPoints(1,2) = 64
standardPoints(2,2) = 51
standardPoints(1,3) = 1216
standardPoints(2,3) = 51
standardPoints(1,4) = 64
standardPoints(2,4) = 973
standardPoints(1,5) = 1216
standardPoints(2,5) = 973
standardPoints(1,6) = 64
standardPoints(2,6) = 512
standardPoints(1,7) = 640
standardPoints(2,7) = 51
standardPoints(1,8) = 1216
standardPoints(2,8) = 512
standardPoints(1,9) = 640
standardPoints(2,9) = 973
standardPoints(1,10) = 352
standardPoints(2,10) = 282
standardPoints(1,11) = 928
standardPoints(2,11) = 282
standardPoints(1,12) = 352
standardPoints(2,12) = 743
standardPoints(1,13) = 928
standardPoints(2,13) = 743
'Scale up/down to match calibration area
Dim b as integer
For b = 1 To 13
shiftedPoints(1,b) = standardPoints(1,b) / screenWidth * CalWidth + (screenWidth - CalWidth)/2
shiftedPoints(2,b) = standardPoints(2,b) / screenHeight * CalHeight + (screenHeight - CalHeight)/2
strData = "ET_PNT " & str(b) & " " & str(shiftedPoints(1,b)) & " " & str(shiftedPoints(2,b)) & strENDL
Serial.WriteString strData
Next
strData = "ET_CAL " & NumPoints & strENDL
Serial.WriteString strData
' Get the current canvas, set to gray and clear it
Dim Cvs as Canvas
Set Cvs = Display.Canvas
Cvs.FillColor = CColor("gray") ' Yes, 'gray'
Cvs.Clear
Cvs.PenWidth = 8
Cvs.PenColor = CColor("0,0,0")
Keyboard.History.RemoveAll
' Process iView X commands
Dim points(NumPoints) as String ' Array for the calibration points
Dim bReady as Boolean
bReady = False
Dim strRead as String
Dim strBuf as String
Dim strComLine as String
Dim strCom as String
Dim strPnt as String
Dim nRead as Long
Dim bWait as Boolean
bWait = false
Dim bPointOnShow as Boolean
bPointOnShow = false
Dim nPos as Long
Dim nLimit as Integer
nLimit = 0
While Not bReady
nLimit = nLimit + 1
if nLimit > 500 then
MsgBox("Communication failure, time-out after 500 attempts")
Stop
end if
' Check the keyboard for presses on space, to force the current
' point to be accepted. This might be needed, sometimes
if bPointOnShow and KeyBoard.History.Count > 0 then
Dim nIndex As Long
Dim theResponseData As ResponseData
For nIndex = 1 To Keyboard.History.Count
' Retrieve a single ResponseData object from the
' collection of ResponseData objects stored in the
' InputHistoryManager
Set theResponseData = Keyboard.History(nIndex)
If Not theResponseData Is Nothing Then
If theResponseData.RESP = "{SPACE}" Then
strData = "ET_ACC" & strENDL
Serial.WriteString strData
End If
End If
Next
Keyboard.History.RemoveAll
end if
nRead = Serial.ReadString(strRead)
if nRead = 0 and bWait then
' Nothing read from port and nothing in buffer to process
Sleep(50)
else
strBuf = strBuf & strRead ' Add newly read input to buffer
nPos = InStr(strBuf, strENDL)
if nPos = 0 then
bWait = true
else
bWait = false
strComLine = Left(strBuf, nPos - 1) ' Extract command and arguments
strBuf = Mid(strBuf, nPos + 2) ' Remove from input buffer
Debug.print strComLine
strCom = Item$(strComLine, 1, 1, " ") ' Extract command itself
'if strCom = "ET_CSZ" then
' Screen size verification
'if CInt(Item$(strComLine, 2, 2, " \t")) <> Display.xres then
'MsgBox("X Resolution error, iView X assumes:\n" & strComLine)
'Stop
'e'nd if
'if CInt(Item$(strComLine, 3, 3, " \t")) <> Display.yres then
'MsgBox("Y Resolution error, iView X assumes:\n" & strComLine)
'Stop
'end if
if strCom = "ET_PNT" then
' Calibration point definition
points(CInt(Item$(strComLine, 2, 2, " \t"))) = Item$(strComLine, 3, 4, " \t")
elseif strCom = "ET_CHG" then
' Change calibration point
bPointOnShow = true
nLimit = 0 ' Create some extra time
strPnt = points(CInt(Item$(strComLine, 2, 2, " \t")))
Cvs.Clear
Cvs.Circle Cint(Item$(strPnt, 1, 1, " \t")), Cint(Item$(strPnt, 2, 2, " \t")), 8
elseif strCom = "ET_FIN" then
' Calibration finished
bReady = True
elseif strCom <> "ET_CPA" and strCom <> "ET_ACC" and strCom <> "ET_BRK" and strCom <> "ET_CLR" and strCom <> "ET_REC" and strCom <> "ET_CAL" and strCom <> "ET_LEV" and strCom <> "ET_CSZ" then
MsgBox("Error in communications with iView X, received:\n" & strComLine)
Stop
end if
end if
end if
Wend
Cvs.Clear
Set Cvs = Nothing
Validation
You can also validate (check) your calibration using the following script:
'' Variables already declared in Calibration AVG & JC
' Start validation
strData = "ET_VLS" & strENDL
Serial.WriteString strData
' Set randomise point order to ON
'strData = "ET_CPA 1 1" & strENDL
'Serial.WriteString strData
' Turn Auto accept ON
'strData = "ET_CPA 2 1" & strENDL
'Serial.WriteString strData
' Get the current canvas, set to gray and clear it
Set Cvs = Display.Canvas
Cvs.FillColor = CColor("gray") ' Yes, 'gray'
Cvs.Clear
Cvs.PenWidth = 8
Cvs.PenColor = CColor("0,0,0")
Keyboard.History.RemoveAll
' Process iView X commands
bReady = False
bWait = false
bPointOnShow = false
nLimit = 0
While Not bReady
nLimit = nLimit + 1
if nLimit > 500 then
MsgBox("Communication failure, time-out after 500 attempts")
Stop
end if
' Check the keyboard for presses on space, to force the current
' point to be accepted. This might be needed, sometimes
if bPointOnShow and KeyBoard.History.Count > 0 then
For nIndex = 1 To Keyboard.History.Count
' Retrieve a single ResponseData object from the
' collection of ResponseData objects stored in the
' InputHistoryManager
Set theResponseData = Keyboard.History(nIndex)
If Not theResponseData Is Nothing Then
If theResponseData.RESP = "{SPACE}" Then
strData = "ET_ACC" & strENDL
Serial.WriteString strData
End If
End If
Next
Keyboard.History.RemoveAll
end if
nRead = Serial.ReadString(strRead)
if nRead = 0 and bWait then
' Nothing read from port and nothing in buffer to process
Sleep(50)
else
strBuf = strBuf & strRead ' Add newly read input to buffer
nPos = InStr(strBuf, strENDL)
if nPos = 0 then
bWait = true
else
bWait = false
strComLine = Left(strBuf, nPos - 1) ' Extract command and arguments
strBuf = Mid(strBuf, nPos + 2) ' Remove from input buffer
Debug.print strComLine
strCom = Item$(strComLine, 1, 1, " ") ' Extract command itself
if strCom = "ET_CSZ" then
' Screen size verification
if CInt(Item$(strComLine, 2, 2, " \t")) <> Display.xres then
MsgBox("X Resolution error, iView X assumes:\n" & strComLine)
Stop
end if
if CInt(Item$(strComLine, 3, 3, " \t")) <> Display.yres then
MsgBox("Y Resolution error, iView X assumes:\n" & strComLine)
Stop
end if
elseif strCom = "ET_PNT" then
' Calibration point definition
points(CInt(Item$(strComLine, 2, 2, " \t"))) = Item$(strComLine, 3, 4, " \t")
elseif strCom = "ET_CHG" then
' Change calibration point
bPointOnShow = true
nLimit = 0 ' Create some extra time
strPnt = points(CInt(Item$(strComLine, 2, 2, " \t")))
Cvs.Clear
Cvs.Circle Cint(Item$(strPnt, 1, 1, " \t")), Cint(Item$(strPnt, 2, 2, " \t")), 8
elseif strCom = "ET_FIN" then
' Calibration finished
bReady = True
elseif strCom <> "ET_CPA" and strCom <> "ET_ACC" and strCom <> "ET_BRK" and strCom <> "ET_CLR" and strCom <> "ET_REC" and strCom <> "ET_CAL" then
MsgBox("Error in communications with iView X, received:\n" & strComLine)
Stop
end if
end if
end if
Wend
Cvs.Clear
Set Cvs = Nothing
Drift correction
And you can do drift correction using this script:
' Start drift correction
strData = "ET_RCL" & strENDL
Serial.WriteString strData
' Get the current canvas, set to gray and clear it
Set Cvs = Display.Canvas
Cvs.FillColor = CColor("gray") ' Yes, 'gray'
Cvs.Clear
Cvs.PenWidth = 8
Cvs.PenColor = CColor("0,0,0")
' Process iView X commands
bReady = False
bWait = false
nLimit = 0
' Put calibration point
bPointOnShow = true
'strPnt = points(CInt(Item$(strComLine, 2, 2, " \t")))
strPnt = points(CInt(Item$("ET_CHG 1", 2, 2, " \t")))
Cvs.Clear
Cvs.Circle Cint(Item$(strPnt, 1, 1, " \t")), Cint(Item$(strPnt, 2, 2, " \t")), 8
While Not bReady
nLimit = nLimit + 1
if nLimit > 500 then
MsgBox("Communication failure, time-out after 500 attempts")
Stop
end if
' Check the keyboard for presses on space, to force the current
' point to be accepted. This might be needed, sometimes
if bPointOnShow and KeyBoard.History.Count > 0 then
For nIndex = 1 To Keyboard.History.Count
' Retrieve a single ResponseData object from the
' collection of ResponseData objects stored in the
' InputHistoryManager
Set theResponseData = Keyboard.History(nIndex)
If Not theResponseData Is Nothing Then
If theResponseData.RESP = "{SPACE}" Then
strData = "ET_ACC" & strENDL
Serial.WriteString strData
End If
End If
Next
Keyboard.History.RemoveAll
end if
nRead = Serial.ReadString(strRead)
if nRead = 0 and bWait then
' Nothing read from port and nothing in buffer to process
Sleep(50)
else
strBuf = strBuf & strRead ' Add newly read input to buffer
nPos = InStr(strBuf, strENDL)
if nPos = 0 then
bWait = true
else
bWait = false
strComLine = Left(strBuf, nPos - 1) ' Extract command and arguments
strBuf = Mid(strBuf, nPos + 2) ' Remove from input buffer
Debug.print strComLine
strCom = Item$(strComLine, 1, 1, " ") ' Extract command itself
if strCom = "ET_FIN" then
' Calibration finished
bReady = True
end if
end if
end if
WendThe main advantage of letting E-Prime take care of the calibration is that you don't have to use WinCal any more. Combine these E-Prime scripts to start the recording, do the calibration, validation, drift correction, mark the trials, stop the recording and save the results to disk.
