|
|
|
@ -53,7 +53,8 @@ stimulus_size = 0.3
@@ -53,7 +53,8 @@ stimulus_size = 0.3
|
|
|
|
|
stim_color = [1, -1, -1] |
|
|
|
|
saccade_fixation_color = [255, 255, 255] |
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
# Pursuit Parameters |
|
|
|
@ -210,6 +211,7 @@ rivalry_instruct_text = (
@@ -210,6 +211,7 @@ rivalry_instruct_text = (
|
|
|
|
|
# 'Press any key to continue.' |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def convert_color_value(color): |
|
|
|
|
"""Converts a list of 3 values from 0 to 255 to -1 to 1. |
|
|
|
|
|
|
|
|
@ -219,6 +221,7 @@ def convert_color_value(color):
@@ -219,6 +221,7 @@ def convert_color_value(color):
|
|
|
|
|
|
|
|
|
|
return [round(((n/127.5)-1), 2) for n in color] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): |
|
|
|
|
def __init__(self, **kwargs): |
|
|
|
|
self.quit = False # Needed because eyetracker must shut down |
|
|
|
@ -255,14 +258,23 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -255,14 +258,23 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
if self.tracker: |
|
|
|
|
fName = os.path.join(self.data_directory, |
|
|
|
|
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') |
|
|
|
|
baseName = fName2 = os.path.join(self.data_directory, |
|
|
|
|
'ETSP_' + |
|
|
|
|
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.close_edf() |
|
|
|
|
self.tracker.transfer_edf() |
|
|
|
|
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) |
|
|
|
|
subprocess.call(['edf2asc', fName2]) |
|
|
|
|
|
|
|
|
@ -271,7 +283,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -271,7 +283,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
def run(self): |
|
|
|
|
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( |
|
|
|
|
additional_fields_dict=questionaire_dict, |
|
|
|
|
field_order=questionaire_order) |
|
|
|
@ -300,15 +313,16 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -300,15 +313,16 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
if not self.disableTracker: |
|
|
|
|
self.tracker = eyelinker.EyeLinker( |
|
|
|
|
self.experiment_window, |
|
|
|
|
self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf', |
|
|
|
|
self.experiment_info['Subject ID'] + |
|
|
|
|
self.experiment_info['Timepoint'] + '.edf', |
|
|
|
|
'BOTH' |
|
|
|
|
) |
|
|
|
|
self.tracker.initialize_graphics() |
|
|
|
|
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.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: |
|
|
|
@ -327,14 +341,10 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -327,14 +341,10 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
numBlocks = 1 |
|
|
|
|
numTrials = 1 |
|
|
|
|
if condition == 'Saccade': |
|
|
|
|
# self.display_text_screen(text=saccade_instruct_text) |
|
|
|
|
self.display_saccade_instructions() |
|
|
|
|
numBlocks = self.number_of_saccade_blocks |
|
|
|
|
numTrials = self.number_of_saccade_trials |
|
|
|
|
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) |
|
|
|
|
numBlocks = self.number_of_saccade_blocks |
|
|
|
|
numTrials = self.number_of_saccade_trials |
|
|
|
@ -342,7 +352,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -342,7 +352,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
numBlocks = self.number_of_fixation_blocks |
|
|
|
|
numTrials = self.number_of_fixation_trials |
|
|
|
|
elif condition == 'Pursuit': |
|
|
|
|
# self.display_text_screen(text=pursuit_instruct_text) |
|
|
|
|
self.display_pursuit_instructions() |
|
|
|
|
numBlocks = self.number_of_pursuit_blocks |
|
|
|
|
numTrials = self.number_of_pursuit_trials |
|
|
|
@ -353,9 +362,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -353,9 +362,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
numBlocks = self.number_of_necker_blocks |
|
|
|
|
numTrials = self.number_of_necker_trials |
|
|
|
|
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( |
|
|
|
|
image_file=self.response_box_file, |
|
|
|
|
image_scale=self.response_box_scale) |
|
|
|
@ -366,7 +372,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -366,7 +372,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
|
|
|
|
|
for block_num in range(numBlocks): |
|
|
|
|
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) |
|
|
|
|
if condition == 'Saccade' or condition == 'AntiSaccade': |
|
|
|
|
self.display_saccade_fixation(1) |
|
|
|
@ -387,19 +394,24 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -387,19 +394,24 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
self.tracker.send_message('CONDITION %s' % condition) |
|
|
|
|
self.tracker.send_message('BLOCK %d' % block_num) |
|
|
|
|
self.tracker.send_message('TRIAL %d' % trial_num) |
|
|
|
|
self.tracker.send_message('Location: %d,%d' % (trial['locations'][0],trial['locations'][1])) |
|
|
|
|
status = '%s: Block %d, Trial %d' % (condition, block_num, trial_num) |
|
|
|
|
self.tracker.send_message('Location: %d,%d' % ( |
|
|
|
|
trial['locations'][0], trial['locations'][1])) |
|
|
|
|
status = '%s: Block %d, Trial %d' % ( |
|
|
|
|
condition, block_num, trial_num) |
|
|
|
|
self.tracker.send_status(status) |
|
|
|
|
# psychopy.sound.Sound('C').play() |
|
|
|
|
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) |
|
|
|
|
self.display_fixation( |
|
|
|
|
self.fixation_trial_time, self.tracker) |
|
|
|
|
data = self.run_trial( |
|
|
|
|
trial, block_num, trial_num, self.tracker) |
|
|
|
|
self.tracker.stop_recording() |
|
|
|
|
# psychopy.sound.Sound('C').play() |
|
|
|
|
else: |
|
|
|
|
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.update({'Condition': condition}) |
|
|
|
|
self.send_data(data) |
|
|
|
@ -418,21 +430,20 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -418,21 +430,20 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
self.display_break() |
|
|
|
|
|
|
|
|
|
if condition == 'Saccade': |
|
|
|
|
self.display_text_screen(text='Remember:\n\n' + saccade_instruct_text) |
|
|
|
|
self.display_saccade_instructions() |
|
|
|
|
elif condition == 'AntiSaccade': |
|
|
|
|
self.display_text_screen(text='Remember:\n\n' + antisaccade_instruct_text, |
|
|
|
|
image_file = antisaccade_instruct_file, |
|
|
|
|
image_scale = self.antisaccade_file_scale) |
|
|
|
|
self.display_saccade_instructions(anti=True) |
|
|
|
|
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': |
|
|
|
|
self.display_text_screen(text='Remember:\n\n' + pursuit_instruct_text) |
|
|
|
|
self.display_pursuit_instructions() |
|
|
|
|
elif condition == 'Necker': |
|
|
|
|
self.display_text_screen(text='Remember:\n\n' + necker_instruct_text, |
|
|
|
|
image_file=self.necker_response_box_file, |
|
|
|
|
image_scale=self.necker_response_box_scale) |
|
|
|
|
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_scale=self.response_box_scale) |
|
|
|
|
|
|
|
|
@ -474,7 +485,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -474,7 +485,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
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) |
|
|
|
|
Xposition.append(math.sin( |
|
|
|
|
freq*math.radians((time+1)*360/num_frames_per_second))*self.pursuit_distance) |
|
|
|
|
counter += 1 |
|
|
|
|
|
|
|
|
|
stim = psychopy.visual.Circle( |
|
|
|
@ -494,7 +506,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -494,7 +506,6 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
if keys == ['space']: |
|
|
|
|
break |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return keys |
|
|
|
|
|
|
|
|
|
def display_saccade_instructions( |
|
|
|
@ -529,7 +540,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -529,7 +540,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
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 = 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') |
|
|
|
@ -552,15 +564,17 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -552,15 +564,17 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
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) |
|
|
|
|
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; |
|
|
|
|
stim_time = 5 |
|
|
|
|
else: |
|
|
|
|
stim_time = round(random.uniform(1, self.saccade_time), 3) |
|
|
|
|
for frameN in range(90): |
|
|
|
@ -607,7 +621,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -607,7 +621,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
fixation.color = color |
|
|
|
|
fixation.draw() |
|
|
|
|
self.experiment_window.flip() |
|
|
|
|
keys = psychopy.event.waitKeys(); |
|
|
|
|
keys = psychopy.event.waitKeys() |
|
|
|
|
|
|
|
|
|
return keys |
|
|
|
|
|
|
|
|
@ -631,7 +645,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -631,7 +645,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
lineSize = self.rivalry_border_width |
|
|
|
|
|
|
|
|
|
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( |
|
|
|
|
self.experiment_window, |
|
|
|
|
image=self.rivalry_file1, pos=(-stimPos, 0)) |
|
|
|
@ -657,19 +672,23 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -657,19 +672,23 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
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), |
|
|
|
|
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]), |
|
|
|
|
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), |
|
|
|
|
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]), |
|
|
|
|
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) |
|
|
|
|
|
|
|
|
@ -688,7 +707,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
@@ -688,7 +707,8 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
|
|
|
|
|
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 |
|
|
|
|
bottomOfScreen = int( |
|
|
|
|
math.floor(-self.experiment_window.size[1]/2+sizey/2))+5 |
|
|
|
|
imageObject.size = [sizex, sizey] |
|
|
|
|
imageObject.pos = (0, bottomOfScreen) |
|
|
|
|
imageObject.draw() |
|
|
|
|