TRACKPixx Demo 4 – Recording and plotting eye position data from the TRACKPixx3

Note

This demo requires TRACKPixx Revision 18 or later. You can check for recent firmware updates at vpixx.com/whatsnew

Note

This demo assumes you have already calibrated the TRACKPixx3 for the session. You can calibrate using the PyPixx GUI, or run TPxTrackpixx3CalibrationTesting() in MATLAB. If the tracker is not calibrated, the eye positions returned by this demo will be NaN.

In this demo we display a series of squares. When the user presses “Enter”, the TRACKPixx3 records eye data for 4 seconds, and then plots the result. We trigger recording using the sequence Datapixx('SetupTPxSchedule'); , Datapixx('StartTPxSchedule'); , and when finished, Datapixx('StopTPxSchedule');. Each of these commands must be followed by a Datapixx('RegWrRd'); to push them to the device register and initiate/finish recording.

To read the buffer of recorded data from the TRACKPixx, we call status = Datapixx('GetTPxStatus');. New data is first isolated in toRead = status.newBufferFrames;, and then interpreted using Datapixx('ReadTPxData', toRead);.

TRACKPixx buffer data has the following format:

Timetag, Left Eye X, Left Eye Y, Left Pupil Diameter, Right Eye X, Right Eye Y, Right Pupil Diameter, Digital Input Values (24 bits), Left Blink Detection, Right Blink Detection, Digital Output Values (24 bits), Left Eye Fixation Flag, Right Eye Fixation Flag, Left Eye Saccade Flag, Right Eye Saccade Flag, Message code, Left Eye Raw X, Left Eye Raw Y, Right Eye Raw X, Right Eye Raw Y.

Finally, we generate three figures, which plot X and Y position over time for the left eye, the right eye, and both eyes. By default, we plot the calibrated eye positions. Raw position can be plotted instead by changing the column of the buffer data used in plot(). Data points where the X and Y positions equal 9000 are frames in which the eye position was lost (i.e., the participant blinked).

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
function TPxRawRecordAndPlot()
%
% This demo will start the required things to start the TPx schedule to record data
% and it will show points for 4 secs and record raw or calibrated data.
% After the four seconds, the data will be plotted.
%
%
% Dec 22, 2017  dml written

Screen('Preference', 'SkipSyncTests', 1);

%% Step 1 -- Open the screen and show the eye.
Datapixx('Open');
Datapixx('SetLedIntensity', 8); 
Datapixx('SetTPxAwake');
Datapixx('SetExpectedIrisSizeInPixels', 115)
Datapixx('RegWrRd');
image = Datapixx('GetEyeImage');
[windowPtr, windowRect]=PsychImaging('OpenWindow', 2, 0);
KbName('UnifyKeyNames');
t = Datapixx('GetTime');
t2 = Datapixx('GetTime');
Screen('TextSize', windowPtr, 24);
i = 0;
while (1)

    
if ((t2 - t) > 1/60) 
    Datapixx('RegWrRd');
    image = Datapixx('GetEyeImage');
    textureIndex=Screen('MakeTexture', windowPtr, image');
    Screen('DrawTexture', windowPtr, textureIndex);
    DrawFormattedText(windowPtr, 'Press Enter once the Eye are Focused', 'center', 700, 255); 
    Screen('Flip', windowPtr);
    t = t2;
else
    Datapixx('RegWrRd');
    t2 = Datapixx('GetTime');
end
    % Keypress goes to next step of demo
    [pressed dummy keycode] = KbCheck;
    if pressed
        if keycode(KbName('escape'))
            Screen('CloseAll')
            Datapixx('Close');
            return;
        else
            break;
        end
    end
end

WaitSecs(1);
%% Step 2 -- Show screen squares
cx = 1920/2;
cy = 1080/2;
dx = 400;
dy = 250;
xy = [cx+dx cy+dy; cx-dx cy+dy; cx-dx cy-dy; cx+dx cy-dy];
xy = [xy;xy]';
size = [30; 30; 30; 30; 10; 10; 10; 10]';
color = [255 255 255; 255 255 255; 255 255 255; 255 255 255; 0 0 0; 0 0 0; 0 0 0; 0 0 0]';
i = 0;
Screen('BlendFunction', windowPtr, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA');
recording = 0;
start_time = 0;
while (1)

    
if ((t2 - t) > 1) 
    Datapixx('RegWrRd');
    i = i + 1;
    %Screen('DrawDots', windowPtr, xy, size, color,[], 0);
    Screen('DrawDots', windowPtr, [xy(:,mod(i,4)+1) xy(:,mod(i,4)+1)], [30;10]', [255 255 255; 0 0 0]', [], 0);
    if ~recording
        DrawFormattedText(windowPtr, 'Press enter when ready to record', 'center', 80, 255); 
    end
    Screen('Flip', windowPtr);
    t = t2;
else
    Datapixx('RegWrRd');
    t2 = Datapixx('GetTime');
end
    % Keypress goes to next step of demo
    [pressed dummy keycode] = KbCheck;
    if pressed
        if keycode(KbName('escape'))
            Screen('CloseAll')
            Datapixx('Close');
            return;
        else
            recording = 1;
            Datapixx('SetupTPxSchedule');
            Datapixx('RegWrRd');
            Datapixx('StartTPxSchedule');
            Datapixx('RegWrRd');
            start_time = Datapixx('GetTime');
        end
    end
    
    if (recording == 1)
        Datapixx('RegWrRd');
        curr_time = Datapixx('GetTime');
        if ((curr_time - start_time) > 5)
            Datapixx('StopTPxSchedule');
            Datapixx('RegWrRd');
            finish_time = Datapixx('GetTime');
            break;
        end
    end
end

% Screen('DrawDots', windowPtr, xy, size, color,[], 1);
% Screen('Flip', windowPtr);
    
WaitSecs(1.0);
%% Step 3 -- Recording

% Datapixx('SetupTPxSchedule');
% Datapixx('RegWrRd');
% 

DrawFormattedText(windowPtr, 'Analyzing Data...Please wait', 'center', 80, 255); 
Screen('Flip', windowPtr);


% Datapixx('GetTPxStatus')
% Datapixx('RegWrRd');
% 
% Datapixx('StartTPxSchedule');
% Datapixx('RegWrRd');
% start_time = Datapixx('GetTime');
% % fprintf('Recording started at %f', l);
% % Datapixx('GetTPxStatus')
% WaitSecs(4.0);
% % 
% Datapixx('StopTPxSchedule');
% Datapixx('RegWrRd');
% finish_time = Datapixx('GetTime');
fprintf('Recording lasted %f seconds', finish_time-start_time);
WaitSecs(2.0);
Datapixx('RegWrRd');
status = Datapixx('GetTPxStatus');
toRead = status.newBufferFrames;


%% Step 4 -- Get and Plot Data
[bufferData, underflow, overflow] = Datapixx('ReadTPxData', toRead);

figure;
hold on;
grid on;
title('Left Eye (Red: X, Blue: Y)');
xlabel('Timetags (seconds)');
ylabel('Gaze information (pixels)');
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,17), 'r')
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,18), 'b')

figure;
hold on;
grid on;
title('Right Eye (Red: X, Blue: Y)');
xlabel('Timetags (seconds)');
ylabel('Gaze information (pixels)');
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,19), 'r')
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,20), 'b')

figure;
hold on;
grid on;
title('Both Eyes (Red: Left X, Blue:  Left Y, Black: Right X, Magenta: Right Y)');
xlabel('Timetags (seconds)');
ylabel('Gaze information (pixels)');
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,17), 'r')
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,18), 'b')
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,19), 'c')
plot(bufferData(:,1)-bufferData(1,1), bufferData(:,20), 'm')


%% Close all!
Screen('CloseAll');

Datapixx('Close');

end