.. _simplegazetracker-commands:

How to control SimpleGazeTracker from your application
============================================================================

SimpleGazeTracker can be controlled by sending commands through TCP/IP connection.
For example, SimpleGazeTracker opens a new data file named 'exp01_participant01.csv' when receiving following text (\\0 indicates null charactor).::

    openDataFile\0exp01_participant01.csv\01\0

In this example, 'openDataFile' is a command. 'exp01_participant01.csv' and '1' are parameters of the command.
Command and each parameter must be end with \\0.

Some commands have return value. \\0 is reserved for representing the end of the data.
For example, 'getCurMenu' command returns current menu item as a string.::

    MinPoints(72)\0

Here 'MinPoints(72)' is the returned value and \\0 is the terminator.

.. note::
    '#' was used to represent the end of the return data in version 0.5.3 or former.
    Exceptionally, 'getImageData' command used 0xFF as the terminator instead of '#'.

SimpleGazeTracker is originally designed to work in conjunction with GazeParser.TrackingTools.  However, SimpleGazeTracker can be controlled by other application.
Following tables show SimpleGazeTracker commands.
**Please note that SimpleGazeTracker is under development and therefore commands may be added, modified or deleted.**

Key emuration
------------------------------------------------

==================== ========================================================================
Commands             Description
==================== ========================================================================
key_Q                Emulating a keypress of 'Q' on the Recorder PC.
                     This terminates SimpleGazeTracker.
                     
                     * **Parameter:** none
                     * **Return:** none
key_UP               Emulating a keypress of up arrow key on the Recorder PC.
                     This changes current menu item.
                     
                     * **Parameter:** none
                     * **Return:** none
key_DOWN             Emulating a keypress of down arrow key on the Recorder PC.
                     This changes current menu item.
                     
                     * **Parameter:** none
                     * **Return:** none
key_LEFT             Emulating a keypress of left arrow key on the Recorder PC.
                     This decreases value of the parameter.
                     
                     * **Parameter:** none
                     * **Return:** none
key_RIGHT            Emulating a keypress of right arrow key on the Recorder PC.
                     This increases value of the parameter.
                     
                     * **Parameter:** none
                     * **Return:** none
==================== ========================================================================



Managing data file
------------------------------------------------

==================== ========================================================================
Commands             Description
==================== ========================================================================
openDataFile         Open data file on the Recorder PC.  If data file is
                     already opened, the data file is closed and a new data 
                     file is opended.
                     
                     * **Parameter:** name of data file, 
                       overwrite mode (0=rename, 1=overwrite)
                     * **Return:** none
insertSettings       Insert GazeParser parameters to the data file.
                     
                     * **Parameter:** a string to be output to the data file. Lines must be
                       separated by '/' and the first charactor must be '#'.
                     * **Return:** none
closeDataFile        Close data file.
                     
                     * **Parameter:** none
                     * **Return:** none
==================== ========================================================================


Calibration and validation
------------------------------------------------

======================= ========================================================================
Commands                Description
======================= ========================================================================
getCurrMenu             Get name of current menu item.
                        
                        * **Parameter:** none
                        * **Return:** a string representing current menu item.
getImageData            Request current camera image.
                        
                        * **Parameter:** none
                        * **Return:** binary data of camera image. Camera image is
                          8bit-monochrome. A value of 0 is reserved for representing the end
                          of the data.  For example, if size of the camera image is 320x240,
                          returned data is 320x240+1 = 76801 bytes. The last byte is 0x00 and 
                          no other byte is 0x00.
startCal                Start calibration mode.
                        
                        * **Parameter:** a string of comma-separated values which represents
                          calibration area and initialization mode.
                          If calibration area is (x1,y1,x2,y2) and initialize all calibration 
                          data, parameter is 'x1,y1,x2,y2,1'.  If you want to append calibration
                          data to the current data, paramter is 'x1,y1,x2,y2,0'.
                          **modified in 0.10.0.**
                          
                        * **Return:** none.
getCalSample            Record the center of the pupil and the Purkinje image with calibration 
                        target position. These values will be used for calculating calibration
                        parameters when **endCal** command is received. *Modified in 0.6.0*
                        
                        * **Parameter:** position of the target in the screen coordinate and 
                          number of samples collected at each position. If the position is 
                          (x,y) and number of samples is n, parameter is 'x,y,n'.
                        * **Return:** none
endCal                  Stop calibraion mode.
                        
                        * **Parameter:** none
                        * **Return:** none
startVal                Start validation mode. 
                        
                        * **Parameter:** a string representing calibration target positions.
                          For example, if target positions are (x1,y1), (x2,y2) and (x3,y3),
                          parameter is 'x1,y1,x2,y2,x3,y3'.
                        * **Return:** none.
getValSample            Record the center of the pupil and the Purkinje image with validation
                        target position. *Modified in 0.6.0*
                        
                        * **Parameter:** position of the target in the screen coordinate and 
                          number of samples collected at each position. If the position is 
                          (x,y) and number of samples is n, parameter is 'x,y,n'.
                        * **Return:** none
endVal                  Stop validation mode.
                        
                        * **Parameter:** none
                        * **Return:** none
toggleCalResult         Toggle calibration result screen on the Recorder PC.
                        
                        * **Parameter:** 0:off / 1:on *New in 0.6.1*
                        * **Return:** none
getCalResults           Get a summary of calibration results.
                        
                        * **Parameter:** none
                        * **Return:** a string of comma-separated values.
                          See :func:`~GazeParser.TrackingTools.BaseController.getCalibrationResults`
                          for detail.
getCalResultsDetail     Get detailed calibration results.
                        
                        * **Parameter:** none
                        * **Return:** a string of comma-separated values. If recording mode is 
                          monocular, number of values are multiple of 4. Each 4 values represent
                          x and y values of target point and gaze position, respectively.
                          If recording mode is binocular, number of values are multiple of 6.
                          Each 4 values represe x and y values of target point, gaze position
                          of left eye and right eye, respectively.
saveCalValResultsDetail Save detailed (raw) calibration data.
                        
                        * **Parameter:** none *New in 0.8.0*
                        * **Return:** none
======================= ========================================================================


Measuring and Recording
------------------------------------------------

======================= ========================================================================
Commands                Description
======================= ========================================================================
startRecording          Start recording mode.
                        
                        * **Parameter:** message to be inserted.
                        * **Return:** none
stopRecording           Stop recording mode. 
                        
                        * **Parameter:** message to be inserted.
                        * **Return:** none
startMeasurement        Start measurement mode. The measurement mode is the same
                        as the recording mode except gaze position data is not 
                        output to the data file. This mode is used by 
                        :func:`~GaezeParser.TrackingTools.BaseController.getSpatialError`.
                        
                        * **Parameter:** none
                        * **Return:** none
stopMeasurement         Stop measurement mode.
                        
                        * **Parameter:** none
                        * **Return:** none
insertMessage           Insert a message with timestamp.
                        
                        * **Parameter:** message to be inserted.
                        * **Return:** none
getEyePosition          Get current eye position. If parameter is 1, the latest data 
                        is returned. If parameter is N (>=2), moving average of the latest 
                        N-samples is returned. *Modified in 0.6.4*
                        
                        * **Parameter:** number of samples *New in 0.6.4*
                        * **Return:** a string representing current eye position.
                          - **monocular:** 'x,y,p'
                          - **binocular:** 'lx,ly,lp,rx,ry,rp'
getWholeEyePositionList Get all gaze position data in the latest recording. *New in 0.6.4*

                        * **Parameter:** 0:without pupil data / 1:with pupil data
                        * **Return:** a string representing recorded data. (N=n of samples)
                          
                          - **parameter=0/monocular:** 'x1,y1,x2,y2,...,xN,yN'
                          - **parameter=1/monocular:** 'x1,y1,p1,x2,y2,p2,...,xN,yN,pN'
                          - **parameter=0/binocular:** 'lx1,ly1,rx1,ry1,lx2,ly2,rx2,ry2,
                            ...,lxN,lyN,rxN,ryN'
                          - **parameter=1/binocular:** 'lx1,ly1,rx1,ry1,lp1,rp1,
                            lx2,ly2,rx2,ry2,lp2,rp2,...,lxN,lyN,rxN,ryN,lpN,rpN'
getWholeMessageList     Get all messages in the latest recording. *New in 0.6.4*
                        
                        * **Parameter:** none.
                        * **Return:** Message list. Messages are separated by '\n'.
                          Each messages are comma-separated values. The first element is 
                          "#MESSAGE", the second element is timestamp and the third element 
                          is message text.
getEyePositionList      Get latest gaze position list. *New in 0.6.4*
                        
                        * **Parameter:** This command takes two parameters.
                          
                          - **Parameter1** 0:without pupil data / 1:with pupil data
                          - **Parameter2** Number of samples returned. If value is negative,
                            Data that have already transered are not transfered.
                        * **Return** 
                        * **Return:** a string representing recorded data. (N=n of samples)
                          
                          - **parameter=0/monocular:** 'x1,y1,x2,y2,...,xN,yN'
                          - **parameter=1/monocular:** 'x1,y1,p1,x2,y2,p2,...,xN,yN,pN'
                          - **parameter=0/binocular:** 'lx1,ly1,rx1,ry1,lx2,ly2,rx2,ry2,
                            ...,lxN,lyN,rxN,ryN'
                          - **parameter=1/binocular:** 'lx1,ly1,rx1,ry1,lp1,rp1,
                            lx2,ly2,rx2,ry2,lp2,rp2,...,lxN,lyN,rxN,ryN,lpN,rpN'
======================= ========================================================================


Other commands
------------------------------------------------

==================== ========================================================================
Commands             Description
==================== ========================================================================
saveCameraImage      Save current camera preview on the Recorder PC.
                     
                     * **Parameter:** file name.
                     * **Return:** none
allowRendering       Allow rendering camera preview on the Recorder PC.
                     This feature is used by
                     :func:`~GazeParser.TrackingTools.cameraDelayEstimationHelper`.
                     
                     * **Parameter:** none
                     * **Return:** none
inhibitRendering     Inhibit rendering camera preview on the Recorder PC.
                     This feature is used by
                     :func:`~GazeParser.TrackingTools.cameraDelayEstimationHelper`.
                     
                     * **Parameter:** none
                     * **Return:** none
isBinocularMode      Reterns whether recording mode is binocular or not. *New in 0.6.4*
                     
                     * **Parameter:** none
                     * **Return** 0: monocular mode / 1: binocular mode
getCameraImageSize   Returns the camera image size.
                     
                     * **Parameter:** none
                     * **Return** Width and height of the camera image (comma-separated).
==================== ========================================================================



How GazeParser.TrackingTools communicates with SimpleGazeTracker
===================================================================

Here are examples of what commands are sent by GazeParser.TrackingTools.
Suppose that 'tracker' is an instance of GazeParser.TrackingTools.ControllerPsychoPyBackend
and that recording mode is monocular.

Opening a new data file
----------------------------------

.. code-block:: python
    
    tracker.openDataFile('test.csv', overwrite=False)

This method sends following command.::

    openDataFile\0test.csv\00\0

.. note::
    'overwrite' option is supported by 0.6.2 or later.

Sending settings
----------------------------------

.. code-block:: python
    
    params = {'SCREEN_WIDTH':1024, 'SCREEN_HEIGHT':768}
    tracker.sendSettings(params)

This method sends following command.::

    insertSettings\0#SCREEN_WIDTH,1024/#SCREEN_HEIGHT,768\0

.. note::
    sendSettings is deprecated in 0.11.0 or later.
    Use "config" option of :func:`~GazeParser.TrackingTools.BaseController.openDataFile` instead.


Calibration Loop
----------------------------------

.. code-block:: python
    
    calarea = [-400,-300,400,300]
    calTargetPos = [[   0,   0],
                    [-350,-250],[-350,  0],[-350,250],
                    [   0,-250],[   0,  0],[   0,250],
                    [ 350,-250],[ 350,  0],[ 350,250]]
    
    tracker.setCalibrationTargetPositions(calarea, calTargetPos)
    
    res = tracker.calibrationLoop()

:func`~GazeParser.TrackingTools.BaseController.calibrationLoop` sends many commands.
At the beginning of calibration loop, key events are checked.
If up arrow key, down arrow key or 'q' key is pressed, corresponding key emuration command is sent.
For example, if down arrow key is pressed, send following command.::

    key_DOWN\0

if left or right arrow key is pressed, corresponding key emuration command is sent.
Then, to update display of parameter value on the Presentation PC, **getCurrMenu** is sent.::

    key_LEFT\0
    getCurrMenu\0

The return value of **getCurrMenu** is like following.

.. code-block:: none
    
    PupilThreshold(56)\0

If 'x' key is pressed, following command is sent to toggle calibration result.
*A parameter (0:off/1:on) is necessary in version 0.6.1 or later*::

    toggleCalResult\01\0

If 'c' key is pressed, following command is sent to start calibration.::

    startCal\0-400,-300,400,300,0\0

During calibration process, **getCalSample** command is sent 400ms after the target reached to new calibration point.::

    getCalSample\0-350,250\0

When calibraton process is finished, **stopCal** command is sent.
Then, **getCalResults** and **getCalResultsDetail** are sent to display calibration results on the Presentation PC.::

    endCal\0
    getCalResults\0
    getCalResultsDetail\0

The return value of **getCalResults** is comma-separated values. If recording mode is monocular, four values are returned.

.. code-block:: none

    5.08,7.88,28.17,50.38\0

**getCalResultsDetail** returns a long string. In this example, there are 9 calibration points.
Ten samples are collected at each point, and each sample has 4 values. Therefore, 9x10x4=360 values are returned.

.. code-block:: none

    -350,9,-357,8,-350,0,-368,0,-350,0,-353,-9,-350,0,-354,-8, (snip) 0,0,-1,7,0,0,2,-6\0

If 'v' key is pressed, validation process is started. Validation process is similar to calibration process, 
but **startVal**, **getValSample** and **endVal** are used instead of **startCal**, **getCalSample** and **endCal**.::

    startVal\0-400,-300,400,300\0
    
    getValSample\0-340,260\0
    
    endVal\0
    getCalResults\0
    getCalResultsDetail\0

After key events are checked, get current camera image by sending **getImageData** if necessary.
::

    getImageData\0

If either 'q' or escape key has been pressed, calibration loop ends. Otherwise, calibration loop is repeated from the beginning.

Recording
----------------------------------

.. code-block:: python
    
    tracker.startRecording(message='trial001')
    tracker.sendMessage('Target LEFT')
    
    while runTrial:
        
        #snip
        
        tracker.getEyePosition(ma=1)
        
        #snip
    
    tracker.stopRecording()

At the beginning of these codes, following commands are sent.::

    startRecording\0trial001\0
    insertMessage\0Target LEFT\0

Everytime when :func:`~GazeParser.TrackingTools.BaseController.getEyePosition` is called, **getEyePosition** command is sent.::

    getEyePosition\01\0

**getEyePosition** returns horizontal, vertical gaze position and pupil size.
Note that units of gaze position is always *pixel*.
Unit conversion is performed within :func:`GazeParser.TrackingTools.ControllerPsychoPyBackend.getEyePosition`.

.. code-block:: none

    766,394,141\0

.. note::
    Only x and y were returned in version 0.5.3 or former. 'ma' option is added in 0.6.4.

At the end of the codes, **stopRecording** is sent. Because tracker.stopRecording() doesn't have message, parameter of **stopRecording** is empty.::

    stopRecording\0\0


Closing the data file
----------------------------------

.. code-block:: python
    
    tracker.closeDataFile()

This code simply sends **closeDataFile** command.::

    closeDataFile\0