WorldViz User Forum

WorldViz User Forum (https://forum.worldviz.com/index.php)
-   Vizard (https://forum.worldviz.com/forumdisplay.php?f=17)
-   -   Timing problem (https://forum.worldviz.com/showthread.php?t=5881)

VizMars 11-02-2016 08:12 AM

Timing problem
 
Hi!
Please find attached a part of my code.
I use a EyeLink 1000 and so "el" stands for eyelink and represents the eyetracker object [el = pylink.EyeLink()]. The variable "ball" is a .osgb-file with a size of 25mb.
The function do_trial is called every trial in my experiment. I want the sound to be played 2 seconds after the ball appeared. But in the first trial of each block (and only in the first) the ball appears after the sound is played, otherwise it works just fine.
Does anybody know why this happens?

Code:

def el_rec_thread():
        while True:               
                #check recording status
                error = el.isRecording()  # First check if recording is aborted
                if error != 0:
                        end_el_trial()
                        return error
                       
                if inspect_over:                               
                        end_el_trial()       
                        break
                       
                #check if break pressed
                if(el.breakPressed()):        # Checks for program termination or ALT-F4 or CTRL-C keys
                        end_el_trial()
                        return pl.ABORT_EXPT
                       
def end_el_recording(participant_id, block_num, trial):
        global inspect_over
       
        sound.play()
        optitrack.set_phase(POST_SOUND)
        msg_end = "%s Block %d Trial %d Ende %d" % ( participant_id, block_num, trial, int(round(viz.tick()*1000)) ) 
        el.sendMessage(msg_end)
        inspect_over = True
       
def end_el_trial():
        '''Ends recording: adds 100 msec of data to catch final events'''
        pl.endRealTimeMode() 
        pl.pumpDelay(100)         
        el.stopRecording()
        while el.getkey() :
                pass

def do_trial(participant_id, block_num, trial, scale, distance):
        global inspect_over
       
        inspect_over = False
        answer = -1 # set initial value to -1
               
        #optitrack.set_block(block_num)
        #optitrack.set_trial(trial)
       
        #This supplies the title of the current trial at the bottom of the eyetracker display
        msg_rec_status = "record_status_message 'Block %d, Trial %d/%d'" % (block_num, trial, N_TRIALS_EXC if (block_num == 0) else N_TRIALS_EXP)
        el.sendCommand(msg_rec_status)
       
        #defines the trial variables
        #MUST be sent to the EyeLink data file PRIOR TO the Trial Start message ("TRIALID ...")
        msg_trial_var = "TRIAL_VAR_LABELS %s %s %s" % ("Participant_ID", "Block_number", "Trial")
        el.sendMessage(msg_trial_var)
       
        #Always send a TRIALID message before starting to record.
        #EyeLink Data Viewer defines the start of a trial by the TRIALID message. 
        #This message is different than the start of recording message START that is logged when the trial recording begins.
        #The Data viewer will not parse any messages, events, or samples, that exist in the data file prior to this message.
        msg_trial_id = "TRIALID %s Block %d Trial %d" % (participant_id, block_num, trial)
        el.sendMessage(msg_trial_id)
       
#        #Does drift correction and handles the re-do camera setup situations
#        ###############################################################################
#        drift_target.visible(viz.ON)
#        yield viztask.waitFrame(1) #wait for the next frame to be drawn
#        while True:                       
#                #Checks whether we are still connected to the tracker
#                if not el.isConnected():               
#                        viztask.returnValue(pl.ABORT_EXPT)                       
#                try:
#                        error = el.doDriftCorrect(MONITOR_WIDTH // 2, MONITOR_HEIGHT // 2, 0, 0)                       
#                        if error == 0:
#                                break # if drift correction OK go on                               
#                except: # if re-calibration is necessary                       
#                        pl.openGraphics( (MONITOR_WIDTH, MONITOR_HEIGHT), 32 )
#                        el.doTrackerSetup()   
#                        pl.closeGraphics()       
#                        break
#        drift_target.visible(viz.OFF)
#        ###############################################################################
       
        #switch tracker to ide and give it time to complete mode switch
        el.setOfflineMode()
        pl.msecDelay(50)
       
        #send trial variable data sometime in BETWEEN the TRIALID and TRIAL_RESULT messages
        msg_trial_data = "!V TRIAL_VAR_DATA %s %d %d" % (participant_id, block_num, trial)
        el.sendMessage(msg_trial_data)

        ##start recording samples and events to edf file and over the link.
        #error = el.startRecording(1, 1, 1, 1)
       
        #start recording samples and events to edf file
        error = el.startRecording(1, 1, 0, 0)
        if(error != 0):        viztask.returnValue(error)
        #disable python garbage collection to avoid delays
        gc.disable()
        #begin the realtime mode
        pl.beginRealTimeMode(100)
        eye_used = el.eyeAvailable() #determine which eye(s) are available
        if eye_used == BINOCULAR:               
                el.sendMessage("EYE_USED: 2 BOTH")
        else:
                print ("Error, not both eyes used!")
                viztask.returnValue(pl.TRIAL_ERROR)
               
        ball.setPosition( [0, 0, -distance] ) 
        ball.setScale( [scale]*3 )       
        #determine trial start time       
        startTime = viz.tick()       
        ball.visible(viz.ON)
        #determine delay of the actual stimulus onset       
        drawTime = int( round((viz.tick() - startTime) * 1000) )       
        msg_start = "%s Block %d Trial %d Start %d" % ( participant_id, block_num, trial, int(round(viz.tick()*1000)) )
        el.sendMessage(msg_start)       
        el.sendMessage("SYNCTIME %d" %drawTime)               

        #reset keys and buttons on tracker
        el.flushKeybuttons(0)
       
        vizact.ontimer2(2, 0, end_el_recording, participant_id, block_num, trial) # repeats = Number of times to repeat the timer. If 0, the timer will be called only once
        rec_data = yield viztask.waitDirector(el_rec_thread)
        if rec_data.returnValue != None: # if not trial-over-case
                viztask.returnValue(rec_data.returnValue)
       
        #the call to the getRecordingStatus() method makes sure that
        #no Abort menu operations remain to be performed, and generates the trial return code
        ret_value = el.getRecordingStatus()
       
        pl.endRealTimeMode()       
       
       
        ###### etc ...


Jeff 11-02-2016 01:06 PM

It's a bit difficult to debug without being able to run the script and reproduce the issue. Please see the guidelines for posting Vizard code as this will make it easier for others to help debug.

One thing you could try is to replace:
Code:

vizact.ontimer2(2, 0, end_el_recording, participant_id, block_num, trial)
with a viztask.waitTime() command that yields for 2 seconds and then calls the function. This will prevent later lines of code in the task function from executing until the two seconds has elapsed.

VizMars 11-04-2016 11:54 AM

Sorry, but I don't know how to provide a code that reproduces the issues without including the eyetracker commands. I excluded the other parts of the code because these are mainly functions that are used for the communication with the eyetracker.
Does
Code:

rec_data = yield viztask.waitDirector(el_rec_thread)
prevent later lines of code in the task function from executing until the timer expires? That poblem is that I need the el_rec_thread to check if the recording is aborted and for (EyeLink) program termination. If I use
Code:

yield viztask.waitTime(2)
then it seems impossible for me to implement this recording thread. :confused:

VizMars 11-08-2016 10:30 AM

Is there an event or function that can tell me whether the rendering of the world is finished?


All times are GMT -7. The time now is 07:56 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Copyright 2002-2023 WorldViz LLC