Browse Source

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

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

106
SaccadePursuit.py

@ -71,12 +71,14 @@ class SPtask(template.BaseExperiment): @@ -71,12 +71,14 @@ class SPtask(template.BaseExperiment):
stim_color, pursuit_frequencies,
saccade_distance, saccade_time,
stimulus_size, saccade_fixation_color,
number_of_saccade_lights,
fixation_size, pursuit_distance,
necker_time, necker_color,
necker_scale, necker_bg_color,
necker_file, rivalry_file1, rivalry_file2,
fixation_trial_time, rivalry_time,
rivalry_scale,rivalry_border_color,
rivalry_height, rivalry_width,
rivalry_border_color,
rivalry_border_width, rivalry_distance,
new_trial_sound,
questionaire_dict=None,
@ -84,33 +86,35 @@ class SPtask(template.BaseExperiment): @@ -84,33 +86,35 @@ class SPtask(template.BaseExperiment):
**kwargs):
self.new_trial_sound = new_trial_sound
# Pursuit
self.pursuit_time = pursuit_time
self.pursuit_distance = pursuit_distance
self.pursuit_frequencies = pursuit_frequencies
# Saccade
self.stim_color = stim_color
self.saccade_time = saccade_time
self.stimulus_size = stimulus_size
self.saccade_distance = saccade_distance
self.saccade_fixation_color = saccade_fixation_color
self.number_of_saccade_lights = number_of_saccade_lights
# Fixation
self.fixation_size = fixation_size
self.fixation_trial_time = fixation_trial_time
# Necker
self.necker_time = necker_time
self.necker_color = necker_color
self.necker_scale = necker_scale
self.necker_bg_color = necker_bg_color
self.necker_file = necker_file
# Rivalry
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_file2 = rivalry_file2
self.rivalry_border_color = rivalry_border_color
@ -118,7 +122,7 @@ class SPtask(template.BaseExperiment): @@ -118,7 +122,7 @@ class SPtask(template.BaseExperiment):
self.rivalry_distance = rivalry_distance
self.questionaire_dict = questionaire_dict
super(SPtask, self).__init__(**kwargs)
def chdir(self):
@ -140,12 +144,16 @@ class SPtask(template.BaseExperiment): @@ -140,12 +144,16 @@ class SPtask(template.BaseExperiment):
"""
trial_list = []
saccade_locations = list(range(-self.saccade_distance,0,1))
for x in range(self.saccade_distance):
saccade_locations.append(x+1)
random.shuffle(saccade_locations)
#saccade_locations = list(range(-self.saccade_distance,0,1))
#for x in range(self.saccade_distance):
# saccade_locations.append(x+1)
#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
for num_trials in range(numTrials):
if condition == 'Pursuit':
@ -184,7 +192,7 @@ class SPtask(template.BaseExperiment): @@ -184,7 +192,7 @@ class SPtask(template.BaseExperiment):
trial_type -- Whether this trial is same or different.
"""
locs = [pursuit_frequency,0]
trial = {
'locations': locs,
'trial_time': trial_time,
@ -201,18 +209,21 @@ class SPtask(template.BaseExperiment): @@ -201,18 +209,21 @@ class SPtask(template.BaseExperiment):
break_text = 'Please take a short break. Press any key to continue.'
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.
Parameters:
wait_time -- The amount of time the fixation should be displayed for.
"""
self.experiment_window.color = necker_bg_color
stim = psychopy.visual.TextStim(
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))):
stim.draw()
self.experiment_window.flip()
@ -225,9 +236,9 @@ class SPtask(template.BaseExperiment): @@ -225,9 +236,9 @@ class SPtask(template.BaseExperiment):
should be displayed.
colors -- A list of colors describing what should be drawn at each coordinate.
"""
color = self.stim_color
stim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2,
pos=coordinates, fillColor=color,
@ -235,7 +246,7 @@ class SPtask(template.BaseExperiment): @@ -235,7 +246,7 @@ class SPtask(template.BaseExperiment):
fixation = psychopy.visual.TextStim(
self.experiment_window, text='+', color=self.saccade_fixation_color,
height=self.fixation_size, units='deg')
stimList = []
temp = list(range(-self.saccade_distance,self.saccade_distance,1))
for circleN in temp:
@ -243,14 +254,14 @@ class SPtask(template.BaseExperiment): @@ -243,14 +254,14 @@ class SPtask(template.BaseExperiment):
tempCoord = circleN
else:
tempCoord = circleN+1
tempStim = psychopy.visual.Circle(
self.experiment_window, radius=self.stimulus_size/2,
pos=[tempCoord,0], fillColor=self.saccade_dot_color,
lineColor=self.saccade_dot_color, units='deg')
stimList.append(tempStim)
tracker.send_message('Start Stim')
if tracker:
tracker.send_message('Start Stim')
for frameN in range(int(round(stim_time*60))):
for s in stimList:
s.draw()
@ -258,7 +269,8 @@ class SPtask(template.BaseExperiment): @@ -258,7 +269,8 @@ class SPtask(template.BaseExperiment):
stim.draw()
self.experiment_window.flip()
#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):
"""Displays the stimuli. A helper function for self.run_saccade_trial.
@ -268,11 +280,11 @@ class SPtask(template.BaseExperiment): @@ -268,11 +280,11 @@ class SPtask(template.BaseExperiment):
should be displayed.
colors -- A list of colors describing what should be drawn at each coordinate.
"""
fixation = psychopy.visual.TextStim(
self.experiment_window, text='+', color=self.stim_color,
height=self.fixation_size, units='deg')
stimList = []
temp = list(range(-self.saccade_distance,self.saccade_distance,1))
for circleN in temp:
@ -285,14 +297,14 @@ class SPtask(template.BaseExperiment): @@ -285,14 +297,14 @@ class SPtask(template.BaseExperiment):
pos=[tempCoord,0], fillColor=self.saccade_dot_color,
lineColor=self.saccade_dot_color, units='deg')
stimList.append(tempStim)
for frameN in range(int(round(stim_time*60))):
for s in stimList:
s.draw()
fixation.draw()
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.
Parameters:
@ -300,9 +312,9 @@ class SPtask(template.BaseExperiment): @@ -300,9 +312,9 @@ class SPtask(template.BaseExperiment):
point of the stimulus.
color -- A color describing what should be drawn.
"""
color = self.stim_color
Xposition = [0]
num_frames_per_second = 60
counter = 0
@ -315,7 +327,7 @@ class SPtask(template.BaseExperiment): @@ -315,7 +327,7 @@ class SPtask(template.BaseExperiment):
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,
@ -325,6 +337,9 @@ class SPtask(template.BaseExperiment): @@ -325,6 +337,9 @@ class SPtask(template.BaseExperiment):
stim.draw()
self.experiment_window.flip()
if tracker:
tracker.send_message('Start Stim')
for Xpos in Xposition:
stim.pos = (Xpos,0)
stim.draw()
@ -344,6 +359,8 @@ class SPtask(template.BaseExperiment): @@ -344,6 +359,8 @@ class SPtask(template.BaseExperiment):
stim.size *= self.necker_scale
stim.setColor(self.necker_color, 'rgb255')
responses = []
if tracker:
tracker.send_message('Start Stim')
for frameN in range(stim_time*60):
response = psychopy.event.getKeys()
if response:
@ -365,16 +382,17 @@ class SPtask(template.BaseExperiment): @@ -365,16 +382,17 @@ class SPtask(template.BaseExperiment):
def display_rivalry(self, stim_time, tracker):
color = self.rivalry_border_color
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(
self.experiment_window,
image=self.rivalry_file1, pos=(-imDist,0))
stim1.size *= self.rivalry_scale
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=(imDist,0))
stim2.size *= self.rivalry_scale
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
@ -408,6 +426,8 @@ class SPtask(template.BaseExperiment): @@ -408,6 +426,8 @@ class SPtask(template.BaseExperiment):
lineColor=color, lineWidth=lineSize)
responses = []
if tracker:
tracker.send_message('Start Stim')
for frameN in range(stim_time*60):
response = psychopy.event.getKeys()
if response:
@ -447,19 +467,19 @@ class SPtask(template.BaseExperiment): @@ -447,19 +467,19 @@ class SPtask(template.BaseExperiment):
if trial['trial_type']=='Necker':
freq = self.display_necker(trial['trial_time'], tracker)
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()
freq = trial['pursuit_frequency']
elif trial['trial_type']=='Fixation':
self.display_fixation(trial['trial_time'])
self.display_fixation(trial['trial_time'],tracker)
elif trial['trial_type']=='Rivalry':
freq = self.display_rivalry(trial['trial_time'], tracker)
else:
self.display_saccade(trial['locations'], trial['trial_time'], tracker)
psychopy.sound.Sound(self.new_trial_sound).play()
data = {
'Subject': self.experiment_info['Subject Identifier'],
'Subject': self.experiment_info['Subject ID'],
'Block': block_num,
'Trial': trial_num,
'Timestamp': psychopy.core.getAbsTime(),
@ -475,6 +495,6 @@ class SPtask(template.BaseExperiment): @@ -475,6 +495,6 @@ class SPtask(template.BaseExperiment):
# If you call this script directly, directs you to correct file
if __name__ == '__main__':
warnings.showwarning(
'Please run SaccadePursuitEyeTracking.py',
'Please run SaccadePursuitEyeTracking.py',
Warning,'SaccadePursuit.py',414)
warnings.formatwarning = warning_on_one_line

430
SaccadePursuitEyeTracking.py

@ -16,6 +16,8 @@ import random @@ -16,6 +16,8 @@ import random
import sys
import traceback
import subprocess
import math
import numpy
# Necesssary to access psychopy paths
import psychopy # noqa:F401
@ -26,22 +28,26 @@ import SaccadePursuit @@ -26,22 +28,26 @@ import SaccadePursuit
# Experimental Parameters
monitor_name = 'testMonitor'
monitor_width = 41
monitor_width = 41 #25.8 height
distance_to_monitor = 74
monitor_px = [1440,900]
window_screen = 1
disableTracker = True # For Debugging
disableTracker = False # For Debugging
isi_time = 2 # Interstimulus Interval
data_directory = os.path.join(
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'
instHeight = 6
# Saccade / Antisaccade Parameters
number_of_saccade_trials = 1
number_of_saccade_blocks = 1
saccade_distance = 15 # Degrees per direction
number_of_saccade_lights = 7 # Number of active lights per direction
saccade_time = 3 # Maximum Time
stimulus_size = 0.3
stim_color = [1,-1,-1]
@ -54,8 +60,8 @@ antisaccade_file_scale = 1 @@ -54,8 +60,8 @@ antisaccade_file_scale = 1
number_of_pursuit_trials = 1
number_of_pursuit_blocks = 1
pursuit_distance = 15
pursuit_frequencies = [0.1,0.2,0.4]
pursuit_time = [40,20,15]
pursuit_frequencies = [0.1,0.2,0.3]
pursuit_time = [40,20,13.33]
# Necker Cube Parameters
number_of_necker_trials = 1
@ -78,12 +84,14 @@ fixation_trial_time = 15 @@ -78,12 +84,14 @@ fixation_trial_time = 15
number_of_rivalry_trials = 1
number_of_rivalry_blocks = 1
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_file2 = os.path.join(image_directory,'face2nS_11-160.tif')
rivalry_border_color = [190,190,190]
rivalry_border_width = 5
rivalry_distance = 4
response_box_file = os.path.join(image_directory,'ResponseBox3.tif')
response_box_scale = 0.22
@ -101,43 +109,42 @@ data_fields = [ @@ -101,43 +109,42 @@ data_fields = [
# Add additional questions here
questionaire_dict = {
'Run Fixation': True,
'Run Smooth Pursuit': True,
'Run Saccade': True,
'Run Anti-Saccade': True,
'Run Necker Cube': True,
'Run Binocular Rivalry': False,
# 'Run Necker Cube': False,
'Run Binocular Rivalry': True,
}
questionaire_order=[
'Subject Identifier',
'Age',
'Subject ID',
'Session',
'Timepoint',
'Experimenter Initials',
'Gender',
'Run Fixation',
'Run Smooth Pursuit',
'Run Saccade',
'Run Anti-Saccade',
'Run Necker Cube',
# 'Run Necker Cube',
'Run Binocular Rivalry',
]
instruct_text = [
('Welcome to the experiment. Press any key to continue.'),
('In this experiment you will be following targets.\n\n'
'Each trial will start with a fixation cross. '
'Focus on the fixation cross until a stimulus appears.\n\n'
'In the first three phases, you will follow the stimuli. '
'In the fourth phase, you will focus on the '
'opposite side of center cross at an '
'equal distance as the stimulus. In the fifth '
'phase, you will see a cube, and are to respond as '
'indicated.'
'\n\n'
('Welcome to the experiment'),
(#'In this experiment you will be following targets.\n\n'
# 'Each trial will start with a fixation cross. '
# 'Focus on the fixation cross until a stimulus appears.\n\n'
# 'In the first three phases, you will follow the stimuli. '
# 'In the fourth phase, you will focus on the '
# 'opposite side of center cross at an '
# 'equal distance as the stimulus. In the fifth '
# 'phase, you will see a cube, and are to respond as '
# 'indicated.'
# '\n\n'
'Do not move your head during the trials of this '
'experiment. Move only your eyes to follow the targets.'
'You will be offered breaks in between sections.\n\n'
'Press any key to continue.'),
'experiment.\n\nMove only your eyes.\n'),
# 'You will be offered rests between sections.\n\n'
# 'Press any key to continue.'),
]
saccade_instruct_text = (
@ -150,7 +157,7 @@ saccade_instruct_text = ( @@ -150,7 +157,7 @@ saccade_instruct_text = (
'move your eyes back to the fixation cross.\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'
'Press any key to continue.'
# 'Press any key to continue.'
)
antisaccade_instruct_text = (
@ -164,7 +171,7 @@ antisaccade_instruct_text = ( @@ -164,7 +171,7 @@ antisaccade_instruct_text = (
'to the fixation point after each target disappears.\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'
'Press any key to continue.'
# 'Press any key to continue.'
)
pursuit_instruct_text = (
@ -176,17 +183,7 @@ pursuit_instruct_text = ( @@ -176,17 +183,7 @@ pursuit_instruct_text = (
'two seconds.\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'
'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.'
# 'Press any key to continue.'
)
necker_instruct_text = (
@ -199,7 +196,7 @@ necker_instruct_text = ( @@ -199,7 +196,7 @@ necker_instruct_text = (
'Try not to blink after the cube appears.\n\n'
'You can blink or close your eyes to rest after the cube '
'disappears.\n\n'
'Press any key to continue.'
# 'Press any key to continue.'
)
rivalry_instruct_text = (
@ -210,7 +207,7 @@ rivalry_instruct_text = ( @@ -210,7 +207,7 @@ rivalry_instruct_text = (
'the face and house, press the center button.\n\n'
'You can blink or close your eyes to rest for a few seconds '
'after the pictures disappear.\n\n'
'Press any key to continue.'
# 'Press any key to continue.'
)
def convert_color_value(color):
@ -226,12 +223,13 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -226,12 +223,13 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
def __init__(self, **kwargs):
self.quit = False # Needed because eyetracker must shut down
self.tracker = None
self.disable_tracker = disableTracker
self.disableTracker = disableTracker
self.window_screen = window_screen
self.monitor_px = monitor_px
self.number_of_saccade_trials = number_of_saccade_trials
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_blocks = number_of_pursuit_blocks
self.number_of_necker_trials = number_of_necker_trials
@ -246,6 +244,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -246,6 +244,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.response_box_scale = response_box_scale
self.antisaccade_instruct_file = antisaccade_instruct_file
self.antisaccade_file_scale = antisaccade_file_scale
self.instHeight = instHeight
super(EyeTrackingSaccadePursuit, self).__init__(**kwargs)
@ -255,12 +254,18 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -255,12 +254,18 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
self.display_text_screen('Quiting...', wait_for_input=False)
if self.tracker:
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.close_edf()
self.tracker.transfer_edf()
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()
def run(self):
@ -268,7 +273,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -268,7 +273,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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,
additional_fields_dict=questionaire_dict,
field_order=questionaire_order)
if not ok:
@ -276,16 +281,14 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -276,16 +281,14 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
sys.exit(1)
conditions = []
if self.experiment_info['Run Fixation']:
conditions.append('Fixation')
if self.experiment_info['Run Smooth Pursuit']:
conditions.append('Pursuit')
if self.experiment_info['Run Saccade']:
conditions.append('Saccade')
if self.experiment_info['Run Anti-Saccade']:
conditions.append('AntiSaccade')
if self.experiment_info['Run Necker Cube']:
conditions.append('Necker')
# if self.experiment_info['Run Necker Cube']:
# conditions.append('Necker')
if self.experiment_info['Run Binocular Rivalry']:
conditions.append('Rivalry')
@ -297,7 +300,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -297,7 +300,7 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
if not self.disableTracker:
self.tracker = eyelinker.EyeLinker(
self.experiment_window,
'ETSP' + self.experiment_info['Subject Identifier'] + '.edf',
self.experiment_info['Subject ID'] + self.experiment_info['Timepoint'] + '.edf',
'BOTH'
)
self.tracker.initialize_graphics()
@ -310,12 +313,12 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -310,12 +313,12 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
for instruction in self.instruct_text:
self.display_text_screen(text=instruction)
if not self.disableTracker:
self.tracker.display_eyetracking_instructions()
self.tracker.setup_tracker()
self.tracker.send_command("track_search_limits=NO")
#random.shuffle(conditions)
condition_counter = 0
@ -324,33 +327,38 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -324,33 +327,38 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
numBlocks = 1
numTrials = 1
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
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_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
elif condition=='Fixation':
self.display_text_screen(text=fixation_instruct_text)
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_text_screen(text=pursuit_instruct_text)
self.display_pursuit_instructions()
numBlocks = self.number_of_pursuit_blocks
numTrials = self.number_of_pursuit_trials
elif condition=='Necker':
self.display_text_screen(text=necker_instruct_text,
image_file=self.necker_response_box_file,
image_scale=self.necker_response_box_scale)
self.display_text_screen(text=necker_instruct_text,
image_file=self.necker_response_box_file,
image_scale=self.necker_response_box_scale)
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_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)
numBlocks = self.number_of_rivalry_blocks
numTrials = self.number_of_rivalry_trials
else:
@ -363,14 +371,18 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -363,14 +371,18 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
if condition == 'Saccade' or condition == 'AntiSaccade':
self.display_saccade_fixation(1)
else:
self.display_fixation(0.5)
self.display_fixation(0.5,[])
for trial_num, trial in enumerate(block):
print(
"Condition: ",condition,"(",condition_counter,"/",len(conditions),")",
"Block ",block_num+1,"/",numBlocks,
" Trial ",trial_num+1,"/",len(block)
)
printString = ("Condition: %s (%d/%d) Block: %d/%d Trial %d/%d"
% (condition,condition_counter,len(conditions),
block_num+1,numBlocks,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:
self.tracker.send_message('CONDITION %s' % condition)
self.tracker.send_message('BLOCK %d' % block_num)
@ -380,22 +392,26 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -380,22 +392,26 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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.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)
data = self.run_trial(trial, block_num, trial_num)
data.update({'Condition': condition})
self.send_data(data)
if condition == 'Saccade' or condition=='AntiSaccade':
self.display_saccade_fixation(self.isi_time)
else:
self.display_fixation(self.isi_time)
self.display_fixation(self.isi_time,[])
if condition == 'Saccade' or condition == 'AntiSaccade':
self.display_saccade_fixation(1)
else:
self.display_fixation(0.5)
self.display_fixation(0.5,[])
self.save_data_to_csv()
if block_num + 1 != numBlocks:
@ -429,6 +445,264 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask): @@ -429,6 +445,264 @@ class EyeTrackingSaccadePursuit(SaccadePursuit.SPtask):
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_name='ETSP',
@ -443,6 +717,7 @@ experiment = EyeTrackingSaccadePursuit( @@ -443,6 +717,7 @@ experiment = EyeTrackingSaccadePursuit(
pursuit_frequencies=pursuit_frequencies,
saccade_distance=saccade_distance,
saccade_time=saccade_time,
number_of_saccade_lights=number_of_saccade_lights,
saccade_fixation_color=convert_color_value(saccade_fixation_color),
saccade_dot_color = convert_color_value(saccade_dot_color),
isi_time=isi_time, stimulus_size=stimulus_size,
@ -453,7 +728,8 @@ experiment = EyeTrackingSaccadePursuit( @@ -453,7 +728,8 @@ experiment = EyeTrackingSaccadePursuit(
necker_bg_color=convert_color_value(necker_bg_color),
fixation_trial_time=fixation_trial_time,
rivalry_time=rivalry_time,
rivalry_scale=rivalry_scale,
rivalry_height=rivalry_height,
rivalry_width=rivalry_width,
necker_file=necker_file,
rivalry_file1=rivalry_file1,
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. @@ -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 print_function
from datetime import date
import os
import pickle
@ -135,8 +136,9 @@ class BaseExperiment(object): @@ -135,8 +136,9 @@ class BaseExperiment(object):
fields for the dialog box and output dictionary.
"""
self.experiment_info = {'Subject Identifier': 'XX00',
'Age': '0',
self.experiment_info = {'Subject ID': '0000',
'Session': 'A',
'Timepoint': '0',
'Experimenter Initials': 'MT',
'Gender': self.gender_options,
}
@ -144,8 +146,9 @@ class BaseExperiment(object): @@ -144,8 +146,9 @@ class BaseExperiment(object):
if additional_fields_dict is not None:
self.experiment_info.update(additional_fields_dict)
if field_order is None:
field_order=['Subject Identifier',
'Age',
field_order=['Subject ID',
'Session',
'Timepoint',
'Experimenter Initials',
'Gender',
]
@ -167,9 +170,11 @@ class BaseExperiment(object): @@ -167,9 +170,11 @@ class BaseExperiment(object):
"""
if filename is None:
filename = (self.experiment_name + '_' +
self.experiment_info['Subject Identifier'] +
'_info')
filename = ('ETSP_' + self.experiment_info['Subject ID']
+ self.experiment_info['Session']
+ self.experiment_info['Timepoint'] +
'_info')
elif filename[-4:] == '.txt':
filename = filename[:-4]
@ -190,7 +195,7 @@ class BaseExperiment(object): @@ -190,7 +195,7 @@ class BaseExperiment(object):
with open(filename, 'w') as info_file:
for key, value in self.experiment_info.items():
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):
"""Opens the csv file and writes the header.
@ -201,8 +206,9 @@ class BaseExperiment(object): @@ -201,8 +206,9 @@ class BaseExperiment(object):
"""
if data_filename is None:
data_filename = (self.experiment_name + '_' +
self.experiment_info['Subject Identifier'])
data_filename = ('ETSP_' + self.experiment_info['Subject ID']
+ self.experiment_info['Session']
+ self.experiment_info['Timepoint'])
elif data_filename[-4:] == '.csv':
data_filename = data_filename[:-4]
@ -355,7 +361,7 @@ class BaseExperiment(object): @@ -355,7 +361,7 @@ class BaseExperiment(object):
wrapWidth=round(.8*self.experiment_window.size[0]), **kwargs)
#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.alignVert = 'top'
textObject.draw()

Loading…
Cancel
Save