Browse Source

Updated a number of settings. Forgot to commit for a while. -MT

master
mike 6 years ago
parent
commit
fd6ae585df
  1. 58
      SaccadePursuit.py
  2. 418
      SaccadePursuitEyeTracking.py
  3. 0
      eyelinker.py
  4. 28
      template.py

58
SaccadePursuit.py

@ -71,12 +71,14 @@ class SPtask(template.BaseExperiment):
stim_color, pursuit_frequencies, stim_color, pursuit_frequencies,
saccade_distance, saccade_time, saccade_distance, saccade_time,
stimulus_size, saccade_fixation_color, stimulus_size, saccade_fixation_color,
number_of_saccade_lights,
fixation_size, pursuit_distance, fixation_size, pursuit_distance,
necker_time, necker_color, necker_time, necker_color,
necker_scale, necker_bg_color, necker_scale, necker_bg_color,
necker_file, rivalry_file1, rivalry_file2, necker_file, rivalry_file1, rivalry_file2,
fixation_trial_time, rivalry_time, fixation_trial_time, rivalry_time,
rivalry_scale,rivalry_border_color, rivalry_height, rivalry_width,
rivalry_border_color,
rivalry_border_width, rivalry_distance, rivalry_border_width, rivalry_distance,
new_trial_sound, new_trial_sound,
questionaire_dict=None, questionaire_dict=None,
@ -96,6 +98,7 @@ class SPtask(template.BaseExperiment):
self.stimulus_size = stimulus_size self.stimulus_size = stimulus_size
self.saccade_distance = saccade_distance self.saccade_distance = saccade_distance
self.saccade_fixation_color = saccade_fixation_color self.saccade_fixation_color = saccade_fixation_color
self.number_of_saccade_lights = number_of_saccade_lights
# Fixation # Fixation
self.fixation_size = fixation_size self.fixation_size = fixation_size
@ -110,7 +113,8 @@ class SPtask(template.BaseExperiment):
# Rivalry # Rivalry
self.rivalry_time = rivalry_time self.rivalry_time = rivalry_time
self.rivalry_scale = rivalry_scale self.rivalry_height = rivalry_height
self.rivalry_width = rivalry_width
self.rivalry_file1 = rivalry_file1 self.rivalry_file1 = rivalry_file1
self.rivalry_file2 = rivalry_file2 self.rivalry_file2 = rivalry_file2
self.rivalry_border_color = rivalry_border_color self.rivalry_border_color = rivalry_border_color
@ -141,10 +145,14 @@ class SPtask(template.BaseExperiment):
trial_list = [] trial_list = []
saccade_locations = list(range(-self.saccade_distance,0,1)) #saccade_locations = list(range(-self.saccade_distance,0,1))
for x in range(self.saccade_distance): #for x in range(self.saccade_distance):
saccade_locations.append(x+1) # saccade_locations.append(x+1)
random.shuffle(saccade_locations) #random.shuffle(saccade_locations)
temp1 = random.sample(range(1,self.saccade_distance+1),self.number_of_saccade_lights)
temp2 = random.sample(range(1,self.saccade_distance+1),self.number_of_saccade_lights)
saccade_locations = [x*-1 for x in temp1] + temp2
counter = 0 counter = 0
for num_trials in range(numTrials): for num_trials in range(numTrials):
@ -201,7 +209,7 @@ class SPtask(template.BaseExperiment):
break_text = 'Please take a short break. Press any key to continue.' break_text = 'Please take a short break. Press any key to continue.'
self.display_text_screen(text=break_text, bg_color=[0, 0, 0]) self.display_text_screen(text=break_text, bg_color=[0, 0, 0])
def display_fixation(self, wait_time, necker_bg_color=[-1,-1,-1]): def display_fixation(self, wait_time, tracker, necker_bg_color=[-1,-1,-1]):
"""Displays a fixation cross. A helper function for self.run_trial. """Displays a fixation cross. A helper function for self.run_trial.
Parameters: Parameters:
@ -213,6 +221,9 @@ class SPtask(template.BaseExperiment):
stim = psychopy.visual.TextStim( stim = psychopy.visual.TextStim(
self.experiment_window, text='+', color=self.stim_color, height=self.fixation_size, units='deg') self.experiment_window, text='+', color=self.stim_color, height=self.fixation_size, units='deg')
if tracker:
tracker.send_message('Start Fixation')
for frameN in range(int(round(wait_time*60))): for frameN in range(int(round(wait_time*60))):
stim.draw() stim.draw()
self.experiment_window.flip() self.experiment_window.flip()
@ -249,8 +260,8 @@ class SPtask(template.BaseExperiment):
pos=[tempCoord,0], fillColor=self.saccade_dot_color, pos=[tempCoord,0], fillColor=self.saccade_dot_color,
lineColor=self.saccade_dot_color, units='deg') lineColor=self.saccade_dot_color, units='deg')
stimList.append(tempStim) stimList.append(tempStim)
if tracker:
tracker.send_message('Start Stim') tracker.send_message('Start Stim')
for frameN in range(int(round(stim_time*60))): for frameN in range(int(round(stim_time*60))):
for s in stimList: for s in stimList:
s.draw() s.draw()
@ -258,7 +269,8 @@ class SPtask(template.BaseExperiment):
stim.draw() stim.draw()
self.experiment_window.flip() self.experiment_window.flip()
#print(psychopy.tools.monitorunittools.deg2pix(stim.pos, self.experiment_monitor)) #print(psychopy.tools.monitorunittools.deg2pix(stim.pos, self.experiment_monitor))
tracker.send_message('End Stim') if tracker:
tracker.send_message('End Stim')
def display_saccade_fixation(self, stim_time): def display_saccade_fixation(self, stim_time):
"""Displays the stimuli. A helper function for self.run_saccade_trial. """Displays the stimuli. A helper function for self.run_saccade_trial.
@ -292,7 +304,7 @@ class SPtask(template.BaseExperiment):
fixation.draw() fixation.draw()
self.experiment_window.flip() self.experiment_window.flip()
def display_pursuit(self, stim_frequency, stim_time): def display_pursuit(self, stim_frequency, stim_time, tracker):
"""Displays a pursuit stimululus. A helper function for self.run_pursuit_trial. """Displays a pursuit stimululus. A helper function for self.run_pursuit_trial.
Parameters: Parameters:
@ -325,6 +337,9 @@ class SPtask(template.BaseExperiment):
stim.draw() stim.draw()
self.experiment_window.flip() self.experiment_window.flip()
if tracker:
tracker.send_message('Start Stim')
for Xpos in Xposition: for Xpos in Xposition:
stim.pos = (Xpos,0) stim.pos = (Xpos,0)
stim.draw() stim.draw()
@ -344,6 +359,8 @@ class SPtask(template.BaseExperiment):
stim.size *= self.necker_scale stim.size *= self.necker_scale
stim.setColor(self.necker_color, 'rgb255') stim.setColor(self.necker_color, 'rgb255')
responses = [] responses = []
if tracker:
tracker.send_message('Start Stim')
for frameN in range(stim_time*60): for frameN in range(stim_time*60):
response = psychopy.event.getKeys() response = psychopy.event.getKeys()
if response: if response:
@ -365,15 +382,16 @@ class SPtask(template.BaseExperiment):
def display_rivalry(self, stim_time, tracker): def display_rivalry(self, stim_time, tracker):
color = self.rivalry_border_color color = self.rivalry_border_color
lineSize = self.rivalry_border_width lineSize = self.rivalry_border_width
imDist = self.rivalry_distance stimPos = self.experiment_window.size[0]/4
stimPos = psychopy.tools.monitorunittools.pix2deg(stimPos,self.experiment_monitor)
stim1 = psychopy.visual.ImageStim( stim1 = psychopy.visual.ImageStim(
self.experiment_window, self.experiment_window,
image=self.rivalry_file1, pos=(-imDist,0)) image=self.rivalry_file1, pos=(-stimPos,0))
stim1.size *= self.rivalry_scale stim1.size = (self.rivalry_width, self.rivalry_height)
stim2 = psychopy.visual.ImageStim( stim2 = psychopy.visual.ImageStim(
self.experiment_window, self.experiment_window,
image=self.rivalry_file2, pos=(imDist,0)) image=self.rivalry_file2, pos=(stimPos,0))
stim2.size *= self.rivalry_scale stim2.size = (self.rivalry_width, self.rivalry_height)
borderScale = stim1.size[0]*0.4 borderScale = stim1.size[0]*0.4
borderWidth1 = stim1.size[0]+borderScale borderWidth1 = stim1.size[0]+borderScale
@ -408,6 +426,8 @@ class SPtask(template.BaseExperiment):
lineColor=color, lineWidth=lineSize) lineColor=color, lineWidth=lineSize)
responses = [] responses = []
if tracker:
tracker.send_message('Start Stim')
for frameN in range(stim_time*60): for frameN in range(stim_time*60):
response = psychopy.event.getKeys() response = psychopy.event.getKeys()
if response: if response:
@ -447,11 +467,11 @@ class SPtask(template.BaseExperiment):
if trial['trial_type']=='Necker': if trial['trial_type']=='Necker':
freq = self.display_necker(trial['trial_time'], tracker) freq = self.display_necker(trial['trial_time'], tracker)
elif trial['trial_type']=='Pursuit': elif trial['trial_type']=='Pursuit':
self.display_pursuit(trial['pursuit_frequency'],trial['trial_time']) self.display_pursuit(trial['pursuit_frequency'],trial['trial_time'],tracker)
psychopy.sound.Sound(self.new_trial_sound).play() psychopy.sound.Sound(self.new_trial_sound).play()
freq = trial['pursuit_frequency'] freq = trial['pursuit_frequency']
elif trial['trial_type']=='Fixation': elif trial['trial_type']=='Fixation':
self.display_fixation(trial['trial_time']) self.display_fixation(trial['trial_time'],tracker)
elif trial['trial_type']=='Rivalry': elif trial['trial_type']=='Rivalry':
freq = self.display_rivalry(trial['trial_time'], tracker) freq = self.display_rivalry(trial['trial_time'], tracker)
else: else:
@ -459,7 +479,7 @@ class SPtask(template.BaseExperiment):
psychopy.sound.Sound(self.new_trial_sound).play() psychopy.sound.Sound(self.new_trial_sound).play()
data = { data = {
'Subject': self.experiment_info['Subject Identifier'], 'Subject': self.experiment_info['Subject ID'],
'Block': block_num, 'Block': block_num,
'Trial': trial_num, 'Trial': trial_num,
'Timestamp': psychopy.core.getAbsTime(), 'Timestamp': psychopy.core.getAbsTime(),

418
SaccadePursuitEyeTracking.py

@ -16,6 +16,8 @@ import random
import sys import sys
import traceback import traceback
import subprocess import subprocess
import math
import numpy
# Necesssary to access psychopy paths # Necesssary to access psychopy paths
import psychopy # noqa:F401 import psychopy # noqa:F401
@ -26,22 +28,26 @@ import SaccadePursuit
# Experimental Parameters # Experimental Parameters
monitor_name = 'testMonitor' monitor_name = 'testMonitor'
monitor_width = 41 monitor_width = 41 #25.8 height
distance_to_monitor = 74 distance_to_monitor = 74
monitor_px = [1440,900] monitor_px = [1440,900]
window_screen = 1 window_screen = 1
disableTracker = True # For Debugging disableTracker = False # For Debugging
isi_time = 2 # Interstimulus Interval isi_time = 2 # Interstimulus Interval
data_directory = os.path.join( data_directory = os.path.join(
os.path.expanduser('~'), 'Desktop', 'ExperimentalData', 'SaccadePursuitEyeTracking') os.path.expanduser('~'), 'Desktop', 'ExperimentalData', 'SaccadePursuitEyeTracking')
image_directory = os.path.join(os.getcwd(),'Images') # image_directory = os.path.join(os.getcwd(),'Images')
image_directory = os.path.join(
os.path.expanduser('~'), 'Desktop','SaccadePursuitExperiment','Images')
new_trial_sound = 'A' new_trial_sound = 'A'
instHeight = 6
# Saccade / Antisaccade Parameters # Saccade / Antisaccade Parameters
number_of_saccade_trials = 1 number_of_saccade_trials = 1
number_of_saccade_blocks = 1 number_of_saccade_blocks = 1
saccade_distance = 15 # Degrees per direction saccade_distance = 15 # Degrees per direction
number_of_saccade_lights = 7 # Number of active lights per direction
saccade_time = 3 # Maximum Time saccade_time = 3 # Maximum Time
stimulus_size = 0.3 stimulus_size = 0.3
stim_color = [1,-1,-1] stim_color = [1,-1,-1]
@ -54,8 +60,8 @@ antisaccade_file_scale = 1
number_of_pursuit_trials = 1 number_of_pursuit_trials = 1
number_of_pursuit_blocks = 1 number_of_pursuit_blocks = 1
pursuit_distance = 15 pursuit_distance = 15
pursuit_frequencies = [0.1,0.2,0.4] pursuit_frequencies = [0.1,0.2,0.3]
pursuit_time = [40,20,15] pursuit_time = [40,20,13.33]
# Necker Cube Parameters # Necker Cube Parameters
number_of_necker_trials = 1 number_of_necker_trials = 1
@ -78,12 +84,14 @@ fixation_trial_time = 15
number_of_rivalry_trials = 1 number_of_rivalry_trials = 1
number_of_rivalry_blocks = 1 number_of_rivalry_blocks = 1
rivalry_time = 90 rivalry_time = 90
rivalry_scale = 2.5 #rivalry_scale = 2.5
rivalry_height = 1.5
rivalry_width = 1
rivalry_distance = 3
rivalry_file1 = os.path.join(image_directory,'house4n_11-160.tif') rivalry_file1 = os.path.join(image_directory,'house4n_11-160.tif')
rivalry_file2 = os.path.join(image_directory,'face2nS_11-160.tif') rivalry_file2 = os.path.join(image_directory,'face2nS_11-160.tif')
rivalry_border_color = [190,190,190] rivalry_border_color = [190,190,190]
rivalry_border_width = 5 rivalry_border_width = 5
rivalry_distance = 4
response_box_file = os.path.join(image_directory,'ResponseBox3.tif') response_box_file = os.path.join(image_directory,'ResponseBox3.tif')
response_box_scale = 0.22 response_box_scale = 0.22
@ -101,43 +109,42 @@ data_fields = [
# Add additional questions here # Add additional questions here
questionaire_dict = { questionaire_dict = {
'Run Fixation': True,
'Run Smooth Pursuit': True, 'Run Smooth Pursuit': True,
'Run Saccade': True, 'Run Saccade': True,
'Run Anti-Saccade': True, 'Run Anti-Saccade': True,
'Run Necker Cube': True, # 'Run Necker Cube': False,
'Run Binocular Rivalry': False, 'Run Binocular Rivalry': True,
} }
questionaire_order=[ questionaire_order=[
'Subject Identifier', 'Subject ID',
'Age', 'Session',
'Timepoint',
'Experimenter Initials', 'Experimenter Initials',
'Gender', 'Gender',
'Run Fixation',
'Run Smooth Pursuit', 'Run Smooth Pursuit',
'Run Saccade', 'Run Saccade',
'Run Anti-Saccade', 'Run Anti-Saccade',
'Run Necker Cube', # 'Run Necker Cube',
'Run Binocular Rivalry', 'Run Binocular Rivalry',
] ]
instruct_text = [ instruct_text = [
('Welcome to the experiment. Press any key to continue.'), ('Welcome to the experiment'),
('In this experiment you will be following targets.\n\n' (#'In this experiment you will be following targets.\n\n'
'Each trial will start with a fixation cross. ' # 'Each trial will start with a fixation cross. '
'Focus on the fixation cross until a stimulus appears.\n\n' # 'Focus on the fixation cross until a stimulus appears.\n\n'
'In the first three phases, you will follow the stimuli. ' # 'In the first three phases, you will follow the stimuli. '
'In the fourth phase, you will focus on the ' # 'In the fourth phase, you will focus on the '
'opposite side of center cross at an ' # 'opposite side of center cross at an '
'equal distance as the stimulus. In the fifth ' # 'equal distance as the stimulus. In the fifth '
'phase, you will see a cube, and are to respond as ' # 'phase, you will see a cube, and are to respond as '
'indicated.' # 'indicated.'
'\n\n' # '\n\n'
'Do not move your head during the trials of this ' 'Do not move your head during the trials of this '
'experiment. Move only your eyes to follow the targets.' 'experiment.\n\nMove only your eyes.\n'),
'You will be offered breaks in between sections.\n\n' # 'You will be offered rests between sections.\n\n'
'Press any key to continue.'), # 'Press any key to continue.'),
] ]
saccade_instruct_text = ( saccade_instruct_text = (
@ -150,7 +157,7 @@ saccade_instruct_text = (
'move your eyes back to the fixation cross.\n\n' 'move your eyes back to the fixation cross.\n\n'
'Try not to blink while a red dot is displayed.\n\n' 'Try not to blink while a red dot is displayed.\n\n'
'You can then blink or close your eyes to rest for a few seconds.\n\n' 'You can then blink or close your eyes to rest for a few seconds.\n\n'
'Press any key to continue.' # 'Press any key to continue.'
) )
antisaccade_instruct_text = ( antisaccade_instruct_text = (
@ -164,7 +171,7 @@ antisaccade_instruct_text = (
'to the fixation point after each target disappears.\n\n' 'to the fixation point after each target disappears.\n\n'
'Try not to blink while a red dot is displayed.\n\n' 'Try not to blink while a red dot is displayed.\n\n'
'You can then blink or close your eyes to rest for a few seconds.\n\n' 'You can then blink or close your eyes to rest for a few seconds.\n\n'
'Press any key to continue.' # 'Press any key to continue.'
) )
pursuit_instruct_text = ( pursuit_instruct_text = (
@ -176,17 +183,7 @@ pursuit_instruct_text = (
'two seconds.\n\n' 'two seconds.\n\n'
'Try not to blink while the dot is moving.\n\n' 'Try not to blink while the dot is moving.\n\n'
'You can then blink or close your eyes to rest for a few seconds.\n\n' 'You can then blink or close your eyes to rest for a few seconds.\n\n'
'Press any key to continue.' # 'Press any key to continue.'
)
fixation_instruct_text = (
'For this experiment, we want to know how well you can keep '
'your eyes fixed on a target without moving. When the cross '
'appears, please fixate on it.\n\n'
'Try not to move your eyes from the cross or blink until it '
'disappears.\n\n'
'You can then blink or close your eyes to rest for a few seconds.\n\n'
'Press any key to continue.'
) )
necker_instruct_text = ( necker_instruct_text = (
@ -199,7 +196,7 @@ necker_instruct_text = (
'Try not to blink after the cube appears.\n\n' 'Try not to blink after the cube appears.\n\n'
'You can blink or close your eyes to rest after the cube ' 'You can blink or close your eyes to rest after the cube '
'disappears.\n\n' 'disappears.\n\n'
'Press any key to continue.' # 'Press any key to continue.'
) )
rivalry_instruct_text = ( rivalry_instruct_text = (
@ -210,7 +207,7 @@ rivalry_instruct_text = (
'the face and house, press the center button.\n\n' 'the face and house, press the center button.\n\n'
'You can blink or close your eyes to rest for a few seconds ' 'You can blink or close your eyes to rest for a few seconds '
'after the pictures disappear.\n\n' 'after the pictures disappear.\n\n'
'Press any key to continue.' # 'Press any key to continue.'
) )
def convert_color_value(color): def convert_color_value(color):
@ -226,12 +223,13 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.quit = False # Needed because eyetracker must shut down self.quit = False # Needed because eyetracker must shut down
self.tracker = None self.tracker = None
self.disable_tracker = disableTracker self.disableTracker = disableTracker
self.window_screen = window_screen self.window_screen = window_screen
self.monitor_px = monitor_px self.monitor_px = monitor_px
self.number_of_saccade_trials = number_of_saccade_trials self.number_of_saccade_trials = number_of_saccade_trials
self.number_of_saccade_blocks = number_of_saccade_blocks self.number_of_saccade_blocks = number_of_saccade_blocks
self.number_of_saccade_lights = number_of_saccade_lights
self.number_of_pursuit_trials = number_of_pursuit_trials self.number_of_pursuit_trials = number_of_pursuit_trials
self.number_of_pursuit_blocks = number_of_pursuit_blocks self.number_of_pursuit_blocks = number_of_pursuit_blocks
self.number_of_necker_trials = number_of_necker_trials self.number_of_necker_trials = number_of_necker_trials
@ -246,6 +244,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.response_box_scale = response_box_scale self.response_box_scale = response_box_scale
self.antisaccade_instruct_file = antisaccade_instruct_file self.antisaccade_instruct_file = antisaccade_instruct_file
self.antisaccade_file_scale = antisaccade_file_scale self.antisaccade_file_scale = antisaccade_file_scale
self.instHeight = instHeight
super(EyeTrackingSaccadePursuit, self).__init__(**kwargs) super(EyeTrackingSaccadePursuit, self).__init__(**kwargs)
@ -255,12 +254,18 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.display_text_screen('Quiting...', wait_for_input=False) self.display_text_screen('Quiting...', wait_for_input=False)
if self.tracker: if self.tracker:
fName = os.path.join(self.data_directory, fName = os.path.join(self.data_directory,
'ETSP' + self.experiment_info['Subject Identifier'] + '.edf') self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf')
fName2 = os.path.join(self.data_directory,
'ETSP_' + self.experiment_info['Subject ID'] + self.experiment_info['Session'] \
+ self.experiment_info['Timepoint'] + '.edf')
self.tracker.set_offline_mode() self.tracker.set_offline_mode()
self.tracker.close_edf() self.tracker.close_edf()
self.tracker.transfer_edf() self.tracker.transfer_edf()
self.tracker.close_connection() self.tracker.close_connection()
subprocess.call(['edf2asc',fName]) #subprocess.call(['rename',fName, fName2])
os.rename(fName, fName2)
subprocess.call(['edf2asc',fName2])
super(EyeTrackingSaccadePursuit, self).quit_experiment() super(EyeTrackingSaccadePursuit, self).quit_experiment()
def run(self): def run(self):
@ -276,16 +281,14 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
sys.exit(1) sys.exit(1)
conditions = [] conditions = []
if self.experiment_info['Run Fixation']:
conditions.append('Fixation')
if self.experiment_info['Run Smooth Pursuit']: if self.experiment_info['Run Smooth Pursuit']:
conditions.append('Pursuit') conditions.append('Pursuit')
if self.experiment_info['Run Saccade']: if self.experiment_info['Run Saccade']:
conditions.append('Saccade') conditions.append('Saccade')
if self.experiment_info['Run Anti-Saccade']: if self.experiment_info['Run Anti-Saccade']:
conditions.append('AntiSaccade') conditions.append('AntiSaccade')
if self.experiment_info['Run Necker Cube']: # if self.experiment_info['Run Necker Cube']:
conditions.append('Necker') # conditions.append('Necker')
if self.experiment_info['Run Binocular Rivalry']: if self.experiment_info['Run Binocular Rivalry']:
conditions.append('Rivalry') conditions.append('Rivalry')
@ -297,7 +300,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
if not self.disableTracker: if not self.disableTracker:
self.tracker = eyelinker.EyeLinker( self.tracker = eyelinker.EyeLinker(
self.experiment_window, self.experiment_window,
'ETSP' + self.experiment_info['Subject Identifier'] + '.edf', self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf',
'BOTH' 'BOTH'
) )
self.tracker.initialize_graphics() self.tracker.initialize_graphics()
@ -324,33 +327,38 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
numBlocks = 1 numBlocks = 1
numTrials = 1 numTrials = 1
if condition == 'Saccade': if condition == 'Saccade':
self.display_text_screen(text=saccade_instruct_text) # self.display_text_screen(text=saccade_instruct_text)
self.display_saccade_instructions()
numBlocks = self.number_of_saccade_blocks numBlocks = self.number_of_saccade_blocks
numTrials = self.number_of_saccade_trials numTrials = self.number_of_saccade_trials
elif condition=='AntiSaccade': elif condition=='AntiSaccade':
self.display_text_screen(text=antisaccade_instruct_text, # self.display_text_screen(text=antisaccade_instruct_text,
image_file = antisaccade_instruct_file, # image_file = antisaccade_instruct_file,
image_scale = self.antisaccade_file_scale) # image_scale = self.antisaccade_file_scale)
self.display_saccade_instructions(anti=True)
numBlocks = self.number_of_saccade_blocks numBlocks = self.number_of_saccade_blocks
numTrials = self.number_of_saccade_trials numTrials = self.number_of_saccade_trials
elif condition=='Fixation': elif condition=='Fixation':
self.display_text_screen(text=fixation_instruct_text)
numBlocks = self.number_of_fixation_blocks numBlocks = self.number_of_fixation_blocks
numTrials = self.number_of_fixation_trials numTrials = self.number_of_fixation_trials
elif condition=='Pursuit': elif condition=='Pursuit':
self.display_text_screen(text=pursuit_instruct_text) # self.display_text_screen(text=pursuit_instruct_text)
self.display_pursuit_instructions()
numBlocks = self.number_of_pursuit_blocks numBlocks = self.number_of_pursuit_blocks
numTrials = self.number_of_pursuit_trials numTrials = self.number_of_pursuit_trials
elif condition=='Necker': elif condition=='Necker':
self.display_text_screen(text=necker_instruct_text, self.display_text_screen(text=necker_instruct_text,
image_file=self.necker_response_box_file, image_file=self.necker_response_box_file,
image_scale=self.necker_response_box_scale) image_scale=self.necker_response_box_scale)
numBlocks = self.number_of_necker_blocks numBlocks = self.number_of_necker_blocks
numTrials = self.number_of_necker_trials numTrials = self.number_of_necker_trials
elif condition=='Rivalry': elif condition=='Rivalry':
self.display_text_screen(text=rivalry_instruct_text, # self.display_text_screen(text=rivalry_instruct_text,
image_file=self.response_box_file, # image_file=self.response_box_file,
image_scale=self.response_box_scale) # image_scale=self.response_box_scale)
self.display_rivalry_instructions(
image_file=self.response_box_file,
image_scale=self.response_box_scale)
numBlocks = self.number_of_rivalry_blocks numBlocks = self.number_of_rivalry_blocks
numTrials = self.number_of_rivalry_trials numTrials = self.number_of_rivalry_trials
else: else:
@ -363,14 +371,18 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
if condition == 'Saccade' or condition == 'AntiSaccade': if condition == 'Saccade' or condition == 'AntiSaccade':
self.display_saccade_fixation(1) self.display_saccade_fixation(1)
else: else:
self.display_fixation(0.5) self.display_fixation(0.5,[])
for trial_num, trial in enumerate(block): for trial_num, trial in enumerate(block):
print( printString = ("Condition: %s (%d/%d) Block: %d/%d Trial %d/%d"
"Condition: ",condition,"(",condition_counter,"/",len(conditions),")", % (condition,condition_counter,len(conditions),
"Block ",block_num+1,"/",numBlocks, block_num+1,numBlocks,trial_num+1,len(block)))
" Trial ",trial_num+1,"/",len(block) if condition == 'Saccade' or condition == 'AntiSaccade':
) if trial['locations'][0]>0:
printString = printString + " (Right)"
else:
printString = printString + " (Left)"
print(printString)
if not self.disableTracker: if not self.disableTracker:
self.tracker.send_message('CONDITION %s' % condition) self.tracker.send_message('CONDITION %s' % condition)
self.tracker.send_message('BLOCK %d' % block_num) self.tracker.send_message('BLOCK %d' % block_num)
@ -380,22 +392,26 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.tracker.send_status(status) self.tracker.send_status(status)
#psychopy.sound.Sound('C').play() #psychopy.sound.Sound('C').play()
self.tracker.start_recording() self.tracker.start_recording()
if condition == 'Pursuit' and trial_num==0:
self.display_fixation(self.fixation_trial_time,self.tracker)
data = self.run_trial(trial, block_num, trial_num, self.tracker) data = self.run_trial(trial, block_num, trial_num, self.tracker)
self.tracker.stop_recording() self.tracker.stop_recording()
#psychopy.sound.Sound('C').play() #psychopy.sound.Sound('C').play()
else: else:
if condition == 'Pursuit' and trial_num==0:
self.display_fixation(self.fixation_trial_time,self.tracker)
data = self.run_trial(trial, block_num, trial_num) data = self.run_trial(trial, block_num, trial_num)
data.update({'Condition': condition}) data.update({'Condition': condition})
self.send_data(data) self.send_data(data)
if condition == 'Saccade' or condition=='AntiSaccade': if condition == 'Saccade' or condition=='AntiSaccade':
self.display_saccade_fixation(self.isi_time) self.display_saccade_fixation(self.isi_time)
else: else:
self.display_fixation(self.isi_time) self.display_fixation(self.isi_time,[])
if condition == 'Saccade' or condition == 'AntiSaccade': if condition == 'Saccade' or condition == 'AntiSaccade':
self.display_saccade_fixation(1) self.display_saccade_fixation(1)
else: else:
self.display_fixation(0.5) self.display_fixation(0.5,[])
self.save_data_to_csv() self.save_data_to_csv()
if block_num + 1 != numBlocks: if block_num + 1 != numBlocks:
@ -429,6 +445,264 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.quit_experiment() self.quit_experiment()
def display_pursuit_instructions(
self, bg_color=[0,0,0], wait_for_input=True, **kwargs):
bg_color = convert_color_value(bg_color)
fg_color = convert_color_value([255,255,255])
backgroundRect = psychopy.visual.Rect(
self.experiment_window, fillColor=bg_color, units='norm', width=2,
height=2)
backgroundRect.draw()
borderFrame = psychopy.visual.Rect(
self.experiment_window, lineColor=fg_color, units='deg',
width=self.pursuit_distance*2.1, height=1.5, pos=(0,self.instHeight))
textObject = psychopy.visual.TextStim(
self.experiment_window, text='** Smooth Pursuit Example **', color=fg_color, units='deg',
height=1, pos=(0,self.instHeight+2), **kwargs)
color = self.stim_color
Xposition = [0]
num_frames_per_second = 60
counter = 0
stim_frequency = [0.1]
stim_time = [10]
for freq in stim_frequency:
stim_frames = int(round(stim_time[counter]*num_frames_per_second))
for time in range(stim_frames):
Xposition.append(math.sin(freq*math.radians((time+1)*360/num_frames_per_second))*self.pursuit_distance)
counter += 1
stim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2,
pos=(0,0), fillColor=color,
lineColor=color, units='deg')
keys = None
while keys != ['space']:
for Xpos in Xposition:
textObject.draw()
borderFrame.draw()
stim.pos = (Xpos,self.instHeight)
stim.draw()
self.experiment_window.flip()
keys = psychopy.event.getKeys()
if keys==['space']:
break
return keys
def display_saccade_instructions(
self, anti=False, bg_color=[0,0,0], wait_for_input=True, **kwargs):
bg_color = convert_color_value(bg_color)
fg_color = convert_color_value([255,255,255])
backgroundRect = psychopy.visual.Rect(
self.experiment_window, fillColor=bg_color, units='norm', width=2,
height=2)
backgroundRect.draw()
borderFrame = psychopy.visual.Rect(
self.experiment_window, lineColor=fg_color, units='deg',
width=self.pursuit_distance*2.1, height=3, pos=(0,self.instHeight ))
if anti:
dispText = '** Anti-Saccade Example **'
else:
dispText = '** Saccade Example **'
textObject = psychopy.visual.TextStim(
self.experiment_window, text=dispText, color=fg_color, units='deg',
height=1, pos=(0,self.instHeight+3), **kwargs)
color = self.stim_color
stim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2,
pos=(1,0), fillColor=color,
lineColor=color, units='deg')
#arrowVert = [(-0.8,0.1),(-0.8,-0.1),(-0.4,-0.1),(-0.4,-0.2),(0,0),(-0.4,0.2),(-0.4,0.1)]
arrowVert = numpy.array([(-.25,-2),(.25,-2),(.25,-.75),(.5,-.75),(0,0),(-.5,-.75),(-.25,-.75),(-.25,-2)])
arrowVert = arrowVert + (0,self.instHeight + 5.25)
arrowStim = psychopy.visual.ShapeStim(
self.experiment_window, vertices=arrowVert, fillColor=color, size=0.5, lineColor=color, units='deg')
fixation = psychopy.visual.TextStim(
self.experiment_window, text='+', color=self.saccade_fixation_color,
height=self.fixation_size, units='deg', pos=[0,self.instHeight])
stimList = []
temp = list(range(-self.saccade_distance,self.saccade_distance,1))
for circleN in temp:
if circleN < 0:
tempCoord = circleN
else:
tempCoord = circleN+1
tempStim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2,
pos=[tempCoord,self.instHeight], fillColor=self.saccade_dot_color,
lineColor=self.saccade_dot_color, units='deg')
stimList.append(tempStim)
temp1 = random.sample(range(1,self.saccade_distance+1),self.number_of_saccade_lights)
temp2 = random.sample(range(1,self.saccade_distance+1),self.number_of_saccade_lights)
saccade_locations = [x*-1 for x in temp1] + temp2
keys = None
while keys != ['space']:
for ii in range(4):
if anti:
stim_time = 5;
else:
stim_time = round(random.uniform(1,self.saccade_time),3)
for frameN in range(90):
textObject.draw()
borderFrame.draw()
for s in stimList:
s.draw()
fixation.color = color
fixation.draw()
self.experiment_window.flip()
keys = psychopy.event.getKeys()
if keys==['space']:
break
if keys==['space']:
break
Xpos = random.randint(1,15)*random.choice([-1,1])
for frameN in range(int(round(stim_time*60))):
textObject.draw()
borderFrame.draw()
for s in stimList:
s.draw()
stim.pos = (Xpos,self.instHeight)
stim.draw()
fixation.color=self.saccade_fixation_color
fixation.draw()
if anti and frameN > stim_time*30:
arrowVert2 = arrowVert + (-Xpos*2,0)
arrowStim.vertices = arrowVert2
arrowStim.draw()
self.experiment_window.flip()
keys = psychopy.event.getKeys()
if keys==['space']:
break
if keys==['space']:
break
if keys==['space']:
break
if anti:
textObject.draw()
borderFrame.draw()
for s in stimList:
s.draw()
fixation.color = color
fixation.draw()
self.experiment_window.flip()
keys = psychopy.event.waitKeys();
return keys
def display_rivalry_instructions(
self, anti=False, bg_color=[0,0,0], wait_for_input=True,
image_file=[], image_scale=0.25, **kwargs):
fg_color = convert_color_value([255,255,255])
bg_color = convert_color_value(bg_color)
backgroundRect = psychopy.visual.Rect(
self.experiment_window, fillColor=bg_color, units='norm', width=2,
height=2)
backgroundRect.draw()
textObject = psychopy.visual.TextStim(
self.experiment_window, text='** Binocular Rivalry Example **', color=fg_color, units='deg',
height=1, pos=(0,self.instHeight+2), **kwargs)
color = self.rivalry_border_color
lineSize = self.rivalry_border_width
stimPos = self.experiment_window.size[0]/4
stimPos = psychopy.tools.monitorunittools.pix2deg(stimPos,self.experiment_monitor)
stim1 = psychopy.visual.ImageStim(
self.experiment_window,
image=self.rivalry_file1, pos=(-stimPos,0))
stim1.size = (self.rivalry_width, self.rivalry_height)
stim2 = psychopy.visual.ImageStim(
self.experiment_window,
image=self.rivalry_file2, pos=(stimPos,0))
stim2.size = (self.rivalry_width, self.rivalry_height)
borderScale = stim1.size[0]*0.4
borderWidth1 = stim1.size[0]+borderScale
borderHeight1 = stim1.size[1]+borderScale
borderWidth2 = stim2.size[0]+borderScale
borderHeight2 = stim2.size[1]+borderScale
stimBorder1 = psychopy.visual.Rect(
self.experiment_window, width=borderWidth1,
height=borderHeight1,
pos=stim1.pos, lineWidth=lineSize,
lineColor=color, units='deg')
stimBorder2 = psychopy.visual.Rect(
self.experiment_window, width=borderWidth2,
height=borderHeight2,
pos=stim2.pos, lineWidth=lineSize,
lineColor=color, units='deg')
stimFix1_top = psychopy.visual.Line(
self.experiment_window, start=(stim1.pos[0],stim1.pos[1]+borderHeight1/2),
end=(stim1.pos[0],stim1.pos[1]+stim1.size[1]/1.9), units='deg',
lineColor=color, lineWidth=lineSize)
stimFix1_left = psychopy.visual.Line(
self.experiment_window, start=(stim1.pos[0]-borderWidth1/2,stim1.pos[1]),
end=(stim1.pos[0]-stim1.size[0]/1.9,stim1.pos[1]), units='deg',
lineColor=color, lineWidth=lineSize)
stimFix2_bottom = psychopy.visual.Line(
self.experiment_window, start=(stim2.pos[0],stim2.pos[1]-borderHeight2/2),
end=(stim2.pos[0],stim2.pos[1]-stim2.size[1]/1.9), units='deg',
lineColor=color, lineWidth=lineSize)
stimFix2_right = psychopy.visual.Line(
self.experiment_window, start=(stim2.pos[0]+borderWidth2/2,stim2.pos[1]),
end=(stim2.pos[0]+stim2.size[0]/1.9,stim2.pos[1]), units='deg',
lineColor=color, lineWidth=lineSize)
textObject.draw()
stim1.draw()
stim2.draw()
stimBorder1.draw()
stimBorder2.draw()
stimFix1_top.draw()
stimFix1_left.draw()
stimFix2_bottom.draw()
stimFix2_right.draw()
imageObject = psychopy.visual.ImageStim(
self.experiment_window, units='pix',
image=image_file)
sizex = int(round(imageObject.size[0])*image_scale)
sizey = int(round(imageObject.size[1])*image_scale)
bottomOfScreen = int(math.floor(-self.experiment_window.size[1]/2+sizey/2))+5
imageObject.size = [sizex,sizey]
imageObject.pos = (0,bottomOfScreen)
imageObject.draw()
self.experiment_window.flip()
keys = None
if wait_for_input:
psychopy.core.wait(.2) # Prevents accidental key presses
keys = psychopy.event.waitKeys()
while keys != ['space']:
keys = psychopy.event.waitKeys()
self.experiment_window.flip()
experiment = EyeTrackingSaccadePursuit( experiment = EyeTrackingSaccadePursuit(
experiment_name='ETSP', experiment_name='ETSP',
@ -443,6 +717,7 @@ experiment = EyeTrackingSaccadePursuit(
pursuit_frequencies=pursuit_frequencies, pursuit_frequencies=pursuit_frequencies,
saccade_distance=saccade_distance, saccade_distance=saccade_distance,
saccade_time=saccade_time, saccade_time=saccade_time,
number_of_saccade_lights=number_of_saccade_lights,
saccade_fixation_color=convert_color_value(saccade_fixation_color), saccade_fixation_color=convert_color_value(saccade_fixation_color),
saccade_dot_color = convert_color_value(saccade_dot_color), saccade_dot_color = convert_color_value(saccade_dot_color),
isi_time=isi_time, stimulus_size=stimulus_size, isi_time=isi_time, stimulus_size=stimulus_size,
@ -453,7 +728,8 @@ experiment = EyeTrackingSaccadePursuit(
necker_bg_color=convert_color_value(necker_bg_color), necker_bg_color=convert_color_value(necker_bg_color),
fixation_trial_time=fixation_trial_time, fixation_trial_time=fixation_trial_time,
rivalry_time=rivalry_time, rivalry_time=rivalry_time,
rivalry_scale=rivalry_scale, rivalry_height=rivalry_height,
rivalry_width=rivalry_width,
necker_file=necker_file, necker_file=necker_file,
rivalry_file1=rivalry_file1, rivalry_file1=rivalry_file1,
rivalry_file2=rivalry_file2, rivalry_file2=rivalry_file2,

0
eyelinker.py

28
template.py

@ -13,6 +13,7 @@ convert_color_value -- Converts a list of 3 values from 0 to 255 to -1 to 1.
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from datetime import date
import os import os
import pickle import pickle
@ -135,8 +136,9 @@ class BaseExperiment(object):
fields for the dialog box and output dictionary. fields for the dialog box and output dictionary.
""" """
self.experiment_info = {'Subject Identifier': 'XX00', self.experiment_info = {'Subject ID': '0000',
'Age': '0', 'Session': 'A',
'Timepoint': '0',
'Experimenter Initials': 'MT', 'Experimenter Initials': 'MT',
'Gender': self.gender_options, 'Gender': self.gender_options,
} }
@ -144,8 +146,9 @@ class BaseExperiment(object):
if additional_fields_dict is not None: if additional_fields_dict is not None:
self.experiment_info.update(additional_fields_dict) self.experiment_info.update(additional_fields_dict)
if field_order is None: if field_order is None:
field_order=['Subject Identifier', field_order=['Subject ID',
'Age', 'Session',
'Timepoint',
'Experimenter Initials', 'Experimenter Initials',
'Gender', 'Gender',
] ]
@ -167,9 +170,11 @@ class BaseExperiment(object):
""" """
if filename is None: if filename is None:
filename = (self.experiment_name + '_' + filename = ('ETSP_' + self.experiment_info['Subject ID']
self.experiment_info['Subject Identifier'] + + self.experiment_info['Session']
'_info') + self.experiment_info['Timepoint'] +
'_info')
elif filename[-4:] == '.txt': elif filename[-4:] == '.txt':
filename = filename[:-4] filename = filename[:-4]
@ -190,7 +195,7 @@ class BaseExperiment(object):
with open(filename, 'w') as info_file: with open(filename, 'w') as info_file:
for key, value in self.experiment_info.items(): for key, value in self.experiment_info.items():
info_file.write(key + ':' + str(value) + '\n') info_file.write(key + ':' + str(value) + '\n')
info_file.write('\n') info_file.write('Date: ' + date.today().strftime('%m/%d/%Y') + '\n\n')
def open_csv_data_file(self, data_filename=None): def open_csv_data_file(self, data_filename=None):
"""Opens the csv file and writes the header. """Opens the csv file and writes the header.
@ -201,8 +206,9 @@ class BaseExperiment(object):
""" """
if data_filename is None: if data_filename is None:
data_filename = (self.experiment_name + '_' + data_filename = ('ETSP_' + self.experiment_info['Subject ID']
self.experiment_info['Subject Identifier']) + self.experiment_info['Session']
+ self.experiment_info['Timepoint'])
elif data_filename[-4:] == '.csv': elif data_filename[-4:] == '.csv':
data_filename = data_filename[:-4] data_filename = data_filename[:-4]
@ -355,7 +361,7 @@ class BaseExperiment(object):
wrapWidth=round(.8*self.experiment_window.size[0]), **kwargs) wrapWidth=round(.8*self.experiment_window.size[0]), **kwargs)
#textObject.draw() #textObject.draw()
if image_file: # Display image immediately below text. if image_file: # Display image at bottom of screen.
textObject.pos = (0,self.experiment_window.size[1]/2-5) textObject.pos = (0,self.experiment_window.size[1]/2-5)
textObject.alignVert = 'top' textObject.alignVert = 'top'
textObject.draw() textObject.draw()

Loading…
Cancel
Save