def __init__(self, tracker, win, settings): """ Initializes PsychopyCustomDisplay object. """ super().__init__() self.tracker = tracker self.win = win self.settings = settings # from session self.txtcol = -1 #self.__target_beep__ = sound.Sound(800, secs=.1) # THIS WILL GIVE A SEGFAULT! #self.__target_beep__done__ = sound.Sound(1200, secs=.1) # THIS WILL GIVE A SEGFAULT! #self.__target_beep__error__ = sound.Sound(400, secs=.1) # THIS WILL GIVE A SEGFAULT! self.backcolor = self.win.color dot_size_pix = misc.deg2pix( self.settings['eyetracker'].get('dot_size'), self.win.monitor) self.targetout = Circle(self.win, pos=(0, 0), radius=dot_size_pix, fillColor='black', units='pix', lineColor='black') self.targetin = Circle(self.win, pos=(0, 0), radius=3, fillColor=0, lineColor=0, units='pix', opacity=0) win.flip()
def make_points(self): self.outer_point = Circle(self, radius=25) self.outer_point.fillColor = 'white' self.outer_point.setPos((5000,5000)) self.inner_point = Circle(self, radius=5) self.inner_point.fillColor = 'red' self.inner_point.setPos((5000,5000))
def draw_circle(self, colour=None, pos=None, r=50, pw=1, fill=False): """Draws a circle on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) pos -- circle center, an (x,y) position tuple or None for a central position (default = None) r -- circle radius (default = 50) pw -- penwidth: circle line thickness (default = 1) fill -- Boolean indicating whether circle should be filled or not (default = False) returns Nothing -- draws a circle on (PyGame) or adds a Circle stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if pos == None: pos = (self.dispsize[0] / 2, self.dispsize[1] / 2) colour = rgb2psychorgb(colour) pos = pos2psychopos(pos, dispsize=self.dispsize) if fill: self.screen.append( Circle(pygaze.expdisplay, radius=r, edges=32, pos=pos, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=colour, fillColorSpace='rgb')) else: self.screen.append( Circle(pygaze.expdisplay, radius=r - pw, edges=32, pos=pos, lineWidth=pw, lineColor=colour, lineColorSpace='rgb'))
def ImageDiagnostic(self): """Draws colored dots onto the window. The dots' positions represent the respective location of where images will be placed throughout the course of the task. This function is to only be used as a diagnostic tool, so that one can get a general sense of where images might appear, without having to actually run through the task. To use this function properly: taskSpatial = mdts.MDTS(...) taskSpatial.ImageDiagnostic #taskSpatial.RunExp() """ win = self.window cRad = 50 tp = self.trialsPer ls = self.imageList shapes = [] leng = len(ls) for i in range(0, leng): color = "black" #print "{:<24}{:<15}{:<15}".format(img[0],img[1],img[2]) img = ls[i] if i < tp: color = "black" elif (i > tp) and (i < tp * 2): color = "blue" elif (i > tp * 2) and (i < tp * 3): color = "orange" elif i > tp * 3: color = "green" shapes.append(Circle(win, radius=cRad, pos=img[1], fillColor=color)) shapes.append(Circle(win, radius=cRad, pos=img[2], fillColor=color)) shapes.append( ShapeStim(win, units='pix', lineWidth=5, lineColor=color, vertices=(img[1], img[2]))) for shape in shapes: shape.draw(self.window) self.window.flip() waitKeys(keyList=['escape']) self.window.close()
def __init__(self, win, warper): self.win = win self.warper = warper self.stimT = TextStim(self.win, text='Null warper', units = 'pix', pos=(0, -140), alignHoriz='center', height=20) self.bl = -win.size / 2.0 self.tl = (self.bl[0], -self.bl[1]) self.tr = win.size / 2.0 self.stims = [] self.degrees = 120 nLines = 12 for x in range(-nLines, nLines+1): t = GratingStim(win,tex=None,units='deg',size=[2,win.size[1]],texRes=128,color=foregroundColor, pos=[float(x) / nLines * self.degrees,0]) self.stims.append (t) for y in range (-nLines, nLines+1): t = GratingStim(win,tex=None,units='deg',size=[win.size[0],2],texRes=128,color=foregroundColor,pos=[0,float(y)/nLines * self.degrees]) self.stims.append (t) for c in range (1, nLines+1): t = Circle (win, radius=c * 10, edges=128, units='deg', lineWidth=4) self.stims.append (t) self.updateInfo() self.keys = key.KeyStateHandler() win.winHandle.push_handlers(self.keys) self.mouse = event.Mouse(win=self.win)
def __init__(self, settings_file=None, eyetracker_on=False): """ Initializes base Session class. parameters ---------- settings_file : str Path to settings file. If None, default_settings.yml is used eyetracker_on : bool Whether to enable eyetracker """ self.settings_file = settings_file self.eyetracker_on=eyetracker_on self.clock = Clock() self.timer = Clock() self.start_exp = None self.current_trial = None self.log = [] self.logfile = logging.LogFile(f='log.txt', filemode='w', level=logging.EXP) # Initialize self.settings = self._load_settings() self.monitor = self._create_monitor() self.win = self._create_window() self.mouse = Mouse(**self.settings['mouse']) self.default_fix = Circle(self.win, radius=0.3, fillColor='white', edges=1000) self.mri_simulator = self._setup_mri_simulator() if self.settings['mri']['simulate'] else None self.tracker = None
def __init__(self, disp, end_event, frame_getter): super(DemoScreen, self).__init__(disp) self.gaze = Circle(self.window, radius=50) self.gaze.fillColor = 'white' self.frame_getter = frame_getter self.min_time_over = False self.end_event = end_event
def create_circle_fixation(win, radius=0.1, color=(1, 1, 1), edges=100, **kwargs): """ Creates a circle fixation dot with sensible defaults. """ return Circle(win, radius=radius, color=color, edges=edges, **kwargs)
def draw_ellipse(self, colour=None, x=None, y=None, w=50, h=50, pw=1, fill=False): """Draws an ellipse on the screen arguments None keyword arguments colour -- colour for the circle (a colour name (e.g. 'red') or a RGB(A) tuple (e.g. (255,0,0) or (255,0,0,255))) or None for the default foreground colour, self.fgc (default = None) x -- x coordinate of the rectangle in which the ellipse is drawn or None for a horizontal centrally drawn ellipse (default = None) y -- y coordinate of the rectangle in which the ellipse is drawn or None for a vertical centrally drawn ellipse (default = None) w -- width of the rectangle in which the ellipse is drawn (default = 50) h -- height of the rectangle in which the ellipse is drawn (default = 50) pw -- penwidth: circle line thickness (default = 1) fill -- Boolean indicating whether ellipse should be filled or not (default = False) returns Nothing -- draws an ellipse on (PyGame) or adds a GratinsStim stimulus to (PsychoPy) the self.screen property """ if colour == None: colour = self.fgc if x == None: x = 0 if y == None: y = 0 pos = x,y colour = rgb2psychorgb(colour) pos = pos2psychopos(pos,dispsize=self.dispsize) pos = pos[0] + w/2, pos[1] - h/2 if fill: self.screen.append(Circle(pygaze.expdisplay, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=colour, fillColorSpace='rgb', pos=pos, size=(w,h))) else: self.screen.append(Circle(pygaze.expdisplay, lineWidth=pw, lineColor=colour, lineColorSpace='rgb', fillColor=None, pos=pos, size=(w,h)))
def make_points(self): """ Creates the circles that users will look at to calibrate. """ outer_point = Circle(self, radius=25) outer_point.fillColor = 'white' outer_point.setPos((5000, 5000)) inner_point = Circle(self, radius=5) inner_point.fillColor = 'red' inner_point.setPos((5000, 5000)) return outer_point, inner_point # returns a tuple
def __init__(self, disp, text, end_event): super(EventInstructionsScreen, self).__init__(disp, text) self.move_on_flag = end_event self.indicator = Circle(self.window, radius=10) self.mouse = Mouse() self.ticker = 0 self.ticker_unit = 2*pi/30 self.ticker_max = 2*pi self.indicator_dist = 15
def main(): groups = create_stim_sequence(BLOCK1, BLOCK2, BLOCK3, TRIALREPEATS) print groups disp = Window(size=SIZE, monitor=MON, units='deg', color=BACKCOL, screen=1, fullscr=True) mouse = Mouse() fixmark = Circle(disp, radius=0.05, edges=32, pos=CENTER, lineColor=FIXCOL) images = [] for item in CIRCLES.keys(): image = ImageStim(disp, image=CIRCLES[item][1], pos=CIRCLES[item][0], size=CIRCLES[item][3]) images.append(image) fixmark.draw() draw_group(images) disp.flip() while True: button = mouse.getPressed() if button[0]: break for item in groups: flashes = [] for i in item: flash = ImageStim(disp, image=CIRCLES[i][2], pos=CIRCLES[i][0], size=CIRCLES[i][3]) flashes.append(flash) fixmark.draw() draw_group(images) draw_group(flashes) disp.flip() wait(FLASH) fixmark.draw() draw_group(images) wait(PAUSE) disp.flip() disp.close()
class DemoScreen(Screen): def __init__(self, disp, end_event, frame_getter): super(DemoScreen, self).__init__(disp) self.gaze = Circle(self.window, radius=50) self.gaze.fillColor = 'white' self.frame_getter = frame_getter self.min_time_over = False self.end_event = end_event def draw(self, debug_mode=False): frame = self.frame_getter() xy = (frame[u'avg'][u'x'], frame[u'avg'][u'y']) if xy == (0.0,0.0): xy = (-5000,-5000) self.gaze.pos = self.coords(xy) self.gaze.draw() if self.end_event.is_set(): self.move_on_flag.set() def cleanup(self): wait(0.5) for _ in range(50): self.gaze.setRadius(self.gaze.radius - 1) self.gaze.draw() self.window.flip()
class DemoScreen(Screen): """ A screen to allow participants to mess around with eye tracking while they wait for the other participants to finish instructions and calibration. """ def __init__(self, disp, end_event, frame_getter): super(DemoScreen, self).__init__(disp) self.gaze = Circle(self.window, radius=50) self.gaze.fillColor = 'white' self.frame_getter = frame_getter self.min_time_over = False self.end_event = end_event def draw(self, debug_mode=False): frame = self.frame_getter() xy = (frame[u'avg'][u'x'], frame[u'avg'][u'y']) if xy == (0.0, 0.0): xy = (-5000, -5000) self.gaze.pos = self.coords(xy) self.gaze.draw() if self.end_event.is_set(): self.move_on_flag.set() def cleanup(self): wait(0.5) for _ in range(50): self.gaze.setRadius(self.gaze.radius - 1) self.gaze.draw() self.window.flip()
def check_keys(self): """Checks key input""" for keys in event.getKeys(timeStamped=True): k = keys[0] if k in ['escape', 'q']: self.win.close() sys.exit() elif k in ['space']: for c in range (1,2): t = Circle(self.win, radius=c) self.stims.append (t) #for c in range (1,2): # t = RadialStim(self.win) # self.stims.append(t) # handle projections elif k in ['s']: self.warper.changeProjection ('spherical', None, (0.5,0.5)) elif k in ['c']: self.warper.changeProjection ('cylindrical', None, (0.5,0.5)) elif k in ['n']: self.warper.changeProjection (None, None, (0.5,0.5)) elif k in ['f']: self.warper.changeProjection ('warpfile', r'..\data\sample.meshwarp.data', (0.5,0.5)) # flip horizontal and vertical elif k in ['h']: self.warper.changeProjection(self.warper.warp, self.warper.warpfile, flipHorizontal = not self.warper.flipHorizontal) elif k in ['v']: self.warper.changeProjection(self.warper.warp, self.warper.warpfile, flipVertical = not self.warper.flipVertical) # move eyepoint elif k in ['down']: if (self.warper.dist_cm > 1): self.warper.dist_cm -= 1 self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) elif k in ['up']: if (self.warper.dist_cm < 200): self.warper.dist_cm += 1 self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) elif k in ['right']: if (self.warper.eyepoint[0] < 0.9): self.warper.eyepoint = (self.warper.eyepoint[0] + 0.1, self.warper.eyepoint[1]) self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) elif k in ['left']: if (self.warper.eyepoint[0] > 0.1): self.warper.eyepoint = (self.warper.eyepoint[0] - 0.1, self.warper.eyepoint[1]) self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) self.updateInfo()
class WaitScreen(EventInstructionsScreen): def __init__(self, disp, text, end_event): super(EventInstructionsScreen, self).__init__(disp, text) self.move_on_flag = end_event self.indicator = Circle(self.window, radius=10) self.mouse = Mouse() self.ticker = 0 self.ticker_unit = 2*pi/30 self.ticker_max = 2*pi self.indicator_dist = 15 def draw(self, debug_mode=False): self.instructions_text.draw() mouse_pos = self.mouse.getPos() x = mouse_pos[0] + self.indicator_dist*cos(self.ticker) y = mouse_pos[1] + self.indicator_dist*sin(self.ticker) self.indicator.pos = (x,y) self.indicator.draw() self.ticker += self.ticker_unit if self.ticker > self.ticker_max: self.ticker = 0
def __init__(self, disp, text, config_dict, pupil_coords_getter, seconds_to_ok): super(DetectPupilsScreen, self).__init__(disp) self.continue_button.pos = (0.0, 0.0) self.pupil_coords_getter = pupil_coords_getter cfg = config_dict[u'detect_pupils_screen'] self.in_range_ctr = 0 fps = self.window.getActualFrameRate() if fps is None: fps = 60 self.ctr_max = fps*seconds_to_ok self.detect_pupils_instructions = TextStim( self.window, text=text, pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.x_cfg_2_pix(cfg[u'text'][u'width']), height=cfg[u'text'][u'font_size'] ) self.lefteye = [] self.lefteye.append(Circle(self.window, radius=50)) self.lefteye[-1].fillColor = 'white' self.lefteye.append(Circle(self.window, radius=25)) self.lefteye[-1].fillColor = 'black' self.riteeye = [] self.riteeye.append(Circle(self.window, radius=50)) self.riteeye[-1].fillColor = 'white' self.riteeye.append(Circle(self.window, radius=25)) self.riteeye[-1].fillColor = 'black' # self.ok_indicator = RadialStim( # self.window, tex='none', mask='gauss', pos=(0,0), # size=(1000,1000), color=[0,0,0.5], opacity=0.5 # ) self.ok_indicator = Circle( self.window, radius=(350, 200), fillColor='palegreen', opacity=0.05, lineColor=None ) self.grid = [] for x, y in self.window.calib_points_coords: self.grid.append(Circle(self.window, radius=5, pos=self.coords((x, y)), lineColor=None, fillColor='green' ))
def __init__(self, disp, text, config_dict, gaze_pos_getter=None, width=None, height=None, margin=None, font_size=None, choice_font_size=100, origin=None ): super(ContribScreen, self).__init__(disp) cfg = config_dict[u'contrib_screen'] self.gaze_pos_getter = gaze_pos_getter self.instr_text_preformat = text self.contrib_choice = '__' self.mouseover_threshold = 0 self.choice_coords = [] if width is not None: self.width = width else: self.width = self.window.hres if height is not None: self.height = height else: self.height = self.window.vres if margin is not None: self.margin = margin else: self.margin = self.window.margin if origin is not None: self.origin = origin if font_size is None: font_size = config_dict[u'contrib_screen'][u'text'][u'font_size'] self.contrib_choices = self.gen_contrib_choices( cfg[u'nrows'], cfg[u'ncols'], font_size=choice_font_size ) self.contrib_instructions = TextStim( self.window, height=font_size, text=self.instr_text_preformat.format(self.contrib_choice), pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.w_cfg_2_pix(cfg[u'text'][u'width']) ) self.gaze = Circle(self.window, radius=5) self.gaze.fillColor = 'red'
def draw(self, location): y = 0 if location == "left": x = int(win_width * -0.25) left_targ = Circle(disp, pos=(x, y), radius=self.radius, edges=32, lineColor=self.color, fillColor=self.color) left_targ.draw() if location == "right": x = int(win_width * 0.25) right_targ = Circle(disp, pos=(x, y), radius=self.radius, edges=32, lineColor=self.color, fillColor=self.color) right_targ.draw()
def draw_overview_target(win, level, target_pos, text_pos, mouse_clicks_all_levels): target = ImageStim(win, 'target.png', size=420, pos=target_pos) level_text = TextStim(win, text=f'Level {level}', height=35, color=(0.2, 0.2, 0.8), pos=text_pos) target.draw() level_text.draw() target_x, target_y = target_pos curr_level_mouse_clicks = mouse_clicks_all_levels[level - 1] for target_hit_pos in curr_level_mouse_clicks: if target_hit_pos['mouse_in_target']: circle = Circle(win, radius=5, fillColor='yellow', lineColor='yellow') circle.setPos((target_hit_pos['mouse_x'] + target_x, target_hit_pos['mouse_y'] + target_y)) circle.draw()
from constants import * from psychopy.visual import Window, TextStim, shape, Circle, Rect from psychopy.event import waitKeys from psychopy.core import wait disp = Window(size=DISPSIZE, units='pix', color=BGC, fullscr=True) instructions = 'Willkommen! \n\nIn diesem Experiment werden die Buchstaben E und F auf dem ' \ 'Bildschirm erscheinen. Wenn du eine E siehst, drücke das E. Wenn du ein F siehst' \ ', drücke das F \n\n Versuche so genau und schnell wie möglich zu antworten. \n\n' \ 'Viel Glück!' inststim = TextStim(disp, units='pix', text=instructions, color=FGC, height=35) fixstim = Circle(disp, radius=6, edges = 32, lineColor = FGC, fillColor = FGC) lboxstim = Rect(disp, pos=BOXCORS['left'], width=BOXSIZE, height=BOXSIZE, lineColor = FGC, lineWidth=3) rboxstim = Rect(disp, pos=BOXCORS['right'], width=BOXSIZE, height=BOXSIZE, lineColor = FGC, lineWidth=3) cuestim = {} cuestim['left'] = Rect(disp, pos=BOXCORS['left'], width=BOXSIZE, height=BOXSIZE, lineColor = FGC, lineWidth=8) cuestim['right'] = Rect(disp, pos=BOXCORS['right'], width=BOXSIZE, height=BOXSIZE, lineColor = FGC, lineWidth=8) tarscr = {} tarscr['left'] = {} tarscr['right'] = {}
level=logging.CRITICAL) message = 'ID\tgender\torder\texperiment\tdifficulty\tfalseAlarm\ttrial\tcondition\ttrial.start.time\tsignal\thumanResp\thumanRT\tautoResp\tautoRT\tACC\tstimlength\tRTor\tRTand\n' logClicks.write(message) pracfilename = 'Mahoney_exp_practice_' + info['ID'] + '.txt' logClicksPrac = logging.LogFile(pracfilename, filemode='a', level=logging.CRITICAL) message2 = 'ID\tage\tgender\torder\texperiment\ttrial\ttrial.start.time\tsignal\thumanResp\thumanRT\tautoResp\tautoRT\ttrialACC\tstimlength\n' logClicksPrac.write(message2) # Object Setup positions = [0, 0] startButton = Circle(win, units="deg", radius=1, lineWidth=.5, lineColor=(1, 1, 1), fillColor=(0, 0, 0)) fixCross = Circle(win, units="deg", radius=1, lineColor=(1, 1, 1), fillColor=(0, 0, 0)) background = Rect(win, units="deg", width=13, height=13, fillColor=(0, 0, 0), lineColor=(0, 0, 0)) placeholder = Circle(win, radius=0.5,
class CalibratableWindow(Window): def __init__(self, num_calib_points=9, margin=100, **kwargs ): super(CalibratableWindow, self).__init__( **kwargs ) self.hres = int(self.size[0]) self.vres = int(self.size[1]) self.num_calib_points = num_calib_points self.margin = margin self.calib_points_coords = self.gen_calib_point_coords() def calibrate(self, et_comm): self.setMouseVisible(False) self.make_points() start_reply = et_comm.start_calibration(self.num_calib_points) if start_reply[u'statuscode'] == 403: et_comm.abort_calibration() et_comm.start_calibration(self.num_calib_points) calibration_obj={} for x,y in self.calib_points_coords: self.point_place(x,y) wait(0.750) et_comm.start_calib_point(x,y) self.point_expand_contract(duration=1) calibration_obj = et_comm.end_calib_point() wait(0.250) self.setMouseVisible(True) return calibration_obj[u'values'][u'calibresult'] def make_points(self): self.outer_point = Circle(self, radius=25) self.outer_point.fillColor = 'white' self.outer_point.setPos((5000,5000)) self.inner_point = Circle(self, radius=5) self.inner_point.fillColor = 'red' self.inner_point.setPos((5000,5000)) def point_place(self, x, y): xy_tuple = self.tl2c((x,y)) self.outer_point.setPos(xy_tuple) self.inner_point.setPos(xy_tuple) self.outer_point.draw() self.inner_point.draw() self.flip() def tl2c(self, coords_tuple): x = coords_tuple[0] - self.hres/2 y = coords_tuple[1] - self.vres/2 return (x, -y) def point_expand_contract(self, duration): start_time = getTime() ratio = 0 while ratio < 1: ratio = (getTime()-start_time)/(duration*0.5) self.outer_point.setRadius(25+25*ratio) self.outer_point.draw() self.inner_point.draw() self.flip() while ratio < 2: ratio = (getTime()-start_time)/(duration*0.5) self.outer_point.setRadius(75-25*ratio) self.outer_point.draw() self.inner_point.draw() self.flip() def gen_calib_point_coords(self): if self.num_calib_points == 9: nrows = 3 ncols = 3 elif self.num_calib_points == 12: nrows = 3 ncols = 4 elif self.num_calib_points == 16: nrows = 4 ncols = 4 else: print('Unacceptable number of calibration points. ' 'Please choose 9, 12, or 16. Defaulting to 9.') nrows = 3 ncols = 3 coord_list = [] h_spacing = (self.hres - 2*self.margin)/(ncols-1) v_spacing = (self.vres - 2*self.margin)/(nrows-1) for row in range(nrows): for col in range(ncols): coord_list.append((col*h_spacing + self.margin, row*v_spacing + self.margin)) shuffle(coord_list) return coord_list
def __init__(self, nstim, locs, oris, linewidth=3, \ stimtypes='gabor', showcolourwheel=False): """Initialises a new StimScreen instance. Arguments nstim - Integer that determines the number of stimuli on this screen. locs - List of (x,y) tuples that determine the positions of all stimuli. The list's length should be equal to the number of stimuli as defined by nstim. oris - List of integers that determine the orientations of all stimuli. The list's length should be equal to the number of stimuli as defined by nstim. Keyword Arguments linewidth - Integer or a list of integers that determines the width of the lines around stimuli (in pixels). Default value is 3. stimtypes - String or a list of strings that determines the type of stimulus. Options are 'gabor' and 'noise'. Default is 'gabor'. showcolourwheel- Boolean that determines whether a central colour wheel should be drawn of not. Default is False. """ # Settings from the constants. self._sf = float(STIMSF) / float(STIMSIZE) self._alpha = STIMALPHA self._contrast = STIMCONTRAST # Noise texture. self._noisetex = numpy.random.rand(STIMNOISERES, STIMNOISERES) # Convert the linewidth to a list (if necessary). if type(linewidth) in [int, float]: linewidth = nstim * [int(linewidth)] # Convert the stimulus types to a list (if necessary). if type(stimtypes) in [str, unicode]: stimtypes = nstim * [stimtypes] # Create a Screen to use its wonderful drawing functions. self.scr = Screen() # Draw the fixation cross. self.scr.draw_fixation(fixtype=FIXTYPE, diameter=FIXSIZE) # Draw the colouw wheel if showcolourwheel: # Load the image. self.scr.draw_image(CWIMG, scale=CWIMGSCALE) # Create an internal list of stimuli (=PsychoPy stimulus instances) by # copying it from the internal screen. self.screen = self.scr.screen # Keep a list of the index numbers of all stimuli. The indices refer # to positions within the self.scr.screen list of PsychoPy stimuli. self._stimindexnrs = [] self._outlineindexnrs = [] # Draw the stimuli. for i in range(nstim): # Add the stimulus' index number to the list of indices. self._stimindexnrs.append(len(self.screen)) # # Create a new Rect stimulus instance. # stim = Rect(pygaze.expdisplay, \ # pos=pos2psychopos(locs[i]), \ # fillColor=rgb2psychorgb(list(oris[i])), \ # lineColor=rgb2psychorgb(list(linecols[i])), \ # lineWidth=linewidth[i], \ # width=STIMSIZE, \ # height=STIMSIZE) # Create a Gabor-ish GratingStim. if stimtypes[i] == 'gabor': tex = 'sin' else: tex = self._noisetex stim = GratingStim(pygaze.expdisplay, \ pos=pos2psychopos(locs[i]), \ ori=oris[i], \ size=STIMSIZE, \ sf=self._sf, \ opacity=self._alpha, \ contrast=self._contrast, \ tex=tex, \ mask='circle', \ color=(1,1,1) ) # Add the new stimulus to our list of stimuli. self.screen.append(stim) # Add an outline for the stimulus. self._outlineindexnrs.append(len(self.screen)) stim = Circle(pygaze.expdisplay, \ pos=pos2psychopos(locs[i]), \ lineWidth=linewidth[i], \ radius=STIMSIZE//2, \ edges=32, \ closeShape=False, \ fillColor=None, \ lineColor=(0,0,0) ) # Add the new stimulus to our list of stimuli. self.screen.append(stim)
class FeedbackScreen(Screen): # This should not be messed with, we want to maintain between- # subject counterbalancing, but not change things within-subject. reversed = choice([True, False]) def __init__(self, disp, num_players, config_dict, gaze_pos_getter=None, width=None, height=None, margin=None, font_size=None, col_x_list=[], AOIs=False): super(FeedbackScreen, self).__init__(disp) self.gaze_pos_getter = gaze_pos_getter self.continue_button.clickable = True cfg = config_dict[u'feedback_screen'] if width is not None: self.width = width else: self.width = self.window.hres if height is not None: self.height = height else: self.height = self.window.vres if margin is not None: self.margin = margin else: self.margin = self.window.margin if font_size is not None: self.font_size = font_size else: self.font_size = config_dict[u'feedback_screen'][u'font_size'] self.col_x_list = [] if col_x_list == []: self.col_x_list.append( self.x_cfg_2_pix( config_dict[u'feedback_screen'][u'left_col_x'] )) self.col_x_list.append( self.x_cfg_2_pix( config_dict[u'feedback_screen'][u'midd_col_x'] )) self.col_x_list.append( self.x_cfg_2_pix( config_dict[u'feedback_screen'][u'rite_col_x'] )) del col_x_list if FeedbackScreen.reversed: self.col_x_list.reverse() self.gaze = Circle(self.window, radius=5) self.gaze.fillColor = 'red' self.nrows = num_players + 3 self.SUMROWINDEX = self.nrows - 2 self.AVGROWINDEX = self.nrows - 1 row_spacing = (self.height - 2*self.margin)/(self.nrows-1) self.contr_col = [] self.label_col = [] self.payof_col = [] for i in range(self.nrows): y = self.window.margin + i*row_spacing temp_contr = TextStim(self.window, height=self.font_size) temp_label = TextStim(self.window, height=self.font_size) temp_payof = TextStim(self.window, height=self.font_size) if i == 0: temp_contr.setText(cfg[u'contributions']) temp_label.setText(cfg[u'players']) temp_payof.setText(cfg[u'payoffs']) else: temp_contr.setText('xx') temp_payof.setText('xx') if i == 1: temp_label.setText(cfg[u'you']) elif i <= num_players: temp_label.setText(cfg[u'others'][i-2]) elif i == self.SUMROWINDEX: temp_label.setText(cfg[u'sum']) elif i == self.AVGROWINDEX: temp_label.setText(cfg[u'average']) else: logging.error('Error in FeedbackScreen.__init__(). Wrong number of rows?') temp_contr.setPos(self.coords((self.col_x_list[0], y))) self.contr_col.append(temp_contr) temp_label.setPos(self.coords((self.col_x_list[1], y))) self.label_col.append(temp_label) temp_payof.setPos(self.coords((self.col_x_list[2], y))) self.payof_col.append(temp_payof) self.AOIs = [] if AOIs: for _ in range(3): self.AOIs.append(Rect(self.window, width=400, height=280, lineColor='slateblue', fillColor='steelblue')) self.AOIs[-1].setPos(self.contr_col[-1].pos) self.AOIs[-2].setPos(self.label_col[-1].pos) self.AOIs[-3].setPos(self.payof_col[-1].pos) def draw(self, debug_mode=False): if getAbsTime() - self.t0 > 30: self.move_on_flag.set() if self.AOIs != [] and self.gaze_pos_getter is not None: self.gaze.pos = self.coords(self.gaze_pos_getter()) for shape in self.AOIs: if shape.contains(self.gaze.pos): shape.setFillColor('slateblue') else: shape.setFillColor('steelblue') for shape in self.AOIs: shape.draw() self.gaze.draw() for i in range(self.nrows): self.label_col[i].draw() self.contr_col[i].draw() self.payof_col[i].draw() self.continue_button.draw() def cleanup(self): self.move_on_flag.clear() def update_info(self, contr_avg, payoff_avg, contr_sum, payoff_sum, my_contr, my_payoff, other_contr=[], other_payoff=[]): # This bit randomizes the order that the other players are # presented in on the feedback screen. Not yet tested to # make sure it works, but it should. Only matters if N > 2. # if len(other_contr) > 1: # indices = [] # for i in range(len(other_contr)): # indices.append(i) # shuffle(indices) # temp_contr = other_contr[:] # temp_payoff = other_payoff[:] # for i in range(len(indices)): # other_contr[i] = temp_contr[indices[i]] # other_payoff[i] = temp_payoff[indices[i]] self.update_col(self.contr_col, contr_avg, contr_sum, my_contr, other_contr) self.update_col(self.payof_col, payoff_avg, payoff_sum, my_payoff, other_payoff) def update_col(self, col, avg, sum_, mine, others): # avg = str(avg).replace('.',',') avg = '{:n}'.format(avg) sum_ = '{:n}'.format(sum_) mine = '{:n}'.format(mine) col[self.AVGROWINDEX].setText(avg) col[self.SUMROWINDEX].setText(sum_) col[1].setText(mine) for i in range(len(others)): other = '{:n}'.format(others[i]) col[i+2].setText(other)
def __init__(self, disp, num_players, config_dict, gaze_pos_getter=None, width=None, height=None, margin=None, font_size=None, col_x_list=[], AOIs=False): super(FeedbackScreen, self).__init__(disp) self.gaze_pos_getter = gaze_pos_getter self.continue_button.clickable = True cfg = config_dict[u'feedback_screen'] if width is not None: self.width = width else: self.width = self.window.hres if height is not None: self.height = height else: self.height = self.window.vres if margin is not None: self.margin = margin else: self.margin = self.window.margin if font_size is not None: self.font_size = font_size else: self.font_size = config_dict[u'feedback_screen'][u'font_size'] self.col_x_list = [] if col_x_list == []: self.col_x_list.append( self.x_cfg_2_pix( config_dict[u'feedback_screen'][u'left_col_x'] )) self.col_x_list.append( self.x_cfg_2_pix( config_dict[u'feedback_screen'][u'midd_col_x'] )) self.col_x_list.append( self.x_cfg_2_pix( config_dict[u'feedback_screen'][u'rite_col_x'] )) del col_x_list if FeedbackScreen.reversed: self.col_x_list.reverse() self.gaze = Circle(self.window, radius=5) self.gaze.fillColor = 'red' self.nrows = num_players + 3 self.SUMROWINDEX = self.nrows - 2 self.AVGROWINDEX = self.nrows - 1 row_spacing = (self.height - 2*self.margin)/(self.nrows-1) self.contr_col = [] self.label_col = [] self.payof_col = [] for i in range(self.nrows): y = self.window.margin + i*row_spacing temp_contr = TextStim(self.window, height=self.font_size) temp_label = TextStim(self.window, height=self.font_size) temp_payof = TextStim(self.window, height=self.font_size) if i == 0: temp_contr.setText(cfg[u'contributions']) temp_label.setText(cfg[u'players']) temp_payof.setText(cfg[u'payoffs']) else: temp_contr.setText('xx') temp_payof.setText('xx') if i == 1: temp_label.setText(cfg[u'you']) elif i <= num_players: temp_label.setText(cfg[u'others'][i-2]) elif i == self.SUMROWINDEX: temp_label.setText(cfg[u'sum']) elif i == self.AVGROWINDEX: temp_label.setText(cfg[u'average']) else: logging.error('Error in FeedbackScreen.__init__(). Wrong number of rows?') temp_contr.setPos(self.coords((self.col_x_list[0], y))) self.contr_col.append(temp_contr) temp_label.setPos(self.coords((self.col_x_list[1], y))) self.label_col.append(temp_label) temp_payof.setPos(self.coords((self.col_x_list[2], y))) self.payof_col.append(temp_payof) self.AOIs = [] if AOIs: for _ in range(3): self.AOIs.append(Rect(self.window, width=400, height=280, lineColor='slateblue', fillColor='steelblue')) self.AOIs[-1].setPos(self.contr_col[-1].pos) self.AOIs[-2].setPos(self.label_col[-1].pos) self.AOIs[-3].setPos(self.payof_col[-1].pos)
def create_circle_fixation(win, radius=0.1, color=(1, 1, 1), edges=100, **kwargs): return Circle(win, radius=radius, color=color, edges=edges, **kwargs)
class DetectPupilsScreen(Screen): def __init__(self, disp, text, config_dict, pupil_coords_getter, seconds_to_ok): super(DetectPupilsScreen, self).__init__(disp) self.continue_button.setPos((0.0,0.0)) self.pupil_coords_getter = pupil_coords_getter cfg = config_dict[u'detect_pupils_screen'] self.in_range_ctr = 0 fps = self.window.getActualFrameRate() self.ctr_max = fps*seconds_to_ok self.detect_pupils_instructions = TextStim( self.window, text=text, pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.x_cfg_2_pix(cfg[u'text'][u'width']), height=cfg[u'text'][u'font_size'] ) self.lefteye = [] self.lefteye.append(Circle(self.window, radius=50)) self.lefteye[-1].fillColor='white' self.lefteye.append(Circle(self.window, radius=25)) self.lefteye[-1].fillColor='black' self.riteeye = [] self.riteeye.append(Circle(self.window, radius=50)) self.riteeye[-1].fillColor='white' self.riteeye.append(Circle(self.window, radius=25)) self.riteeye[-1].fillColor='black' # self.ok_indicator = RadialStim( # self.window, tex='none', mask='gauss', pos=(0,0), # size=(1000,1000), color=[0,0,0.5], opacity=0.5 # ) self.ok_indicator = Circle( self.window, radius=(350,200), fillColor='palegreen', opacity=0.05, lineColor=None ) self.grid = [] for x, y in self.window.calib_points_coords: self.grid.append(Circle(self.window, radius=5, pos=self.coords((x, y)), lineColor=None, fillColor='green' )) def draw(self, debug_mode=False): ((leftx,lefty),(ritex,ritey)) = self.pupil_coords_getter() leftx *= self.window.hres lefty *= self.window.vres ritex *= self.window.hres ritey *= self.window.vres if leftx == 0.0 or lefty == 0.0: leftx, lefty = (-5000,-5000) if ritex == 0.0 or ritey == 0.0: ritex, ritey = (-5000,-5000) for circle in self.lefteye: circle.pos = self.coords((leftx,lefty)) for circle in self.riteeye: circle.pos = self.coords((ritex,ritey)) # ldist = xydist([leftx,lefty], (self.window.hres/2,self.window.vres/2)) # rdist = xydist([ritex,ritey], (self.window.hres/2,self.window.vres/2)) # if ldist+rdist < self.window.vres/2: # self.in_range_ctr += 1 if (self.ok_indicator.contains(self.lefteye[0].pos) and self.ok_indicator.contains(self.riteeye[0].pos) ): self.in_range_ctr += 1 op = self.ok_indicator.opacity + 0.03 self.ok_indicator.opacity = min(op, 0.65) else: op = self.ok_indicator.opacity - 0.03 self.ok_indicator.opacity = max(op, 0.05) # # # if missed_flag: # temp = self.ok_indicator.color * 0.95 # temp[2] = 0.5 # temp[0] = 0 # else: # ratio = self.window.vres/(3*(ldist+rdist)) # if ratio > 1: # ratio = 1 # temp = [0, ratio, 0.5] # # self.ok_indicator.color = temp if ((self.in_range_ctr >= self.ctr_max) or debug_mode ): self.continue_button.clickable = True # draw commands for thing in self.grid: thing.draw() self.ok_indicator.draw() self.detect_pupils_instructions.draw() self.continue_button.draw() for circle in self.lefteye: circle.draw() for circle in self.riteeye: circle.draw()
class ContribScreen(Screen): """ This screen lets users select their contribution. """ def __init__(self, disp, text, config_dict, gaze_pos_getter=None, width=None, height=None, margin=None, font_size=None, choice_font_size=100, origin=None ): super(ContribScreen, self).__init__(disp) cfg = config_dict[u'contrib_screen'] self.gaze_pos_getter = gaze_pos_getter self.instr_text_preformat = text self.contrib_choice = '__' self.mouseover_threshold = 0 self.choice_coords = [] if width is not None: self.width = width else: self.width = self.window.hres if height is not None: self.height = height else: self.height = self.window.vres if margin is not None: self.margin = margin else: self.margin = self.window.margin if origin is not None: self.origin = origin if font_size is None: font_size = config_dict[u'contrib_screen'][u'text'][u'font_size'] self.contrib_choices = self.gen_contrib_choices( cfg[u'nrows'], cfg[u'ncols'], font_size=choice_font_size ) self.contrib_instructions = TextStim( self.window, height=font_size, text=self.instr_text_preformat.format(self.contrib_choice), pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.w_cfg_2_pix(cfg[u'text'][u'width']) ) self.gaze = Circle(self.window, radius=5) self.gaze.fillColor = 'red' def draw(self, debug_mode=False): mouse_x, mouse_y = self.mouse.getPos() for text_stim in self.contrib_choices: if xydist((mouse_x, mouse_y), text_stim.pos) < self.mouseover_threshold: text_stim.color = 'darkorange' if self.mouse.getPressed()[0]: self.contrib_choice = text_stim.text self.contrib_instructions.setText(self.instr_text_preformat.format(self.contrib_choice)) self.continue_button.clickable = True else: text_stim.color = 'white' text_stim.draw() self.continue_button.draw() self.contrib_instructions.draw() if self.gaze_pos_getter is not None: self.gaze.pos = self.coords(self.gaze_pos_getter()) self.gaze.draw() def cleanup(self): self.continue_button.clickable = False self.contrib_instructions.setText(self.instr_text_preformat.format('__')) self.move_on_flag.clear() def gen_contrib_choices(self, nrows, ncols, font_size): h_spacing = (self.width - 2*self.margin)/(ncols-1) v_spacing = h_spacing '''OR: v_spacing = (self.height - 2*self.margin)/(nrows-1)''' self.mouseover_threshold = min(h_spacing, v_spacing)/4 contrib_choices = [] for i in range(0, nrows*ncols): xpos = self.margin + (i % ncols)*h_spacing ''' To move the array to the bottom of the page: ypos = self.height - self.margin - (nrows-floor(1.0*i/ncols)-1)*v_spacing ''' ypos = floor(1.0*i/ncols)*v_spacing + self.margin ''' 1.0*i/ncols gives us a floating-point number. Without the 1.0, python interprets this as int-division and truncates. I could have exploited this for slightly simpler code but it is really stupid that it works that way and who knows what bugs could pop up by relying on something that is in my opinion a bug? We take the floor of that number to give us a "row index." We multiply this number by the vertical spacing. ''' if i < 10: temp = ' {} '.format(i) else: temp = '{}'.format(i) contrib_choices.append(TextStim(win=self.window, text=temp, pos=self.coords((xpos, ypos)), height=font_size)) self.choice_coords.append((xpos, ypos)) return contrib_choices
def main(window, dominant_eye): """ This is pretty much just a less complicated version of the step method in the testing script, so it's not commented that much. """ # Fusion box stuff maskPos = -200 if dominant_eye: maskPos = 200 box_1 = Rect(win = window, width = 180, height = 180, lineWidth = 4, lineColor = 'grey', pos = (-200, 150), autoDraw = True) box_2 = Rect(win = window, width = 180, height = 180, lineWidth = 4, lineColor = 'grey', pos = (-1 * -200, 150), autoDraw = True) box_1.setAutoDraw(True) box_2.setAutoDraw(True) # Mask stuff frame_paths = ["Masks/" + file for file in os.listdir("Masks")] frames = map(lambda file_name: ImageStim(window, image = file_name, color = (1,1,1), size = [150, 150], pos = (maskPos,150), opacity = 1), frame_paths) #Fixation dot stuff fixation_dot_1 = Circle(win = window, radius = 2, fillColor = 'red', pos = (-200, 150), lineWidth = 0, autoDraw = True) fixation_dot_2 = Circle(win = window, radius = 2, fillColor = 'red', pos = (-1 * -200, 150), lineWidth = 0, autoDraw = True) img = Image("Pairs/practice_img.jpg", "") img = img.stimulus(window, position = (-1*maskPos, 150), transparency = 1) transparencies = [0.016 * (n + 1) * 0.1 for n in range(60)] # ten trials at 10% contrast and ten at 50% N_TRIALS = 20 all_trials = [i for i in range(N_TRIALS)] shuffle(all_trials) low_contrast = all_trials[:10] high_contrast = all_trials[10:] low_transparencies = [0.016 * (n + 1) * 0.1 for n in range(60)] high_transparencies = [0.016 * (n + 1) * 0.5 for n in range(60)] for i in range(N_TRIALS): if i in low_contrast: step(window, low_transparencies, img, frames, 0.05 * i) if i in high_contrast: step(window, high_transparencies, img, frames, 0.05 * i) box_1.setAutoDraw(False) box_2.setAutoDraw(False) fixation_dot_1.setAutoDraw(False) fixation_dot_2.setAutoDraw(False)
units='pix', color=(0, 0, 0)) win.update() #n trials nTrials = 8 #Visual stimuli black = [-1, -1, -1] leftPos = -300 rightPos = 300 #HEIGHT circleHIGH = Circle(win=win, units="pix", radius=100, fillColor=black, lineColor=black, pos=[0, 300], name="high") circleLOW = Circle(win=win, units="pix", radius=100, fillColor=black, lineColor=black, pos=[0, -300], name="low") #SIZE circleBIG = Circle(win=win, units="pix", radius=200, fillColor=black,
lineColor = cue_Flash, lineWidth = 8) cue_Stim['right'] = Rect(disp, pos = Box_Coord['right'],\ width = Box_Dimen[0], height = Box_Dimen[1],\ lineColor = cue_Flash, lineWidth = 8) #create a fixation point/cross fix_Stim = ShapeStim(disp, lineWidth = 100, lineColor = [1, 1, 1], \ fillColor = [1, 1, 1], vertices = 'cross') #create a dictionary for target display, and nested dict for different targets targ_Stim = {} targ_Stim['left'] = {} targ_Stim['right'] = {} targ_Stim['left']['P'] = Circle(disp, radius = 15, edges = 32, lineColor = FGC,\ lineWidth = 5, fillColor = FGC, pos = Box_Coord['left']) targ_Stim['right']['P'] = Circle(disp, radius = 15, edges = 32, lineColor = FGC,\ lineWidth = 5, fillColor = FGC, pos = Box_Coord['right']) targ_Stim['left']['C'] = Circle(disp, radius = 50, edges = 32, lineColor = FGC,\ lineWidth = 5, fillColor = FGC, pos = Box_Coord['left']) targ_Stim['right']['C'] = Circle(disp, radius = 50, edges = 32, lineColor = FGC,\ lineWidth = 5, fillColor = FGC, pos = Box_Coord['right']) # define the feedback screens fb_scr = {} fb_scr['Incorrect'] = TextStim(disp, text = 'Incorrect', height = 24,\ color = (1, -1, -1)) fb_scr['Correct'] = TextStim(disp, text = 'Correct!', height = 24,\ color = (-1, 1, -1)) fb_scr['NoResp'] = TextStim(disp, text = 'Please make a choice',\
def RunButtonDiagnostic(self): ''' Run a test to make sure that the buttons are being recorded correctly Creates a temporary window and accepts keypresses Shows the buttonpresses with a highlighting circle ''' if (self.screenType == 'Windowed'): screenSelect = False elif (self.screenType == 'Fullscreen'): screenSelect = True window = Window(fullscr=screenSelect, units='pix', color='White', allowGUI=False) indRadius = 100 tHeight = 2 * indRadius / 5 posC1 = (-window.size[0] / 4, 0) posC2 = (window.size[0] / 4, 0) #creating circle opjects circ1 = Circle(window, indRadius, lineColor='White', lineWidth=6, pos=posC1) #training and p1 circles circ2 = Circle(window, indRadius, lineColor='White', lineWidth=6, pos=posC2) #creating text objects for cicles trtext1 = TextStim(window, " Button 1", color='White', height=tHeight, pos=posC1) #training text trtext2 = TextStim(window, " Button 2", color='White', height=tHeight, pos=posC2) #List of final circle and text objects trCircs = [circ1, circ2] trTexts = [trtext1, trtext2] trTxt = TextStim( window, "This is a test to ensure that the buttons are being recorded correctly.\n Press each button to make sure it is being recorded correctly.\n Press escape to move on", pos=(0, window.size[1] / 4), color="Black", height=40, wrapWidth=0.8 * window.size[0]) for circ in trCircs: circ.fillColor = 'Gray' trTxt.draw(window) for circ in trCircs: circ.draw(window) for text in trTexts: text.draw(window) window.flip() while 1: key = waitKeys(keyList=self.inputButtons + [self.pauseButton, 'escape'])[0] for circ in trCircs: circ.fillColor = 'Gray' if key == 'escape' or key == self.pauseButton: #print "Press ecape one more time\n" break elif key == self.inputButtons[0]: trCircs[0].fillColor = 'Green' elif key == self.inputButtons[1]: trCircs[1].fillColor = 'Green' trTxt.draw(window) for circ in trCircs: circ.draw(window) for text in trTexts: text.draw(window) window.flip() window.flip() window.close()
#time RT=core.Clock() #sound stimuli #highSound = sound.Sound('A',octave=4,sampleRate=44100,secs=0.120,stereo=True,name = "high") highSound = sound.Sound("/Users/peerchristensen/Desktop/PsPy/high_low_short/high_a4.wav",name = "high") #lowSound = sound.Sound('A',octave=2,sampleRate=44100,secs=0.120,stereo=True,name = "low") lowSound = sound.Sound("/Users/peerchristensen/Desktop/PsPy/high_low_short/low_a1.wav",name = "low") sounds=[highSound,lowSound] * (nTrials/2) # Visual stimuli #fixation cross fixCross = visual.TextStim(win, text="+",pos=center,units="deg", color=black,height=3) #HEIGHT circleHIGH = Circle(win=win,units="deg",radius= 3, fillColor=black,lineColor=black,pos=[-0.1,8],name="high") circleLOW = Circle(win=win,units="deg",radius= 3, fillColor=black,lineColor=black,pos=[-0.1,-8],name="low") #SIZE circleBIG = Circle(win=win,units="deg",radius= 6, fillColor=black,lineColor=black,pos=center,name="big") circleSMALL = Circle(win=win,units="deg",radius= 1.5, fillColor=black,lineColor=black,pos=center,name="small") stimsSize= [circleBIG,circleSMALL] * (nTrials/2) stimsHeight=[circleHIGH,circleLOW] * (nTrials/2) #warm up circles=[circleBIG,circleSMALL,circleHIGH,circleLOW] * 2 random.shuffle(circles) voices=[highSound,lowSound] * 4 random.shuffle(voices) msg.draw() win.flip()
class DetectPupilsScreen(Screen): """ Screen which lets subjects see where they should move their head to get the best calibration. """ def __init__(self, disp, text, config_dict, pupil_coords_getter, seconds_to_ok): super(DetectPupilsScreen, self).__init__(disp) self.continue_button.pos = (0.0, 0.0) self.pupil_coords_getter = pupil_coords_getter cfg = config_dict[u'detect_pupils_screen'] self.in_range_ctr = 0 fps = self.window.getActualFrameRate() if fps is None: fps = 60 self.ctr_max = fps*seconds_to_ok self.detect_pupils_instructions = TextStim( self.window, text=text, pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.x_cfg_2_pix(cfg[u'text'][u'width']), height=cfg[u'text'][u'font_size'] ) self.lefteye = [] self.lefteye.append(Circle(self.window, radius=50)) self.lefteye[-1].fillColor = 'white' self.lefteye.append(Circle(self.window, radius=25)) self.lefteye[-1].fillColor = 'black' self.riteeye = [] self.riteeye.append(Circle(self.window, radius=50)) self.riteeye[-1].fillColor = 'white' self.riteeye.append(Circle(self.window, radius=25)) self.riteeye[-1].fillColor = 'black' # self.ok_indicator = RadialStim( # self.window, tex='none', mask='gauss', pos=(0,0), # size=(1000,1000), color=[0,0,0.5], opacity=0.5 # ) self.ok_indicator = Circle( self.window, radius=(350, 200), fillColor='palegreen', opacity=0.05, lineColor=None ) self.grid = [] for x, y in self.window.calib_points_coords: self.grid.append(Circle(self.window, radius=5, pos=self.coords((x, y)), lineColor=None, fillColor='green' )) def draw(self, debug_mode=False): ((leftx, lefty), (ritex, ritey)) = self.pupil_coords_getter() leftx *= self.window.hres lefty *= self.window.vres ritex *= self.window.hres ritey *= self.window.vres if leftx == 0.0 or lefty == 0.0: leftx, lefty = (-5000, -5000) if ritex == 0.0 or ritey == 0.0: ritex, ritey = (-5000, -5000) for circle in self.lefteye: circle.pos = self.coords((leftx, lefty)) for circle in self.riteeye: circle.pos = self.coords((ritex, ritey)) if self.ok_indicator.contains(self.lefteye[0].pos) and self.ok_indicator.contains(self.riteeye[0].pos): self.in_range_ctr += 1 op = self.ok_indicator.opacity + 0.03 self.ok_indicator.opacity = min(op, 0.65) else: op = self.ok_indicator.opacity - 0.03 self.ok_indicator.opacity = max(op, 0.05) if (self.in_range_ctr >= self.ctr_max) or debug_mode: self.continue_button.clickable = True # draw commands for thing in self.grid: thing.draw() self.ok_indicator.draw() self.detect_pupils_instructions.draw() self.continue_button.draw() for circle in self.lefteye: circle.draw() for circle in self.riteeye: circle.draw()
start=(-75, 300), end=(75, 300), lineWidth=30, lineColor=black, name="high") stimLOW = Line(win, start=(-75, -300), end=(75, -300), lineWidth=30, lineColor=black, name="low") #SIZE circleBIG = Circle(win=win, units="pix", radius=200, fillColor=black, lineColor=black, pos=[0, 0], name="big") circleSMALL = Circle(win=win, units="pix", radius=50, fillColor=black, lineColor=black, pos=[0, 0], name="small") #Visual stimulus lists completeList = [[circleSMALL, circleBIG], [stimLOW, stimHIGH], [stimHIGH, circleSMALL], [stimLOW, circleBIG]] * (nTrials / 4) random.shuffle(completeList)
pos=(0.5, 0), labels=(sliderLeftT, sliderRightT), ticks=(sliderLeftP, sliderRightP), granularity=0, style=['slider'], color='black', font='HelveticaBold', flip=True, units="height") # notice that the "size" of the slider controls whether the slider is verticle or horizontal # change to desired style, using the in-built visual stimulus from psychopy slider.marker = Circle( win, radius=slider.size[0] * 0.5, # The radius should be half the width edges=32, fillColor='black', lineColor='gray') slider.line = Rect( win, units=slider.units, pos=slider.pos, width=slider.size[0], height=slider.size[1] + 0.005, # +0.005 just to make the rectangule looks better lineColor='black', fillColor='gray', autoLog=False) text1 = visual.TextStim(win=win,
def __init__(self, win, rating_question=None, labels=None, coords=None, buttons=None, label_height=45, anchor_size=15, anchor_color='lightblue', anchor_color_chosen='orange', offset_label=50, time_until_disappear=0.3, fixation=None): """ Initializes ButtonBoxRating object. """ if rating_question is None: rating_question = '' if len(labels) == 2 and coords is None: labels = [labels[0], ' ', ' ', ' ', ' ', ' ', ' ', labels[1]] offset_label = -1 * offset_label if coords is None: coords = [(-600, -300), (-450, -200), (-300, -150), (-150, -100), (150, -100), (300, -150), (450, -200), (600, -300)] if buttons is None: # ONLY TEST VERSION (MRI should be 'b', 'y', 'g' etc) buttons = [str(i + 1) for i in range(8)] self.rating_question = rating_question self.labels = labels self.coords = coords self.buttons = buttons self.actual_buttons = [ b for i, b in enumerate(buttons) if self.labels[i] ] self.label_height = label_height self.anchor_size = anchor_size self.anchor_color = anchor_color self.anchor_color_chosen = anchor_color_chosen self.offset_label = offset_label self.time_until_disappear = time_until_disappear if fixation is None: self.fixation = GratingStim(win, tex='sin', mask='raisedCos', size=10, texRes=512, color='white', sf=0, maskParams={'fringeWidth': 0.4}) self.fixation = fixation self.rating_anchors = [] self.label_texts = [] self.resp = None self.time_resp = np.inf for i in range(len(self.coords)): if not self.labels[i]: continue # remove anchor for empty label rating_anchor = Circle( win=win, pos=coords[i], radius=self.anchor_size, edges=200, units='pix', fillColor=self.anchor_color, ) #rating_anchor.setColor(self.anchor_color) label_text = TextStim(win=win, pos=(self.coords[i][0], self.coords[i][1] + self.offset_label), height=self.label_height, units='pix', text=self.labels[i]) self.rating_anchors.append(rating_anchor) self.label_texts.append(label_text) self.rating_text = TextStim(win=win, pos=(0, max([c[1] for c in self.coords]) + 200), height=self.label_height * 1.5, units='pix', text=self.rating_question, wrapWidth=max([c[0] for c in self.coords]) - min([c[0] for c in self.coords]))
class PsychopyCustomDisplay(pylink.EyeLinkCustomDisplay): """ Custom display for Eyelink eyetracker. Modified from the 'pylinkwrapper' package by Nick DiQuattro (https://github.com/ndiquattro/pylinkwrapper). All credits go to him. """ def __init__(self, tracker, win, settings): """ Initializes PsychopyCustomDisplay object. """ super().__init__() self.tracker = tracker self.win = win self.settings = settings # from session self.txtcol = -1 #self.__target_beep__ = sound.Sound(800, secs=.1) # THIS WILL GIVE A SEGFAULT! #self.__target_beep__done__ = sound.Sound(1200, secs=.1) # THIS WILL GIVE A SEGFAULT! #self.__target_beep__error__ = sound.Sound(400, secs=.1) # THIS WILL GIVE A SEGFAULT! self.backcolor = self.win.color dot_size_pix = misc.deg2pix( self.settings['eyetracker'].get('dot_size'), self.win.monitor) self.targetout = Circle(self.win, pos=(0, 0), radius=dot_size_pix, fillColor='black', units='pix', lineColor='black') self.targetin = Circle(self.win, pos=(0, 0), radius=3, fillColor=0, lineColor=0, units='pix', opacity=0) win.flip() def setup_cal_display(self): txt = TextStim( self.win, text= "Please follow the dot. Try not to anticipate its movements.", pos=(0, 100), color='black', units='pix') txt.draw() self.targetout.draw() self.win.flip() def exit_cal_display(self): self.clear_cal_display() def clear_cal_display(self): self.setup_cal_display() def erase_cal_target(self): self.win.flip() def draw_cal_target(self, x, y): # Convert to psychopy coordinates x = x - (self.win.size[0] / 2) y = -(y - (self.win.size[1] / 2)) # Set calibration target position self.targetout.pos = (x, y) self.targetin.pos = (x, y) # Display self.targetout.draw() self.targetin.draw() self.win.flip() def alert_printf(self, msg): print("alert_printf %s" % msg) def play_beep(self, beepid): if beepid == pylink.DC_TARG_BEEP or beepid == pylink.CAL_TARG_BEEP: self.__target_beep__.play() elif beepid == pylink.CAL_ERR_BEEP or beepid == pylink.DC_ERR_BEEP: self.__target_beep__error__.play() else: # CAL_GOOD_BEEP or DC_GOOD_BEEP self.__target_beep__done__.play() def get_input_key(self): ky = [] v = event.getKeys() for key in v: pylink_key = None if len(key) == 1: pylink_key = ord(key) elif key == "escape": pylink_key = pylink.ESC_KEY elif key == "return": pylink_key = pylink.ENTER_KEY elif key == "pageup": pylink_key = pylink.PAGE_UP elif key == "pagedown": pylink_key = pylink.PAGE_DOWN elif key == "up": pylink_key = pylink.CURS_UP elif key == "down": pylink_key = pylink.CURS_DOWN elif key == "left": pylink_key = pylink.CURS_LEFT elif key == "right": pylink_key = pylink.CURS_RIGHT else: print(f'Error! :{key} is not a used key.') return ky.append(pylink.KeyInput(pylink_key, 0)) return ky def record_abort_hide(self): pass def setup_image_display(self, width, height): self.size = (width / 2, height / 2) self.clear_cal_display() self.last_mouse_state = -1 # Create array to hold image data later if self.rgb_index_array is None: self.rgb_index_array = np.zeros((self.size[1], self.size[0]), dtype=np.uint8) def exit_image_display(self): self.clear_cal_display() def image_title(self, text): # Display or update Pupil/CR info on image screen if self.imagetitlestim is None: self.imagetitlestim = TextStim( self.window, text=text, pos=(0, self.window.size[1] / 2 - 15), height=28, color=self.txtcol, alignHoriz='center', alignVert='top', wrapWidth=self.window.size[0] * .8, units='pix') else: self.imagetitlestim.setText(text) def exit_image_display(self): self.clear_cal_display() def draw_image_line(self, width, line, totlines, buff): # Get image info for each line of image for i in range(width): self.rgb_index_array[line - 1, i] = buff[i] # Once all lines are collected turn into an image to display if line == totlines: # Make image image = scipy.misc.toimage(self.rgb_index_array, pal=self.rgb_pallete, mode='P') # Resize Image if self.imgstim_size is None: maxsz = self.sres[0] / 2 mx = 1.0 while (mx + 1) * self.size[0] <= maxsz: mx += 1.0 self.imgstim_size = int(self.size[0] * mx), int( self.size[1] * mx) image = image.resize(self.imgstim_size) # Save image as a temporay file tfile = os.path.join(tempfile.gettempdir(), '_eleye.png') image.save(tfile, 'PNG') # Need this for target distance to show up self.__img__ = image self.draw_cross_hair() self.__img__ = None # Create eye image if self.eye_image is None: self.eye_image = visual.ImageStim(self.window, tfile, size=self.imgstim_size, units='pix') else: self.eye_image.setImage(tfile) # Redraw the Camera Setup Mode graphics self.eye_image.draw() if self.imagetitlestim: self.imagetitlestim.draw() # Display self.window.flip() def set_image_palette(self, r, g, b): # This does something the other image functions need self.clear_cal_display() sz = len(r) self.rgb_pallete = np.zeros((sz, 3), dtype=np.uint8) i = 0 while i < sz: self.rgb_pallete[i:] = int(r[i]), int(g[i]), int(b[i]) i += 1 def dummynote(self): # Draw Text visual.TextStim(self.window, text='Dummy Connection with EyeLink', color=self.txtcol).draw() self.window.flip() # Wait for key press event.waitKeys() self.window.flip()