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. 106
      SaccadePursuitEyeTracking.py

106
SaccadePursuitEyeTracking.py

@ -53,7 +53,8 @@ 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
@ -210,6 +211,7 @@ rivalry_instruct_text = (
# '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,14 +258,23 @@ 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])
@ -271,7 +283,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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:
@ -327,14 +341,10 @@ 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
@ -342,7 +352,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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
@ -353,9 +362,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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,7 +372,8 @@ 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)
@ -387,19 +394,24 @@ 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)
@ -418,21 +430,20 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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,
image_scale = self.antisaccade_file_scale)
elif condition == 'Fixation': elif condition == 'Fixation':
self.display_text_screen(text='Remember:\n\n' + fixation_instruct_text) self.display_text_screen(
text='Prepare for next trial.')
elif condition == 'Pursuit': elif condition == 'Pursuit':
self.display_text_screen(text='Remember:\n\n' + pursuit_instruct_text) self.display_pursuit_instructions()
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)
@ -474,7 +485,8 @@ 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(
@ -494,7 +506,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
if keys == ['space']: if keys == ['space']:
break break
return keys return keys
def display_saccade_instructions( def display_saccade_instructions(
@ -529,7 +540,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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),
(.5, -.75), (0, 0), (-.5, -.75), (-.25, -.75), (-.25, -2)])
arrowVert = arrowVert + (0, self.instHeight + 5.25) 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')
@ -552,15 +564,17 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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):
@ -607,7 +621,7 @@ 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
@ -631,7 +645,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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))
@ -657,19 +672,23 @@ 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=(
stim1.pos[0], stim1.pos[1]+borderHeight1/2),
end=(stim1.pos[0], stim1.pos[1]+stim1.size[1]/1.9), units='deg', 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=(
stim1.pos[0]-borderWidth1/2, stim1.pos[1]),
end=(stim1.pos[0]-stim1.size[0]/1.9, stim1.pos[1]), units='deg', 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=(
stim2.pos[0], stim2.pos[1]-borderHeight2/2),
end=(stim2.pos[0], stim2.pos[1]-stim2.size[1]/1.9), units='deg', 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=(
stim2.pos[0]+borderWidth2/2, stim2.pos[1]),
end=(stim2.pos[0]+stim2.size[0]/1.9, stim2.pos[1]), units='deg', end=(stim2.pos[0]+stim2.size[0]/1.9, stim2.pos[1]), units='deg',
lineColor=color, lineWidth=lineSize) lineColor=color, lineWidth=lineSize)
@ -688,7 +707,8 @@ 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(
math.floor(-self.experiment_window.size[1]/2+sizey/2))+5
imageObject.size = [sizex, sizey] imageObject.size = [sizex, sizey]
imageObject.pos = (0, bottomOfScreen) imageObject.pos = (0, bottomOfScreen)
imageObject.draw() imageObject.draw()

Loading…
Cancel
Save