SightLab Code Reference

SightLab Class Documentation


1. Importing and Initial Setup

You no longer need to import vizconnect, viz, vizfx, or viztask separately as these are automatically included in the settings file.

To initialize SightLab, use the following:

import sightlab_utils.sightlab as sl

from sightlab_utils.settings import *


# Create a SightLab instance

sightlab = sl.SightLab()


# Disable GUI

sightlab = sl.SightLab(gui=False)


Note: For multi-user use sightlab = sightlab = sl.SightLabServer() or sightlab = sl.SightLabClient()

2. Class Overview

The SightLab class initializes a visual experiment environment with attributes for controlling the experiment settings. 

Attributes:


3. Setting the Environment

To configure the environment for your experiment, such as loading 3D models or 360 media:

env = vizfx.addChild('sightlab_resources/environments/dojo2.osgb')

sightlab.setEnvironment(env)


Method Parameters:


4. Managing Trials

Setting Trial Count:

sightlab.setTrialCount(5)


Starting a Trial:

You can start a trial using keyboard/button events or programmatically within a script:

Using Keyboard Events:

vizact.onkeydown(' ', sightlab.startTrial)


Programmatic Start:

yield viztask.waitTime(0.1)

yield sightlab.startTrial(trialLength=60, trialLabel="A", startTrialText="Beginning Trial")

Parameters: 

startTrial(condition = NO_CONDITION, trialLength=-1, trialLabel="A", startTrialText=None, startExperimentText=None, textContinueEvent='triggerPress', textContinueKey=None, trackingDataLogging=True, replayDataLogging=True, experimentSummaryLogging = None, timeLineLogging = None, startPoint = None, startEuler = None)

Ending a Trial:

vizact.onkeydown('e', sightlab.endTrial)

Parameters:

endTrial(condition = NO_CONDITION, endTrialText = None, endExperimentText = None, textContinueEvent = "triggerPress", textContinueKey = None, textContinueTimer = None, endRatings = None)

Direct Event Trigger:

To directly send an event to end a trial from within a function: 

viz.sendEvent(INITIATE_TRIAL_END)

Use this method when you need to trigger the end of a trial based on specific logic or external conditions. 


Scheduling SightLab

viztask.schedule(sightlab.runExperiment())


5. Setting Condition Based on Hardware Setup

You can set up specific conditions based on the hardware configuration being used. For instance, to check if the hardware is a "Meta Quest Pro" and adjust your experiment setup accordingly: 

if sightlab.getConfig() == "Meta Quest Pro":

# Add conditional logic for Meta Quest Pro hardware 


6. Adding and Managing Scene Objects

Adding Scene Objects

To add objects to the scene, use the addSceneObject method. This allows you to track gaze, grab interactions, and set visibility for the objects. Note: you only need to add the parameters you need. If you only add the name and sceneObject it will just be tracked for replay, but not gaze or grab data and interactions. 

sightlab.addSceneObject(name, sceneObject, gaze=True, grab=False, visible=True, avatar=False)


Parameters:

Multiple Objects:

You can add multiple objects in bulk:

sceneDict = {'Soccerball': [True, True], 'Baseball': [True, True]}

for item in sceneDict:

    sightlab.addSceneObject(item, env.getChild(item), gaze=sceneDict[item][0], grab=sceneDict[item][1])



7. Session Replay

The SightLabReplay class allows for replaying sessions, interacting with objects, and retrieving trial and gaze data. For more information and all the relevant code with the replay, see this page

Import and Setup:

from sightlab_utils import replay as Replay

from sightlab_utils.replay_settings import *


replay = Replay.SightLabReplay()

Session Replay Methods:

replay.transportNode.setPosition([x, y, z])

env = replay.getEnvironmentObject()

screen = replay.sceneObjects[GAZE_OBJECTS]['screen']

trial_number = int(replay.currTrial)

gazePointObject = replay.sceneObjects[GAZE_POINT_OBJECT]['1']


8. Ratings and Instructions

Ratings:

yield sightlab.showRatings('How are you feeling?', ratingScale=scaleList, pauseTimer=True)

You can also add a start or end rating scale within the trial using the startTrial or endTrial methods. See here for more information

Instructions:

yield sightlab.showInstructions('Press Space to Continue')

yield viztask.waitEvent('triggerPress')

yield sightlab.hideInstructions()

Can also add a start or end instructions or use images (see here for more information)

9. Gaze-Based Interactions 

You can trigger events based on gaze interactions within your scene. For example, detecting when a participant finds a target object: see here for more information

This is how you check which object is being viewed 

if e.object == sightlab.sceneObjects[GAZE_OBJECTS][TARGET_PAINTING]:

Example

def gazeActionEnd(e):

if e.object == sightlab.sceneObjects[GAZE_OBJECTS]['target_object']:

print('item found')

viz.sendEvent(INITIATE_TRIAL_END)

vizact.addCallback(sightlab.GAZE_TIME_EVENT, findItem)

10. Adjusting Fixations/Saccade/Dwell Parameters

Note: these need to be set after .startTrial()

sightlab.setDwellTimeThreshold(dwellTime = DWELL_THRESHOLD)      

sightlab.setFixationSaccadeThresholds(dispersionThreshold = 1, durationThreshold = 0.1)

11. Setting Position

Reset Position

viz.callback(viz.getEventID('ResetPosition'), sightlab.resetViewPoint)

This will reset your position back to the origin relative to your physical location. To change this point to a different value, will need to manually add the resetPosition code. 

Changing Starting Position

SightLab (can also add a Starting Point object in the GUI (see Creating a New Scene), or when calling sightlab.startTrial()

sightlab.transportNode.setPosition([0,0,0])

#or can use this

sightlab.setStartPoint((2,0,0))

Session Replay Starting Point

replay.transportNode.setPosition([0,0,0])

12. Miscellaneous  

sightlab.setEnvironmentDirectory('path_to_resources_folder')


sightlab.setStartText('Press Spacebar to start')

for i in range(sightlab.getTrialCount()):

    # Custom logic for each trial

sightlab.addSceneObject("wall2", wall2, gaze=True, visible=False)

sightlab.getEyeTracker()


To work with STIM files, initialize the StimReader: see here for more information

from sightlab_utils import stim_reader

SR = stim_reader.StimReader(STIM_FILE_LOCATION)

SR.fillStimFileEntryList()

If you are using env.getChild to access your objects you need to use a .getTransform to access the object's position: 

targetTransform = env.getTransform('targetTransform')

Alternatively, use env.getChild on the object's GEODE.

sightlab.hud.getCurrentTime()

sightlab.setMaxDistance(1000)

sightlab.setHeadLight(state, intensity = None, color = None)

13. Working with 360 Media

sightlab.getMediaObject()

region1 = sightlab.getRegionOfInterest('tire')

14. Accessing the Environment Object

env = sightlab.getEnvironment()

Using the environment object in context

#Access after EXPERIMENT_START

def sightLabExperiment():

global env

yield viztask.waitEvent(EXPERIMENT_START)

env = sightlab.getEnvironment()

#If need access to it before use env = None, and put inside a function that can be called after it is set in the trial

def initialize_environment():

target = env.getChild(name)

def sightLabExperiment():

global env

yield viztask.waitEvent(EXPERIMENT_START)

env = sightlab.getEnvironment()

initialize_environment()

15. Changing Models to use for Avatar


head = vizfx.addChild(AVATAR_HEAD_RESOURCE_PATH+'/Male1.osgb'))

sightlab.setAvatarHead(head)

Other way

sightlab.setAvatarHead(head = vizfx.addChild(AVATAR_HEAD_RESOURCE_PATH+'/Male1.osgb'))

#Setting Hands

sightlab.setAvatarRightHand(rightHand= vizfx.addChild(AVATAR_HANDS_RESOURCE_PATH+'/empty.osgb'))

16. Toggling Visibility of Overlays

sightlab.toggleHUD()

17. Data Logging

For more information see this page

addCustomFlagColumn(self, columnName)


addTrackingTrialDataColumn(self, columnName, trackedObject, dataType='SIXDOF', mode=4)


sightlab.setExperimentSummaryData('condition',condition)

Adding a Custom Flag

sightlab.setCustomTrialData('name of flag')

Changing Data Directories

sightlab.setDataDirectory()


Setting Condition/Label

yield sightlab.startTrial(trialLabel = "A")

Adding additional file to the Data folder

fileName = '{d}_{p.id}_experiment_data._trial_{t}.pdf'.format(d=sightlab.dateTime, p=sightlab.participantData, t=sightlab.trialNumber)

fullPath = os.path.join(sightlab.getExperimentDataFolderPath(), fileName) drawChart(fullPath, sightlab.getPlotData())

18. Settings File

See here for information on the settings file located in the sightlab installation folder

19. Multi User

For code relevant to Multi User see this page

20. Hardware Events

Hardware button and keyboard mappings can be accessed to trigger functions. See the page on the Vizconnect Hardware Configurations page for a list. 

21. Method Reference

Environment and Setup:

Trial Management

Object Management

Avatar Management

Gaze and Tracking

Data Logging

Ratings and Instructions

Recording and Replay

Control and Transport

HUD and Console

Region of Interest (ROI)

Experiment Control

Miscellaneous


22. Example Usage

import sightlab_utils.sightlab as sl

from sightlab_utils.settings import *


# Initialize SightLab without GUI

sightlab = sl.SightLab(gui=False)


# Set up environment

env = vizfx.addChild('sightlab_resources/environments/dojo.osgb')

sightlab.setEnvironment(env)


# Add scene objects

soccerball = env.getChild('soccerball')

sightlab.addSceneObject('soccerball', soccerball, gaze=True, grab=True)


# Set trial count and start the experiment

sightlab.setTrialCount(3)


def sightLabExperiment():

    yield viztask.waitKeyDown(' ')

    while True:

        yield sightlab.startTrial(trialLength=5, startTrialText="Look around!")

        yield viztask.waitEvent(TRIAL_END)


viztask.schedule(sightlab.runExperiment)

viztask.schedule(sightLabExperiment)