Browse Source

Added a fix for not using a unique filename. Should probably work, but not yet tested. -MT

master
mike 6 years ago
parent
commit
d16d08c959
  1. 302
      SaccadePursuitEyeTracking.py

302
SaccadePursuitEyeTracking.py

@ -28,9 +28,9 @@ import SaccadePursuit
# Experimental Parameters # Experimental Parameters
monitor_name = 'testMonitor' monitor_name = 'testMonitor'
monitor_width = 41 #25.8 height 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 = False # For Debugging disableTracker = False # For Debugging
@ -39,7 +39,7 @@ 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( image_directory = os.path.join(
os.path.expanduser('~'), 'Desktop','SaccadePursuitExperiment','Images') os.path.expanduser('~'), 'Desktop', 'SaccadePursuitExperiment', 'Images')
new_trial_sound = 'A' new_trial_sound = 'A'
instHeight = 6 instHeight = 6
@ -50,28 +50,29 @@ saccade_distance = 15 # Degrees per direction
number_of_saccade_lights = 7 # Number of active lights 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]
saccade_fixation_color = [255,255,255] saccade_fixation_color = [255, 255, 255]
saccade_dot_color = [50,50,50] saccade_dot_color = [50, 50, 50]
antisaccade_instruct_file = os.path.join(image_directory,'AntiSaccadeInstruct2.tif') antisaccade_instruct_file = os.path.join(
image_directory, 'AntiSaccadeInstruct2.tif')
antisaccade_file_scale = 1 antisaccade_file_scale = 1
# Pursuit Parameters # Pursuit Parameters
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.3] pursuit_frequencies = [0.1, 0.2, 0.3]
pursuit_time = [40,20,13.33] pursuit_time = [40, 20, 13.33]
# Necker Cube Parameters # Necker Cube Parameters
number_of_necker_trials = 1 number_of_necker_trials = 1
number_of_necker_blocks = 3 number_of_necker_blocks = 3
necker_time = 60 necker_time = 60
necker_color = [190,190,190] necker_color = [190, 190, 190]
necker_bg_color = [30,30,30] necker_bg_color = [30, 30, 30]
necker_scale = 0.5 necker_scale = 0.5
necker_file = os.path.join(image_directory,'Necker1.tif') necker_file = os.path.join(image_directory, 'Necker1.tif')
necker_response_box_file = os.path.join(image_directory,'ResponseBox5.tif') necker_response_box_file = os.path.join(image_directory, 'ResponseBox5.tif')
necker_response_box_scale = 0.22 necker_response_box_scale = 0.22
# Fixation Parameters # Fixation Parameters
@ -88,11 +89,11 @@ rivalry_time = 90
rivalry_height = 1.5 rivalry_height = 1.5
rivalry_width = 1 rivalry_width = 1
rivalry_distance = 3 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
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
data_fields = [ data_fields = [
@ -112,11 +113,11 @@ questionaire_dict = {
'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': False, # 'Run Necker Cube': False,
'Run Binocular Rivalry': True, 'Run Binocular Rivalry': True,
} }
questionaire_order=[ questionaire_order = [
'Subject ID', 'Subject ID',
'Session', 'Session',
'Timepoint', 'Timepoint',
@ -125,26 +126,26 @@ questionaire_order=[
'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'), ('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.\n\nMove only your eyes.\n'), 'experiment.\n\nMove only your eyes.\n'),
# 'You will be offered rests 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 = (
@ -157,7 +158,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 = (
@ -171,7 +172,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 = (
@ -183,7 +184,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.'
) )
necker_instruct_text = ( necker_instruct_text = (
@ -196,7 +197,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 = (
@ -207,9 +208,10 @@ 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):
"""Converts a list of 3 values from 0 to 255 to -1 to 1. """Converts a list of 3 values from 0 to 255 to -1 to 1.
@ -219,6 +221,7 @@ def convert_color_value(color):
return [round(((n/127.5)-1), 2) for n in color] return [round(((n/127.5)-1), 2) for n in color]
class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): 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
@ -255,23 +258,33 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
if self.tracker: if self.tracker:
fName = os.path.join(self.data_directory, fName = os.path.join(self.data_directory,
self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf') self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf')
fName2 = os.path.join(self.data_directory, baseName = fName2 = os.path.join(self.data_directory,
'ETSP_' + self.experiment_info['Subject ID'] + self.experiment_info['Session'] \ 'ETSP_' +
+ self.experiment_info['Timepoint'] + '.edf') self.experiment_info['Subject ID'] +
self.experiment_info['Session']
+ self.experiment_info['Timepoint'])
fName2 = os.path.join(baseName, '.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(['rename',fName, fName2]) if os.path.exists(fName2):
ii = 1
newName = os.path.join(basename,'(',str(ii),')','.edf')
while os.path.exists(newName):
ii+=1
newName = os.path.join(basename,'(',str(ii),')','.edf')
fName2 = newName
os.rename(fName, fName2) os.rename(fName, fName2)
subprocess.call(['edf2asc',fName2]) subprocess.call(['edf2asc', fName2])
super(EyeTrackingSaccadePursuit, self).quit_experiment() super(EyeTrackingSaccadePursuit, self).quit_experiment()
def run(self): def run(self):
self.chdir() self.chdir()
print('Note: EDF file will be overwritten if identical subject identifiers are used!') print(
'Note: EDF file will be overwritten if identical subject identifiers are used!')
ok = self.get_experiment_info_from_dialog( ok = self.get_experiment_info_from_dialog(
additional_fields_dict=questionaire_dict, additional_fields_dict=questionaire_dict,
field_order=questionaire_order) field_order=questionaire_order)
@ -300,15 +313,16 @@ 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,
self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf', self.experiment_info['Subject ID'] +
self.experiment_info['Timepoint'] + '.edf',
'BOTH' 'BOTH'
) )
self.tracker.initialize_graphics() self.tracker.initialize_graphics()
self.tracker.open_edf() self.tracker.open_edf()
#self.tracker.send_command("add_file_preamble_text 'Saccade Pursuit Experiment Plus Fixation and Necker Cube'")
self.tracker.initialize_tracker() self.tracker.initialize_tracker()
self.tracker.send_calibration_settings( self.tracker.send_calibration_settings(
settings={'preamble_text':'Saccade Pursuit Experiment Plus Fixation and Necker Cube',} settings={
'preamble_text': 'Saccade Pursuit Experiment Plus Fixation and Necker Cube', }
) )
for instruction in self.instruct_text: for instruction in self.instruct_text:
@ -319,7 +333,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.tracker.setup_tracker() self.tracker.setup_tracker()
self.tracker.send_command("track_search_limits=NO") self.tracker.send_command("track_search_limits=NO")
#random.shuffle(conditions) # random.shuffle(conditions)
condition_counter = 0 condition_counter = 0
for condition in conditions: for condition in conditions:
@ -327,35 +341,27 @@ 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_saccade_instructions() 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,
# image_file = antisaccade_instruct_file,
# image_scale = self.antisaccade_file_scale)
self.display_saccade_instructions(anti=True) 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':
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_pursuit_instructions() 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,
# image_file=self.response_box_file,
# image_scale=self.response_box_scale)
self.display_rivalry_instructions( self.display_rivalry_instructions(
image_file=self.response_box_file, image_file=self.response_box_file,
image_scale=self.response_box_scale) image_scale=self.response_box_scale)
@ -366,19 +372,20 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
for block_num in range(numBlocks): for block_num in range(numBlocks):
block = self.make_block(condition, numTrials) block = self.make_block(condition, numTrials)
self.display_text_screen(text='Get ready...', wait_for_input=False) self.display_text_screen(
text='Get ready...', wait_for_input=False)
psychopy.core.wait(2) psychopy.core.wait(2)
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):
printString = ("Condition: %s (%d/%d) Block: %d/%d Trial %d/%d" printString = ("Condition: %s (%d/%d) Block: %d/%d Trial %d/%d"
% (condition,condition_counter,len(conditions), % (condition, condition_counter, len(conditions),
block_num+1,numBlocks,trial_num+1,len(block))) block_num+1, numBlocks, trial_num+1, len(block)))
if condition == 'Saccade' or condition == 'AntiSaccade': if condition == 'Saccade' or condition == 'AntiSaccade':
if trial['locations'][0]>0: if trial['locations'][0] > 0:
printString = printString + " (Right)" printString = printString + " (Right)"
else: else:
printString = printString + " (Left)" printString = printString + " (Left)"
@ -387,52 +394,56 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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)
self.tracker.send_message('TRIAL %d' % trial_num) self.tracker.send_message('TRIAL %d' % trial_num)
self.tracker.send_message('Location: %d,%d' % (trial['locations'][0],trial['locations'][1])) self.tracker.send_message('Location: %d,%d' % (
status = '%s: Block %d, Trial %d' % (condition, block_num, trial_num) trial['locations'][0], trial['locations'][1]))
status = '%s: Block %d, Trial %d' % (
condition, block_num, trial_num)
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: if condition == 'Pursuit' and trial_num == 0:
self.display_fixation(self.fixation_trial_time,self.tracker) self.display_fixation(
data = self.run_trial(trial, block_num, trial_num, self.tracker) self.fixation_trial_time, 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: if condition == 'Pursuit' and trial_num == 0:
self.display_fixation(self.fixation_trial_time,self.tracker) 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:
self.display_break() self.display_break()
if condition == 'Saccade': if condition == 'Saccade':
self.display_text_screen(text='Remember:\n\n' + saccade_instruct_text) self.display_saccade_instructions()
elif condition=='AntiSaccade': elif condition == 'AntiSaccade':
self.display_text_screen(text='Remember:\n\n' + antisaccade_instruct_text, self.display_saccade_instructions(anti=True)
image_file = antisaccade_instruct_file, elif condition == 'Fixation':
image_scale = self.antisaccade_file_scale) self.display_text_screen(
elif condition=='Fixation': text='Prepare for next trial.')
self.display_text_screen(text='Remember:\n\n' + fixation_instruct_text) elif condition == 'Pursuit':
elif condition=='Pursuit': self.display_pursuit_instructions()
self.display_text_screen(text='Remember:\n\n' + pursuit_instruct_text) elif condition == 'Necker':
elif condition=='Necker':
self.display_text_screen(text='Remember:\n\n' + necker_instruct_text, self.display_text_screen(text='Remember:\n\n' + 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)
elif condition=='Rivalry': elif condition == 'Rivalry':
self.display_text_screen(text='Remember:\n\n' + rivalry_instruct_text, self.display_rivalry_instructions(
image_file=self.response_box_file, image_file=self.response_box_file,
image_scale=self.response_box_scale) image_scale=self.response_box_scale)
@ -446,10 +457,10 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.quit_experiment() self.quit_experiment()
def display_pursuit_instructions( def display_pursuit_instructions(
self, bg_color=[0,0,0], wait_for_input=True, **kwargs): self, bg_color=[0, 0, 0], wait_for_input=True, **kwargs):
bg_color = convert_color_value(bg_color) bg_color = convert_color_value(bg_color)
fg_color = convert_color_value([255,255,255]) fg_color = convert_color_value([255, 255, 255])
backgroundRect = psychopy.visual.Rect( backgroundRect = psychopy.visual.Rect(
self.experiment_window, fillColor=bg_color, units='norm', width=2, self.experiment_window, fillColor=bg_color, units='norm', width=2,
@ -458,11 +469,11 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
borderFrame = psychopy.visual.Rect( borderFrame = psychopy.visual.Rect(
self.experiment_window, lineColor=fg_color, units='deg', self.experiment_window, lineColor=fg_color, units='deg',
width=self.pursuit_distance*2.1, height=1.5, pos=(0,self.instHeight)) width=self.pursuit_distance*2.1, height=1.5, pos=(0, self.instHeight))
textObject = psychopy.visual.TextStim( textObject = psychopy.visual.TextStim(
self.experiment_window, text='** Smooth Pursuit Example **', color=fg_color, units='deg', self.experiment_window, text='** Smooth Pursuit Example **', color=fg_color, units='deg',
height=1, pos=(0,self.instHeight+2), **kwargs) height=1, pos=(0, self.instHeight+2), **kwargs)
color = self.stim_color color = self.stim_color
@ -474,12 +485,13 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
for freq in stim_frequency: for freq in stim_frequency:
stim_frames = int(round(stim_time[counter]*num_frames_per_second)) stim_frames = int(round(stim_time[counter]*num_frames_per_second))
for time in range(stim_frames): for time in range(stim_frames):
Xposition.append(math.sin(freq*math.radians((time+1)*360/num_frames_per_second))*self.pursuit_distance) Xposition.append(math.sin(
freq*math.radians((time+1)*360/num_frames_per_second))*self.pursuit_distance)
counter += 1 counter += 1
stim = psychopy.visual.Circle( stim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2, self.experiment_window, radius=self.stimulus_size/2,
pos=(0,0), fillColor=color, pos=(0, 0), fillColor=color,
lineColor=color, units='deg') lineColor=color, units='deg')
keys = None keys = None
@ -487,21 +499,20 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
for Xpos in Xposition: for Xpos in Xposition:
textObject.draw() textObject.draw()
borderFrame.draw() borderFrame.draw()
stim.pos = (Xpos,self.instHeight) stim.pos = (Xpos, self.instHeight)
stim.draw() stim.draw()
self.experiment_window.flip() self.experiment_window.flip()
keys = psychopy.event.getKeys() keys = psychopy.event.getKeys()
if keys==['space']: if keys == ['space']:
break break
return keys return keys
def display_saccade_instructions( def display_saccade_instructions(
self, anti=False, bg_color=[0,0,0], wait_for_input=True, **kwargs): self, anti=False, bg_color=[0, 0, 0], wait_for_input=True, **kwargs):
bg_color = convert_color_value(bg_color) bg_color = convert_color_value(bg_color)
fg_color = convert_color_value([255,255,255]) fg_color = convert_color_value([255, 255, 255])
backgroundRect = psychopy.visual.Rect( backgroundRect = psychopy.visual.Rect(
self.experiment_window, fillColor=bg_color, units='norm', width=2, self.experiment_window, fillColor=bg_color, units='norm', width=2,
@ -510,7 +521,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
borderFrame = psychopy.visual.Rect( borderFrame = psychopy.visual.Rect(
self.experiment_window, lineColor=fg_color, units='deg', self.experiment_window, lineColor=fg_color, units='deg',
width=self.pursuit_distance*2.1, height=3, pos=(0,self.instHeight )) width=self.pursuit_distance*2.1, height=3, pos=(0, self.instHeight))
if anti: if anti:
dispText = '** Anti-Saccade Example **' dispText = '** Anti-Saccade Example **'
@ -519,27 +530,28 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
textObject = psychopy.visual.TextStim( textObject = psychopy.visual.TextStim(
self.experiment_window, text=dispText, color=fg_color, units='deg', self.experiment_window, text=dispText, color=fg_color, units='deg',
height=1, pos=(0,self.instHeight+3), **kwargs) height=1, pos=(0, self.instHeight+3), **kwargs)
color = self.stim_color color = self.stim_color
stim = psychopy.visual.Circle( stim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2, self.experiment_window, radius=self.stimulus_size/2,
pos=(1,0), fillColor=color, pos=(1, 0), fillColor=color,
lineColor=color, units='deg') 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 = [(-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 = numpy.array([(-.25, -2), (.25, -2), (.25, -.75),
arrowVert = arrowVert + (0,self.instHeight + 5.25) (.5, -.75), (0, 0), (-.5, -.75), (-.25, -.75), (-.25, -2)])
arrowVert = arrowVert + (0, self.instHeight + 5.25)
arrowStim = psychopy.visual.ShapeStim( arrowStim = psychopy.visual.ShapeStim(
self.experiment_window, vertices=arrowVert, fillColor=color, size=0.5, lineColor=color, units='deg') self.experiment_window, vertices=arrowVert, fillColor=color, size=0.5, lineColor=color, units='deg')
fixation = psychopy.visual.TextStim( fixation = psychopy.visual.TextStim(
self.experiment_window, text='+', color=self.saccade_fixation_color, self.experiment_window, text='+', color=self.saccade_fixation_color,
height=self.fixation_size, units='deg', pos=[0,self.instHeight]) height=self.fixation_size, units='deg', pos=[0, self.instHeight])
stimList = [] stimList = []
temp = list(range(-self.saccade_distance,self.saccade_distance,1)) temp = list(range(-self.saccade_distance, self.saccade_distance, 1))
for circleN in temp: for circleN in temp:
if circleN < 0: if circleN < 0:
tempCoord = circleN tempCoord = circleN
@ -548,21 +560,23 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
tempStim = psychopy.visual.Circle( tempStim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2, self.experiment_window, radius=self.stimulus_size/2,
pos=[tempCoord,self.instHeight], fillColor=self.saccade_dot_color, pos=[tempCoord, self.instHeight], 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)
temp1 = random.sample(range(1,self.saccade_distance+1),self.number_of_saccade_lights) temp1 = random.sample(
temp2 = random.sample(range(1,self.saccade_distance+1),self.number_of_saccade_lights) 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 saccade_locations = [x*-1 for x in temp1] + temp2
keys = None keys = None
while keys != ['space']: while keys != ['space']:
for ii in range(4): for ii in range(4):
if anti: if anti:
stim_time = 5; stim_time = 5
else: else:
stim_time = round(random.uniform(1,self.saccade_time),3) stim_time = round(random.uniform(1, self.saccade_time), 3)
for frameN in range(90): for frameN in range(90):
textObject.draw() textObject.draw()
borderFrame.draw() borderFrame.draw()
@ -572,32 +586,32 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
fixation.draw() fixation.draw()
self.experiment_window.flip() self.experiment_window.flip()
keys = psychopy.event.getKeys() keys = psychopy.event.getKeys()
if keys==['space']: if keys == ['space']:
break break
if keys==['space']: if keys == ['space']:
break break
Xpos = random.randint(1,15)*random.choice([-1,1]) Xpos = random.randint(1, 15)*random.choice([-1, 1])
for frameN in range(int(round(stim_time*60))): for frameN in range(int(round(stim_time*60))):
textObject.draw() textObject.draw()
borderFrame.draw() borderFrame.draw()
for s in stimList: for s in stimList:
s.draw() s.draw()
stim.pos = (Xpos,self.instHeight) stim.pos = (Xpos, self.instHeight)
stim.draw() stim.draw()
fixation.color=self.saccade_fixation_color fixation.color = self.saccade_fixation_color
fixation.draw() fixation.draw()
if anti and frameN > stim_time*30: if anti and frameN > stim_time*30:
arrowVert2 = arrowVert + (-Xpos*2,0) arrowVert2 = arrowVert + (-Xpos*2, 0)
arrowStim.vertices = arrowVert2 arrowStim.vertices = arrowVert2
arrowStim.draw() arrowStim.draw()
self.experiment_window.flip() self.experiment_window.flip()
keys = psychopy.event.getKeys() keys = psychopy.event.getKeys()
if keys==['space']: if keys == ['space']:
break break
if keys==['space']: if keys == ['space']:
break break
if keys==['space']: if keys == ['space']:
break break
if anti: if anti:
textObject.draw() textObject.draw()
@ -607,15 +621,15 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
fixation.color = color fixation.color = color
fixation.draw() fixation.draw()
self.experiment_window.flip() self.experiment_window.flip()
keys = psychopy.event.waitKeys(); keys = psychopy.event.waitKeys()
return keys return keys
def display_rivalry_instructions( def display_rivalry_instructions(
self, anti=False, bg_color=[0,0,0], wait_for_input=True, self, anti=False, bg_color=[0, 0, 0], wait_for_input=True,
image_file=[], image_scale=0.25, **kwargs): image_file=[], image_scale=0.25, **kwargs):
fg_color = convert_color_value([255,255,255]) fg_color = convert_color_value([255, 255, 255])
bg_color = convert_color_value(bg_color) bg_color = convert_color_value(bg_color)
backgroundRect = psychopy.visual.Rect( backgroundRect = psychopy.visual.Rect(
@ -625,20 +639,21 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
textObject = psychopy.visual.TextStim( textObject = psychopy.visual.TextStim(
self.experiment_window, text='** Binocular Rivalry Example **', color=fg_color, units='deg', self.experiment_window, text='** Binocular Rivalry Example **', color=fg_color, units='deg',
height=1, pos=(0,self.instHeight+2), **kwargs) height=1, pos=(0, self.instHeight+2), **kwargs)
color = self.rivalry_border_color color = self.rivalry_border_color
lineSize = self.rivalry_border_width lineSize = self.rivalry_border_width
stimPos = self.experiment_window.size[0]/4 stimPos = self.experiment_window.size[0]/4
stimPos = psychopy.tools.monitorunittools.pix2deg(stimPos,self.experiment_monitor) 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=(-stimPos,0)) image=self.rivalry_file1, pos=(-stimPos, 0))
stim1.size = (self.rivalry_width, self.rivalry_height) 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=(stimPos,0)) image=self.rivalry_file2, pos=(stimPos, 0))
stim2.size = (self.rivalry_width, self.rivalry_height) stim2.size = (self.rivalry_width, self.rivalry_height)
borderScale = stim1.size[0]*0.4 borderScale = stim1.size[0]*0.4
@ -657,20 +672,24 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
pos=stim2.pos, lineWidth=lineSize, pos=stim2.pos, lineWidth=lineSize,
lineColor=color, units='deg') lineColor=color, units='deg')
stimFix1_top = psychopy.visual.Line( stimFix1_top = psychopy.visual.Line(
self.experiment_window, start=(stim1.pos[0],stim1.pos[1]+borderHeight1/2), self.experiment_window, start=(
end=(stim1.pos[0],stim1.pos[1]+stim1.size[1]/1.9), units='deg', 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) lineColor=color, lineWidth=lineSize)
stimFix1_left = psychopy.visual.Line( stimFix1_left = psychopy.visual.Line(
self.experiment_window, start=(stim1.pos[0]-borderWidth1/2,stim1.pos[1]), self.experiment_window, start=(
end=(stim1.pos[0]-stim1.size[0]/1.9,stim1.pos[1]), units='deg', 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) lineColor=color, lineWidth=lineSize)
stimFix2_bottom = psychopy.visual.Line( stimFix2_bottom = psychopy.visual.Line(
self.experiment_window, start=(stim2.pos[0],stim2.pos[1]-borderHeight2/2), self.experiment_window, start=(
end=(stim2.pos[0],stim2.pos[1]-stim2.size[1]/1.9), units='deg', 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) lineColor=color, lineWidth=lineSize)
stimFix2_right = psychopy.visual.Line( stimFix2_right = psychopy.visual.Line(
self.experiment_window, start=(stim2.pos[0]+borderWidth2/2,stim2.pos[1]), self.experiment_window, start=(
end=(stim2.pos[0]+stim2.size[0]/1.9,stim2.pos[1]), units='deg', 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) lineColor=color, lineWidth=lineSize)
textObject.draw() textObject.draw()
@ -688,9 +707,10 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
image=image_file) image=image_file)
sizex = int(round(imageObject.size[0])*image_scale) sizex = int(round(imageObject.size[0])*image_scale)
sizey = int(round(imageObject.size[1])*image_scale) sizey = int(round(imageObject.size[1])*image_scale)
bottomOfScreen = int(math.floor(-self.experiment_window.size[1]/2+sizey/2))+5 bottomOfScreen = int(
imageObject.size = [sizex,sizey] math.floor(-self.experiment_window.size[1]/2+sizey/2))+5
imageObject.pos = (0,bottomOfScreen) imageObject.size = [sizex, sizey]
imageObject.pos = (0, bottomOfScreen)
imageObject.draw() imageObject.draw()
self.experiment_window.flip() self.experiment_window.flip()
@ -719,7 +739,7 @@ experiment = EyeTrackingSaccadePursuit(
saccade_time=saccade_time, saccade_time=saccade_time,
number_of_saccade_lights=number_of_saccade_lights, 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,
fixation_size=fixation_size, fixation_size=fixation_size,
pursuit_distance=pursuit_distance, pursuit_distance=pursuit_distance,
@ -737,7 +757,7 @@ experiment = EyeTrackingSaccadePursuit(
disableTracker=disableTracker, disableTracker=disableTracker,
rivalry_border_width=rivalry_border_width, rivalry_border_width=rivalry_border_width,
rivalry_distance=rivalry_distance, rivalry_distance=rivalry_distance,
new_trial_sound = new_trial_sound new_trial_sound=new_trial_sound
) )
if __name__ == '__main__': if __name__ == '__main__':

Loading…
Cancel
Save