# pause screen
scr.clear()
scr.draw_text(text="Press Space to continue.")
disp.fill(scr)
disp.show()
kb.get_key(keylist=["space"], timeout=None, flush=True)


# # # # #
# IMAGES

# loop through images
for imgpath in IMAGES:
	# draw image
	scr.clear(colour=(255,255,255))
	scr.draw_image(imgpath)
	disp.fill(scr)
	# start recording
	tracker.start_recording()
	tracker.log("IMAGE_TRIALSTART")
	tracker.log("imgname=%s" % (os.path.basename(imgpath)))
	# show display
	disp.show()
	tracker.log("image_on")
	# wait for a bit
	clock.pause(IMGTIME)
	# clear screen
	scr.clear()
	disp.fill(scr)
	disp.show()
	# stop recording
Esempio n. 2
0
                # Make a PyGame Surface out of the NumPy array.
                frame = pygame.surfarray.make_surface(frame)

        # If loading fails, generate a black frame instead.
        if not success:
            if DISPTYPE == 'psychopy':
                frame = numpy.zeros((height, width, 3), dtype=float)
            elif DISPTYPE == 'pygame':
                frame = pygame.Surface((width, height))

        if DISPTYPE == 'psychopy':
            # Set the ImageStim's image to the loaded frame.
            stimscr.screen[stim_index].setImage(frame)
        elif DISPTYPE == 'pygame':
            # Draw the Surface (automatically detected format by draw_image).
            stimscr.draw_image(frame)

        # Present the new frame. The disp.show call will block until the start
        # of the next refresh cycle.
        disp.fill(stimscr)
        frametime = disp.show()
        pc_frametime = datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S.%f')
        tracker.log("FRAMENR %d; TIME %.3f; PCTIME %s" % \
            (framenr, frametime, pc_frametime))

        # Compute the loading duration.
        loaddur = frametime - loadstart

        # Wait for the frame duration (corrected for the load duration, and
        # including 10 milliseconds of buffer time).
        timer.pause(int(framedur - (loaddur + 5)))
Esempio n. 3
0
    scr.clear()
    scr.draw_text("Function %s works! Press space to test the next" %
                  str(eventfuncs[i]))
    disp.fill(scr)
    disp.show()
    kb.get_key()

# # # # #
# test gaze contingency

# AOI
scr.clear()
scr.draw_text("There should be an image in the centre of the screen",
              pos=(DISPSIZE[0] / 2, DISPSIZE[1] / 10))
scr.draw_image(
    imagefile
)  # imginfo: 400x600 px; kitten head position relative to image x=40, y=160, w=130, h=140
x = (
    DISPSIZE[0] / 2 - 200
) + 40  # centre minus half of the image width, plus kitten head X position in image
y = (
    DISPSIZE[1] / 2 - 300
) + 160  # centre minus half of the image height, plus kitten head Y position in image
aoi = AOI('rectangle', (x, y), (130, 140))
disp.fill(scr)
t1 = disp.show()
log.write(["AOI", t1])
key = None
tracker.start_recording()
while key != 'space':
    # check for key input
Esempio n. 4
0
class EyelinkGraphics(custom_display):

	"""
	Implements the EyeLink graphics that are shown on the experimental PC, such
	as the camera image, and the calibration dots. This class only implements
	the drawing operations, and little to no of the logic behind the set-up,
	which is implemented in PyLink.
	"""

	def __init__(self, libeyelink, tracker):

		"""
		Constructor.

		Arguments:
		libeyelink	--	A libeyelink object.
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

		pylink.EyeLinkCustomDisplay.__init__(self)

		# objects
		self.libeyelink = libeyelink
		self.display = libeyelink.display
		self.screen = Screen(disptype=DISPTYPE, mousevisible=False)
		self.kb = Keyboard(keylist=None, timeout=0)
		self.mouse = Mouse(timeout=0)
		if DISPTYPE == 'pygame':
			self.kb.set_timeout(timeout=0.001)
		# If we are using a DISPTYPE that cannot be used directly, we have to
		# save the camera image to a temporary file on each frame.
		#if DISPTYPE not in ('pygame', 'psychopy'):
		import tempfile
		import os
		self.tmp_file = os.path.join(tempfile.gettempdir(), '__eyelink__.jpg')
		# drawing properties
		self.xc = self.display.dispsize[0]/2
		self.yc = self.display.dispsize[1]/2
		self.extra_info = True
		self.ld = 40 # line distance
		self.fontsize = libeyelink.fontsize
		self.title = ""
		self.display_open = True
		# menu
		self.menuscreen = Screen(disptype=DISPTYPE, mousevisible=False)		
		self.menuscreen.draw_text(text="Eyelink calibration menu",
			pos=(self.xc,self.yc-6*self.ld), center=True, font='mono',
			fontsize=int(2*self.fontsize), antialias=True)
		self.menuscreen.draw_text(text="%s (pygaze %s, pylink %s)" \
			% (libeyelink.eyelink_model, pygaze.version, pylink.__version__),
			pos=(self.xc,self.yc-5*self.ld), center=True,
			font='mono', fontsize=int(.8*self.fontsize), antialias=True)
		self.menuscreen.draw_text(text="Press C to calibrate", 
			pos=(self.xc, self.yc-3*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press V to validate",
			pos=(self.xc, self.yc-2*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press A to auto-threshold",
			pos=(self.xc,self.yc-1*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press I to toggle extra info in camera image",
			pos=(self.xc,self.yc-0*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press Enter to show camera image",
			pos=(self.xc,self.yc+1*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(
			text="(then change between images using the arrow keys)",
			pos=(self.xc, self.yc+2*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		self.menuscreen.draw_text(text="Press Escape to abort experiment",
			pos=(self.xc, self.yc+4*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)			
		self.menuscreen.draw_text(text="Press Q to exit menu",
			pos=(self.xc, self.yc+5*self.ld), center=True, font='mono',
			fontsize=self.fontsize, antialias=True)
		# beeps
		self.__target_beep__ = Sound(osc='sine', freq=440, length=50, 
			attack=0, decay=0, soundfile=None)
		self.__target_beep__done__ = Sound(osc='sine', freq=880, length=200,
			attack=0, decay=0, soundfile=None)
		self.__target_beep__error__ = Sound(osc='sine', freq=220, length=200,
			attack=0, decay=0, soundfile=None)
		# Colors
		self.color = {
			pylink.CR_HAIR_COLOR:			pygame.Color('white'),
			pylink.PUPIL_HAIR_COLOR:		pygame.Color('white'),
			pylink.PUPIL_BOX_COLOR:			pygame.Color('green'),
			pylink.SEARCH_LIMIT_BOX_COLOR:	pygame.Color('red'),
			pylink.MOUSE_CURSOR_COLOR:		pygame.Color('red'),	
			'font':							pygame.Color('white'),		
			}
		# Font
		pygame.font.init()
		self.font = pygame.font.SysFont('Courier New', 11)
		# further properties
		self.state = None
		self.pal = None
		
		self.size = (0,0)
		self.set_tracker(tracker)
		self.last_mouse_state = -1
		self.bit64 = '64bit' in platform.architecture()
		self.imagebuffer = self.new_array()		
		
	def close(self):
	
		"""
		Is called when the connection and display are shutting down.		
		"""
		
		self.display_open = False
		
	def new_array(self):
	
		"""
		Creates a new array with a system-specific format.
		
		Returns:
		An array.
		"""
		
		# On 64 bit Linux, we need to use an unsigned int data format.
		# <https://www.sr-support.com/showthread.php?3215-Visual-glitch-when-/
		# sending-eye-image-to-display-PC&highlight=ubuntu+pylink>
		if os.name == 'posix' and self.bit64:
			return array.array('I')
		return array.array('L')

	def set_tracker(self, tracker):

		"""
		Connects the tracker to the graphics environment.

		Arguments:
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

		self.tracker = tracker
		self.tracker_version = tracker.getTrackerVersion()
		if self.tracker_version >= 3:
			self.tracker.sendCommand("enable_search_limits=YES")
			self.tracker.sendCommand("track_search_limits=YES")
			self.tracker.sendCommand("autothreshold_click=YES")
			self.tracker.sendCommand("autothreshold_repeat=YES")
			self.tracker.sendCommand("enable_camera_position_detect=YES")

	def setup_cal_display(self):

		"""
		Sets up the initial calibration display, which contains a menu with
		instructions.
		"""
		
		# show instructions
		self.display.fill(self.menuscreen)
		self.display.show()

	def exit_cal_display(self):

		"""Exits calibration display."""

		self.clear_cal_display()

	def record_abort_hide(self):

		"""TODO: What does this do?"""

		pass

	def clear_cal_display(self):

		"""Clears the calibration display"""

		self.display.fill()
		self.display.show()

	def erase_cal_target(self):

		"""TODO: What does this do?"""

		self.clear_cal_display()

	def draw_cal_target(self, x, y):

		"""
		Draws calibration target.

		Arguments:
		x		--	The X coordinate of the target.
		y		--	The Y coordinate of the target.
		"""

		self.play_beep(pylink.CAL_TARG_BEEP)
		self.screen.clear()		
		self.screen.draw_fixation(fixtype='dot', pos=(x,y))
		self.display.fill(screen=self.screen)
		self.display.show()

	def play_beep(self, beepid):

		"""
		Plays a sound.

		Arguments:
		beepid		--	A number that identifies the sound.
		"""

		if beepid == pylink.CAL_TARG_BEEP:
			# For some reason, playing the beep here doesn't work, so we have
			# to play it when the calibration target is drawn.
			if EYELINKCALBEEP:
				self.__target_beep__.play()			
		elif beepid == pylink.CAL_ERR_BEEP or beepid == pylink.DC_ERR_BEEP:
			# show a picture
			self.screen.clear()
			self.screen.draw_text(
				text="calibration lost, press 'Enter' to return to menu",
				pos=(self.xc,self.yc), center=True, font='mono',
				fontsize=self.fontsize, antialias=True)
			self.display.fill(self.screen)
			self.display.show()
			# play beep
			self.__target_beep__error__.play()
		elif beepid == pylink.CAL_GOOD_BEEP:
			self.screen.clear()
			if self.state == "calibration":
				self.screen.draw_text(
					text="Calibration succesfull, press 'v' to validate",
					pos=(self.xc,self.yc), center=True, font='mono',
					fontsize=self.fontsize, antialias=True)
			elif self.state == "validation":
				self.screen.draw_text(
					text="Validation succesfull, press 'Enter' to return to menu",
					pos=(self.xc,self.yc), center=True, font='mono',
					fontsize=self.fontsize, antialias=True)				
			else:
				self.screen.draw_text(text="Press 'Enter' to return to menu",
					pos=(self.xc,self.yc), center=True, font='mono',
					fontsize=self.fontsize, antialias=True)
			# show screen
			self.display.fill(self.screen)
			self.display.show()
			# play beep
			self.__target_beep__done__.play()
		else: #	DC_GOOD_BEEP	or DC_TARG_BEEP
			pass

	def draw_line(self, x1, y1, x2, y2, colorindex):

		"""
		Unlike the function name suggests, this draws a single pixel. I.e.
		the end coordinates are always exactly one pixel away from the start
		coordinates.
		
		Arguments:
		x1			--	The starting x.
		y1			--	The starting y.
		x2			--	The end x.
		y2			--	The end y.
		colorIndex	--	A color index.
		"""

		x1 = int(self.scale*x1)
		y1 = int(self.scale*y1)
		x2 = int(self.scale*x2)
		y2 = int(self.scale*y2)			
		pygame.draw.line(self.cam_img, self.color[colorindex], (x1, y1),
			(x2, y2))
		
	def draw_lozenge(self, x, y, w, h, colorindex):

		"""
		desc:
			Draws a rectangle.
			
		arguments:
			x:
				desc:	X coordinate.
				type:	int
			y:
				desc:	Y coordinate.
				type:	int
			w:
				desc:	A width.
				type:	int
			h:
				desc:	A height.
				type:	int
			colorindex:
				desc:	A colorindex.
				type:	int
		"""

		x = int(self.scale*x)
		y = int(self.scale*y)
		w = int(self.scale*w)
		h = int(self.scale*h)		
		pygame.draw.rect(self.cam_img, self.color[colorindex], (x, y, w, h), 2)
		
	def draw_title(self):
	
		"""
		desc:
			Draws title info.
		"""
	
		y = 0
		for line in self.title:
			surf = self.font.render(line, 0, self.color['font'])
			self.cam_img.blit(surf, (1, y))
			y += 12

	def get_mouse_state(self):

		"""
		desc:
			Gets the mouse position and state.
			
		returns:
			desc:	A (pos, state) tuple.
			type:	tuple.		
		"""
		
		button, pos, time = self.mouse.get_clicked()
		if button == None:
			button = -1
		if pos == None:
			pos = self.mouse.get_pos()
		return pos, button

	def get_input_key(self):

		"""
		Gets an input key.

		Returns:
		A list containing a single pylink key identifier.
		"""

		# Don't try to collect key presses when the display is no longer
		# available. This is necessary, because pylink polls key presses during
		# file transfer, which generally occurs after the display has been
		# closed.
		if not self.display_open:
			return None
		try:
			key, time = self.kb.get_key(keylist=None, timeout='default')
		except:
			self.esc_pressed = True
			key = 'q'
		if key == None:
			return None
		# Escape functions as a 'q' with the additional esc_pressed flag
		if key == 'escape':
			key = 'q'
			self.esc_pressed = True
		# Process regular keys
		if key == "return":
			keycode = pylink.ENTER_KEY
			self.state = None
		elif key == "space":
			keycode = ord(" ")
		elif key == "q":
			keycode = pylink.ESC_KEY
			self.state = None
		elif key == "c":
			keycode = ord("c")
			self.state = "calibration"
		elif key == "v":
			keycode = ord("v")
			self.state = "validation"
		elif key == "a":
			keycode = ord("a")
		elif key == "i":
			self.extra_info = not self.extra_info
			keycode = 0
		elif key == "up":
			keycode = pylink.CURS_UP
		elif key == "down":
			keycode = pylink.CURS_DOWN
		elif key == "left":
			keycode = pylink.CURS_LEFT
		elif key == "right":
			keycode = pylink.CURS_RIGHT
		else:
			keycode = 0
		# Convert key to PyLink keycode and return
		return [pylink.KeyInput(keycode, 0)] # 0 = pygame.KMOD_NONE

	def exit_image_display(self):

		"""Exits the image display."""

		self.clear_cal_display()

	def alert_printf(self,msg):

		"""
		Prints alert message.

		Arguments:
		msg		--	The message to be played.
		"""

		print "eyelink_graphics.alert_printf(): %s" % msg

	def setup_image_display(self, width, height):

		"""
		Initializes the buffer that will contain the camera image.

		Arguments:
		width		--	The width of the image.
		height		--	The height of the image.
		"""

		self.size = width, height
		self.clear_cal_display()
		self.last_mouse_state = -1
		self.imagebuffer = self.new_array()

	def image_title(self, text):

		"""
		Sets the current image title.

		Arguments:
		text	--	An image title.
		"""

		while ': ' in text:
			text = text.replace(': ', ':')
		self.title = text.split()
		
	def draw_image_line(self, width, line, totlines, buff):

		"""
		Draws a single eye video frame, line by line.

		Arguments:

		width		--	Width of the video.
		line		--	Line nr of current line.
		totlines	--	Total lines in video.
		buff		--	Frame buffer.
		imagesize	--	The size of the image, which is (usually?) 192x160 px.
		"""

		# If the buffer hasn't been filled yet, add a line.
		for i in range(width):
			try:
				self.imagebuffer.append(self.pal[buff[i]])
			except:
				pass
		# If the buffer is full, push it to the display.
		if line == totlines:
			self.scale = totlines/320.
			self._size = int(self.scale*self.size[0]), int(
				self.scale*self.size[1])
			# Convert the image buffer to a pygame image, save it ...			
			self.cam_img = pygame.image.fromstring(self.imagebuffer.tostring(),
				self._size, 'RGBX')
			if self.extra_info:
				self.draw_cross_hair()				
				self.draw_title()
			pygame.image.save(self.cam_img, self.tmp_file)
			# ... and then show the image.
			self.screen.clear()
			self.screen.draw_image(self.tmp_file, scale=1.5/self.scale)
			self.display.fill(self.screen)
			self.display.show()			
			# Clear the buffer for the next round!
			self.imagebuffer = self.new_array()

	def set_image_palette(self, r, g, b):

		"""
		Sets the image palette.

		TODO: What this function actually does is highly mysterious. Figure it
		out!

		Arguments:
		r		--	The red channel.
		g		--	The green channel.
		b		--	The blue channel.
		"""

		self.imagebuffer = self.new_array()
		self.clear_cal_display()
		sz = len(r)
		i = 0
		self.pal = []
		while i < sz:
			rf = int(b[i])
			gf = int(g[i])
			bf = int(r[i])
			self.pal.append((rf<<16) | (gf<<8) | (bf))
			i += 1
Esempio n. 5
0
		print(itis[0])
		for ii in range(TRIALS_PER_BLOCK): # loop through all the trials 
			trials[run][i][ii] = [[]] * 6
			trials[run][i][ii][0] = prefix + '_' + str(ii) + '.jpg' #image name 
			trials[run][i][ii][1] = conds[ii] # trial type 
			trials[run][i][ii][2] = itis[ii] # iti time
			trials[run][i][ii][3] = onsets[ii] # signal onset time 
			trials[run][i][ii][4] = [[]] * 3
			trials[run][i][ii][5] = block
			# now pre-generate the screens! 
			# Note: this is code efficient but not memory efficient (i.e. I am lazy and would rather pre-load almost twice the number of screens, because this is why we have RAM)

			tempstim = Screen()
			#tempstim.draw_image(RESDIR + trials[run][i][ii][0], pos=DISPCENTRE)# draw face on center of screen 

			tempstim.draw_image(os.path.join(RESDIR, trials[run][i][ii][0]), pos=DISPCENTRE, scale=0.5)# draw face on center of screen 
			trials[run][i][ii][4][0] = tempstim

			tempsig = Screen()
			#tempsig.draw_image(RESDIR + trials[run][i][ii][0], pos=DISPCENTRE)# draw face on center of screen
			tempsig.draw_image(os.path.join(RESDIR, trials[run][i][ii][0]), pos=DISPCENTRE, scale=0.5)# draw face on center of screen 

			tempfeed = Screen()
			tempfeed.draw_image(os.path.join(RESDIR, trials[run][i][ii][0]), pos=DISPCENTRE, scale=0.5)#
			#RESPMAP 0 = go squares, no-go circles 

			square_sz = 100
			square_off = square_sz/2
			pen_width = 6
			circle_sz = 50
			# 1 = go circles, no-go squares
Esempio n. 6
0
# -*- coding: utf-8 -*-
"""
Created on Thu Nov 10 13:29:48 2016

@author: adam
"""

from pygaze.display import Display
from pygaze.screen import Screen
import pygaze.libtime as timer

# disp = Window(size=DISPSIZE, units='pix', fullscr=True)
disp = Display()
fixscreen = Screen()
fixscreen.draw_fixation(fixtype='dot')

imgscreen = Screen()
imgscreen.draw_image('/home/adam/Desktop/experiment0/Example.png')

disp.fill(fixscreen)
disp.show()
timer.pause(1000)

disp.fill(imgscreen)
disp.show()
timer.pause(2000)

disp.close()
Esempio n. 7
0
class EyelinkGraphics(custom_display):

    """
	Implements the EyeLink graphics that are shown on the experimental PC, such
	as the camera image, and the calibration dots. This class only implements
	the drawing operations, and little to no of the logic behind the set-up,
	which is implemented in PyLink.
	"""

    def __init__(self, libeyelink, tracker):

        """
		Constructor.

		Arguments:
		libeyelink	--	A libeyelink object.
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

        pylink.EyeLinkCustomDisplay.__init__(self)

        # objects
        self.libeyelink = libeyelink
        self.display = libeyelink.display
        self.screen = Screen(disptype=DISPTYPE, mousevisible=False)
        self.kb = Keyboard(keylist=None, timeout=0)
        self.mouse = Mouse(timeout=0)
        if DISPTYPE == "pygame":
            self.kb.set_timeout(timeout=0.001)
            # If we are using a DISPTYPE that cannot be used directly, we have to
            # save the camera image to a temporary file on each frame.
            # if DISPTYPE not in ('pygame', 'psychopy'):
        import tempfile
        import os

        self.tmp_file = os.path.join(tempfile.gettempdir(), "__eyelink__.jpg")
        # drawing properties
        self.xc = self.display.dispsize[0] / 2
        self.yc = self.display.dispsize[1] / 2
        self.extra_info = True
        self.ld = 40  # line distance
        self.fontsize = libeyelink.fontsize
        self.title = ""
        self.display_open = True
        # menu
        self.menuscreen = Screen(disptype=DISPTYPE, mousevisible=False)
        self.menuscreen.draw_text(
            text="Eyelink calibration menu",
            pos=(self.xc, self.yc - 6 * self.ld),
            center=True,
            font="mono",
            fontsize=int(2 * self.fontsize),
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="%s (pygaze %s, pylink %s)" % (libeyelink.eyelink_model, pygaze.version, pylink.__version__),
            pos=(self.xc, self.yc - 5 * self.ld),
            center=True,
            font="mono",
            fontsize=int(0.8 * self.fontsize),
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press C to calibrate",
            pos=(self.xc, self.yc - 3 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press V to validate",
            pos=(self.xc, self.yc - 2 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press A to auto-threshold",
            pos=(self.xc, self.yc - 1 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press I to toggle extra info in camera image",
            pos=(self.xc, self.yc - 0 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press Enter to show camera image",
            pos=(self.xc, self.yc + 1 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="(then change between images using the arrow keys)",
            pos=(self.xc, self.yc + 2 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press Escape to abort experiment",
            pos=(self.xc, self.yc + 4 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        self.menuscreen.draw_text(
            text="Press Q to exit menu",
            pos=(self.xc, self.yc + 5 * self.ld),
            center=True,
            font="mono",
            fontsize=self.fontsize,
            antialias=True,
        )
        # beeps
        self.__target_beep__ = Sound(osc="sine", freq=440, length=50, attack=0, decay=0, soundfile=None)
        self.__target_beep__done__ = Sound(osc="sine", freq=880, length=200, attack=0, decay=0, soundfile=None)
        self.__target_beep__error__ = Sound(osc="sine", freq=220, length=200, attack=0, decay=0, soundfile=None)
        # Colors
        self.color = {
            pylink.CR_HAIR_COLOR: pygame.Color("white"),
            pylink.PUPIL_HAIR_COLOR: pygame.Color("white"),
            pylink.PUPIL_BOX_COLOR: pygame.Color("green"),
            pylink.SEARCH_LIMIT_BOX_COLOR: pygame.Color("red"),
            pylink.MOUSE_CURSOR_COLOR: pygame.Color("red"),
            "font": pygame.Color("white"),
        }
        # Font
        pygame.font.init()
        self.font = pygame.font.SysFont("Courier New", 11)
        # further properties
        self.state = None
        self.pal = None

        self.size = (0, 0)
        self.set_tracker(tracker)
        self.last_mouse_state = -1
        self.bit64 = "64bit" in platform.architecture()
        self.imagebuffer = self.new_array()

    def close(self):

        """
		Is called when the connection and display are shutting down.		
		"""

        self.display_open = False

    def new_array(self):

        """
		Creates a new array with a system-specific format.
		
		Returns:
		An array.
		"""

        # On 64 bit Linux, we need to use an unsigned int data format.
        # <https://www.sr-support.com/showthread.php?3215-Visual-glitch-when-/
        # sending-eye-image-to-display-PC&highlight=ubuntu+pylink>
        if os.name == "posix" and self.bit64:
            return array.array("I")
        return array.array("L")

    def set_tracker(self, tracker):

        """
		Connects the tracker to the graphics environment.

		Arguments:
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

        self.tracker = tracker
        self.tracker_version = tracker.getTrackerVersion()
        if self.tracker_version >= 3:
            self.tracker.sendCommand("enable_search_limits=YES")
            self.tracker.sendCommand("track_search_limits=YES")
            self.tracker.sendCommand("autothreshold_click=YES")
            self.tracker.sendCommand("autothreshold_repeat=YES")
            self.tracker.sendCommand("enable_camera_position_detect=YES")

    def setup_cal_display(self):

        """
		Sets up the initial calibration display, which contains a menu with
		instructions.
		"""

        # show instructions
        self.display.fill(self.menuscreen)
        self.display.show()

    def exit_cal_display(self):

        """Exits calibration display."""

        self.clear_cal_display()

    def record_abort_hide(self):

        """TODO: What does this do?"""

        pass

    def clear_cal_display(self):

        """Clears the calibration display"""

        self.display.fill()
        self.display.show()

    def erase_cal_target(self):

        """TODO: What does this do?"""

        self.clear_cal_display()

    def draw_cal_target(self, x, y):

        """
		Draws calibration target.

		Arguments:
		x		--	The X coordinate of the target.
		y		--	The Y coordinate of the target.
		"""

        self.play_beep(pylink.CAL_TARG_BEEP)
        self.screen.clear()
        self.screen.draw_fixation(fixtype="dot", pos=(x, y))
        self.display.fill(screen=self.screen)
        self.display.show()

    def play_beep(self, beepid):

        """
		Plays a sound.

		Arguments:
		beepid		--	A number that identifies the sound.
		"""

        if beepid == pylink.CAL_TARG_BEEP:
            # For some reason, playing the beep here doesn't work, so we have
            # to play it when the calibration target is drawn.
            if EYELINKCALBEEP:
                self.__target_beep__.play()
        elif beepid == pylink.CAL_ERR_BEEP or beepid == pylink.DC_ERR_BEEP:
            # show a picture
            self.screen.clear()
            self.screen.draw_text(
                text="calibration lost, press 'Enter' to return to menu",
                pos=(self.xc, self.yc),
                center=True,
                font="mono",
                fontsize=self.fontsize,
                antialias=True,
            )
            self.display.fill(self.screen)
            self.display.show()
            # play beep
            self.__target_beep__error__.play()
        elif beepid == pylink.CAL_GOOD_BEEP:
            self.screen.clear()
            if self.state == "calibration":
                self.screen.draw_text(
                    text="Calibration succesfull, press 'v' to validate",
                    pos=(self.xc, self.yc),
                    center=True,
                    font="mono",
                    fontsize=self.fontsize,
                    antialias=True,
                )
            elif self.state == "validation":
                self.screen.draw_text(
                    text="Validation succesfull, press 'Enter' to return to menu",
                    pos=(self.xc, self.yc),
                    center=True,
                    font="mono",
                    fontsize=self.fontsize,
                    antialias=True,
                )
            else:
                self.screen.draw_text(
                    text="Press 'Enter' to return to menu",
                    pos=(self.xc, self.yc),
                    center=True,
                    font="mono",
                    fontsize=self.fontsize,
                    antialias=True,
                )
                # show screen
            self.display.fill(self.screen)
            self.display.show()
            # play beep
            self.__target_beep__done__.play()
        else:  # 	DC_GOOD_BEEP	or DC_TARG_BEEP
            pass

    def draw_line(self, x1, y1, x2, y2, colorindex):

        """
		Unlike the function name suggests, this draws a single pixel. I.e.
		the end coordinates are always exactly one pixel away from the start
		coordinates.
		
		Arguments:
		x1			--	The starting x.
		y1			--	The starting y.
		x2			--	The end x.
		y2			--	The end y.
		colorIndex	--	A color index.
		"""

        x1 = int(self.scale * x1)
        y1 = int(self.scale * y1)
        x2 = int(self.scale * x2)
        y2 = int(self.scale * y2)
        pygame.draw.line(self.cam_img, self.color[colorindex], (x1, y1), (x2, y2))

    def draw_lozenge(self, x, y, w, h, colorindex):

        """
		desc:
			Draws a rectangle.
			
		arguments:
			x:
				desc:	X coordinate.
				type:	int
			y:
				desc:	Y coordinate.
				type:	int
			w:
				desc:	A width.
				type:	int
			h:
				desc:	A height.
				type:	int
			colorindex:
				desc:	A colorindex.
				type:	int
		"""

        x = int(self.scale * x)
        y = int(self.scale * y)
        w = int(self.scale * w)
        h = int(self.scale * h)
        pygame.draw.rect(self.cam_img, self.color[colorindex], (x, y, w, h), 2)

    def draw_title(self):

        """
		desc:
			Draws title info.
		"""

        y = 0
        for line in self.title:
            surf = self.font.render(line, 0, self.color["font"])
            self.cam_img.blit(surf, (1, y))
            y += 12

    def get_mouse_state(self):

        """
		desc:
			Gets the mouse position and state.
			
		returns:
			desc:	A (pos, state) tuple.
			type:	tuple.		
		"""

        button, pos, time = self.mouse.get_clicked()
        if button == None:
            button = -1
        if pos == None:
            pos = self.mouse.get_pos()
        return pos, button

    def get_input_key(self):

        """
		Gets an input key.

		Returns:
		A list containing a single pylink key identifier.
		"""

        # Don't try to collect key presses when the display is no longer
        # available. This is necessary, because pylink polls key presses during
        # file transfer, which generally occurs after the display has been
        # closed.
        if not self.display_open:
            return None
        try:
            key, time = self.kb.get_key(keylist=None, timeout="default")
        except:
            self.esc_pressed = True
            key = "q"
        if key == None:
            return None
            # Escape functions as a 'q' with the additional esc_pressed flag
        if key == "escape":
            key = "q"
            self.esc_pressed = True
            # Process regular keys
        if key == "return":
            keycode = pylink.ENTER_KEY
            self.state = None
        elif key == "space":
            keycode = ord(" ")
        elif key == "q":
            keycode = pylink.ESC_KEY
            self.state = None
        elif key == "c":
            keycode = ord("c")
            self.state = "calibration"
        elif key == "v":
            keycode = ord("v")
            self.state = "validation"
        elif key == "a":
            keycode = ord("a")
        elif key == "i":
            self.extra_info = not self.extra_info
            keycode = 0
        elif key == "up":
            keycode = pylink.CURS_UP
        elif key == "down":
            keycode = pylink.CURS_DOWN
        elif key == "left":
            keycode = pylink.CURS_LEFT
        elif key == "right":
            keycode = pylink.CURS_RIGHT
        else:
            keycode = 0
            # Convert key to PyLink keycode and return
        return [pylink.KeyInput(keycode, 0)]  # 0 = pygame.KMOD_NONE

    def exit_image_display(self):

        """Exits the image display."""

        self.clear_cal_display()

    def alert_printf(self, msg):

        """
		Prints alert message.

		Arguments:
		msg		--	The message to be played.
		"""

        print "eyelink_graphics.alert_printf(): %s" % msg

    def setup_image_display(self, width, height):

        """
		Initializes the buffer that will contain the camera image.

		Arguments:
		width		--	The width of the image.
		height		--	The height of the image.
		"""

        self.size = width, height
        self.clear_cal_display()
        self.last_mouse_state = -1
        self.imagebuffer = self.new_array()

    def image_title(self, text):

        """
		Sets the current image title.

		Arguments:
		text	--	An image title.
		"""

        while ": " in text:
            text = text.replace(": ", ":")
        self.title = text.split()

    def draw_image_line(self, width, line, totlines, buff):

        """
		Draws a single eye video frame, line by line.

		Arguments:

		width		--	Width of the video.
		line		--	Line nr of current line.
		totlines	--	Total lines in video.
		buff		--	Frame buffer.
		imagesize	--	The size of the image, which is (usually?) 192x160 px.
		"""

        # If the buffer hasn't been filled yet, add a line.
        for i in range(width):
            try:
                self.imagebuffer.append(self.pal[buff[i]])
            except:
                pass
                # If the buffer is full, push it to the display.
        if line == totlines:
            self.scale = totlines / 320.0
            self._size = int(self.scale * self.size[0]), int(self.scale * self.size[1])
            # Convert the image buffer to a pygame image, save it ...
            self.cam_img = pygame.image.fromstring(self.imagebuffer.tostring(), self._size, "RGBX")
            if self.extra_info:
                self.draw_cross_hair()
                self.draw_title()
            pygame.image.save(self.cam_img, self.tmp_file)
            # ... and then show the image.
            self.screen.clear()
            self.screen.draw_image(self.tmp_file, scale=1.5 / self.scale)
            self.display.fill(self.screen)
            self.display.show()
            # Clear the buffer for the next round!
            self.imagebuffer = self.new_array()

    def set_image_palette(self, r, g, b):

        """
		Sets the image palette.

		TODO: What this function actually does is highly mysterious. Figure it
		out!

		Arguments:
		r		--	The red channel.
		g		--	The green channel.
		b		--	The blue channel.
		"""

        self.imagebuffer = self.new_array()
        self.clear_cal_display()
        sz = len(r)
        i = 0
        self.pal = []
        while i < sz:
            rf = int(b[i])
            gf = int(g[i])
            bf = int(r[i])
            self.pal.append((rf << 16) | (gf << 8) | (bf))
            i += 1
Esempio n. 8
0
#scr.draw_fixation()
scr.clear()
scr.draw_text("There should be three fixation targets on the screen: \
\nred cross on the left, green X in the centre, and blue dot on the right", pos=(DISPSIZE[0]/2, DISPSIZE[1]/4))
scr.draw_fixation(fixtype='cross', colour=(255,0,0), pos=(DISPSIZE[0]*0.25,DISPSIZE[1]/2), pw=3, diameter=15)
scr.draw_fixation(fixtype='x', colour=(0,255,0), pos=(DISPSIZE[0]/2,DISPSIZE[1]/2), pw=3, diameter=15)
scr.draw_fixation(fixtype='dot', colour=(0,0,255), pos=(DISPSIZE[0]*0.75,DISPSIZE[1]/2), pw=3, diameter=15)
disp.fill(scr)
disp.show()
kb.get_key()

#scr.draw_image()
scr.clear()
scr.draw_text("There should be an image in the centre of the screen", pos=(DISPSIZE[0]/2, DISPSIZE[1]/10))
scr.draw_image(imagefile)
disp.fill(scr)
disp.show()
kb.get_key()

#scr.set_background_colour()
scr.set_background_colour(colour=(200,100,100))
scr.clear()
scr.draw_text("This screen should a different background colour than the previous screen", pos=(DISPSIZE[0]/2, DISPSIZE[1]/4))
disp.fill(scr)
disp.show()
kb.get_key()
scr.set_background_colour(BGC)


# # # # #
Esempio n. 9
0
# initialize a keyboard
kb = Keyboard(keylist=['space'],timeout=None)

# initialize a Timer
timer = Time()

# create a new logfile
log = Logfile(filename="test")
log.write(["x_pos","y_pos", "time"])

# # # # #
# test gaze contingency

# UI test
scr.clear()
scr.draw_image(image_file)
x = (DISPSIZE[0] - IMGSIZE[0]) / 2 # centre minus half of the image width
y = (DISPSIZE[1] - IMGSIZE[1]) / 2 # centre minus half of the image height
aoi = AOI('rectangle', (x,y), IMGSIZE)
disp.fill(scr)
t1 = disp.show()
key = None
tracker.start_recording()
while key != 'space':
    # check for key input
    key, presstime = kb.get_key(keylist=['space'],timeout=1)
    # get gaze position
    gazepos = tracker.sample()
    gazetime = clock.get_time() - t1
    if aoi.contains(gazepos):
        print(gazepos)
Esempio n. 10
0
class EyelinkGraphics(custom_display):

	"""
	Implements the EyeLink graphics that are shown on the experimental PC, such
	as the camera image, and the calibration dots. This class only implements
	the drawing operations, and little to no of the logic behind the set-up,
	which is implemented in PyLink.
	"""

	def __init__(self, display, tracker):

		"""
		Constructor.

		Arguments:
		display		--	A PyGaze Display object.
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

		pylink.EyeLinkCustomDisplay.__init__(self)

		# objects
		self.display = display
		self.screen = Screen(disptype=DISPTYPE, mousevisible=False)
		self.kb = Keyboard(keylist=None, timeout=1)
		if DISPTYPE == 'pygame':
			self.kb.set_timeout(timeout=0.001)
		# If we are using a DISPTYPE that cannot be used directly, we have to
		# save the camera image to a temporary file on each frame.
		#if DISPTYPE not in ('pygame', 'psychopy'):
		import tempfile
		import os
		self.tmp_file = os.path.join(tempfile.gettempdir(), \
			'__eyelink__.jpg')
		# drawing properties
		self.xc = self.display.dispsize[0]/2
		self.yc = self.display.dispsize[1]/2
		self.ld = 40 # line distance
		# menu
		self.menuscreen = Screen(disptype=DISPTYPE, mousevisible=False)
		self.menuscreen.draw_text(text="== Eyelink calibration menu ==", pos= \
			(self.xc,self.yc-5*self.ld), center=True, font='mono', fontsize= \
			12, antialias=True)
		self.menuscreen.draw_text(text="Press C to calibrate", pos=(self.xc, \
			self.yc-3*self.ld), center=True, font='mono', fontsize=12, \
			antialias=True)
		self.menuscreen.draw_text(text="Press V to validate", pos=(self.xc, \
			self.yc-2*self.ld), center=True, font='mono', fontsize=12, \
			antialias=True)
		self.menuscreen.draw_text(text="Press A to auto-threshold", pos=( \
			self.xc,self.yc-1*self.ld), center=True, font='mono', fontsize=12, \
			antialias=True)
		self.menuscreen.draw_text(text="Press Enter to show camera image", \
			pos=(self.xc,self.yc+1*self.ld), center=True, font='mono', \
			fontsize=12, antialias=True)
		self.menuscreen.draw_text(text= \
			"(then change between images using the arrow keys)", pos=(self.xc, \
			self.yc+2*self.ld), center=True, font='mono', fontsize=12, \
			antialias=True)
		self.menuscreen.draw_text(text="Press Q to exit menu", pos=(self.xc, \
			self.yc+5*self.ld), center=True, font='mono', fontsize=12, \
			antialias=True)
		# beeps
		self.__target_beep__ = Sound(osc='sine', freq=440, length=50, attack= \
			0, decay=0, soundfile=None)
		self.__target_beep__done__ = Sound(osc='sine', freq=880, length=200, \
			attack=0, decay=0, soundfile=None)
		self.__target_beep__error__ = Sound(osc='sine', freq=220, length=200, \
			attack=0, decay=0, soundfile=None)
		# further properties
		self.state = None
		self.imagebuffer = array.array('l')
		self.pal = None
		self.size = (0,0)
		self.set_tracker(tracker)
		self.last_mouse_state = -1

	def set_tracker(self, tracker):

		"""
		Connects the tracker to the graphics environment.

		Arguments:
		tracker		--	An tracker object as returned by pylink.EyeLink().
		"""

		self.tracker = tracker
		self.tracker_version = tracker.getTrackerVersion()
		if self.tracker_version >= 3:
			self.tracker.sendCommand("enable_search_limits=YES")
			self.tracker.sendCommand("track_search_limits=YES")
			self.tracker.sendCommand("autothreshold_click=YES")
			self.tracker.sendCommand("autothreshold_repeat=YES")
			self.tracker.sendCommand("enable_camera_position_detect=YES")

	def setup_cal_display(self):

		"""
		Sets up the initial calibration display, which contains a menu with
		instructions.
		"""
		
		# show instructions
		self.display.fill(self.menuscreen)
		self.display.show()

	def exit_cal_display(self):

		"""Exits calibration display."""

		self.clear_cal_display()

	def record_abort_hide(self):

		"""TODO: What does this do?"""

		pass

	def clear_cal_display(self):

		"""Clears the calibration display"""

		self.display.fill()
		self.display.show()

	def erase_cal_target(self):

		"""TODO: What does this do?"""

		self.clear_cal_display()

	def draw_cal_target(self, x, y):

		"""
		Draws calibration target.

		Arguments:
		x		--	The X coordinate of the target.
		y		--	The Y coordinate of the target.
		"""

		self.play_beep(pylink.CAL_TARG_BEEP)
		self.screen.clear()		
		self.screen.draw_fixation(fixtype='dot', pos=(x,y))
		self.display.fill(screen=self.screen)
		self.display.show()

	def play_beep(self, beepid):

		"""
		Plays a sound.

		Arguments:
		beepid		--	A number that identifies the sound.
		"""

		if beepid == pylink.CAL_TARG_BEEP:
			# For some reason, playing the beep here doesn't work, so we have
			# to play it when the calibration target is drawn.
			if EYELINKCALBEEP:
				self.__target_beep__.play()			
		elif beepid == pylink.CAL_ERR_BEEP or beepid == pylink.DC_ERR_BEEP:
			# show a picture
			self.screen.clear()
			self.screen.draw_text(text= \
				"calibration lost, press 'q' to return to menu", pos= \
				(self.xc,self.yc), center=True, font='mono', fontsize=12, \
				antialias=True)
			self.display.fill(self.screen)
			self.display.show()
			# play beep
			self.__target_beep__error__.play()
		elif beepid == pylink.CAL_GOOD_BEEP:
			self.screen.clear()
			if self.state == "calibration":
				self.screen.draw_text(text= \
					"Calibration succesfull, press 'v' to validate", pos= \
					(self.xc,self.yc), center=True, font='mono', fontsize=12, \
					antialias=True)
				pass
			elif self.state == "validation":
				self.screen.draw_text(text= \
					"Validation succesfull, press 'q' to return to menu", \
					pos=(self.xc,self.yc), center=True, font='mono', fontsize= \
					12, antialias=True)
				pass
			else:
				self.screen.draw_text(text="Press 'q' to return to menu", pos= \
					(self.xc,self.yc), center=True, font='mono', fontsize=12, \
					antialias=True)
				pass
			# show screen
			self.display.fill(self.screen)
			self.display.show()
			# play beep
			self.__target_beep__done__.play()
		else: #	DC_GOOD_BEEP	or DC_TARG_BEEP
			pass

	def getColorFromIndex(self, i):

		"""
		Maps a PyLink color code onto a color-name string.

		Arguments:
		i		--	A PyLink color code.

		Returns:
		A color-name string.
		"""

		print 'getColorFromIndex(%s)' % i
		if i == pylink.CR_HAIR_COLOR:
			return 'white'
		if i == pylink.PUPIL_HAIR_COLOR:
			return 'yellow'
		if i == pylink.PUPIL_BOX_COLOR:
			return 'green'
		if i == pylink.SEARCH_LIMIT_BOX_COLOR:
			return 'red'
		if i == pylink.MOUSE_CURSOR_COLOR:
			return 'blue'
		return 'black'

	def draw_line(self, x1, y1, x2, y2, colorindex):

		"""Unused"""

		# Find out how this can be used
		print 'draw_line() %s %s %s %s' % (x1, y1, x2, y2)
		
	def draw_lozenge(self, x, y, width, height, colorindex):

		"""Unused"""

		# Find out how this can be used
		print 'draw_lozenge() %s %s %s %s' % (x, y, width, height)

	def get_mouse_state(self):

		"""Unused"""

		pass

	def get_input_key(self):

		"""
		Gets an input key.

		Returns:
		A list containing a single pylink key identifier.
		"""

		try:
			key, time = self.kb.get_key(keylist=None, timeout='default')
		except:
			self.esc_pressed = True
			key = 'q'
		if key == None:
			return None
		# Escape functions as a 'q' with the additional esc_pressed flag
		if key == 'escape':
			key = 'q'
			self.esc_pressed = True
		# Process regular keys
		if key == "return":
			keycode = pylink.ENTER_KEY
			self.state = None
		elif key == "space":
			keycode = ord(" ")
		elif key == "q":
			keycode = pylink.ESC_KEY
			self.state = None
		elif key == "c":
			keycode = ord("c")
			self.state = "calibration"
		elif key == "v":
			keycode = ord("v")
			self.state = "validation"
		elif key == "a":
			keycode = ord("a")
		elif key == "up":
			keycode = pylink.CURS_UP
		elif key == "down":
			keycode = pylink.CURS_DOWN
		elif key == "left":
			keycode = pylink.CURS_LEFT
		elif key == "right":
			keycode = pylink.CURS_RIGHT
		else:
			keycode = 0
		# Convert key to PyLink keycode and return
		return [pylink.KeyInput(keycode, 0)] # 0 = pygame.KMOD_NONE

	def exit_image_display(self):

		"""Exits the image display."""

		self.clear_cal_display()

	def alert_printf(self,msg):

		"""
		Prints alert message.

		Arguments:
		msg		--	The message to be played.
		"""

		print "eyelink_graphics.alert_printf(): %s" % msg

	def setup_image_display(self, width, height):

		"""
		Initializes the buffer that will contain the camera image.

		Arguments:
		width		--	The width of the image.
		height		--	The height of the image.
		"""

		self.size = (width,height)
		self.clear_cal_display()
		self.last_mouse_state = -1
		self.imagebuffer = array.array('l')

	def image_title(self, text):

		"""
		TODO: What does this do?

		Arguments:
		text	--	Unknown.
		"""

		pass

	def draw_image_line(self, width, line, totlines, buff):

		"""
		Draws a single eye video frame, line by line.

		Arguments:

		width		--	Width of the video.
		line		--	Line nr of current line.
		totlines	--	Total lines in video.
		buff		--	Frame buffer.
		imagesize	--	The size of the image, which is (usually?) 192x160 px.
		"""

		# If the buffer hasn't been filled yet, add a line.
		for i in range(width):
			try:
				self.imagebuffer.append(self.pal[buff[i]])
			except:
				pass
		# If the buffer is full, push it to the display.
		if line == totlines:
			# First create a PIL image, then convert it to a PyGame image, and
			# then save it to a temporary file on disk. This juggling with
			# formats is necessary to show the image without distortions under
			# (so far) all conditions. Surprisingly, it doesn't cause any
			# appreciable delays, relative to directly invoking PyGame or
			# PsychoPy functions.
			bufferv = self.imagebuffer.tostring()
			img = Image.new("RGBX", self.size)
			imgsz = self.xc, self.yc
			img.fromstring(bufferv)
			img = img.resize(imgsz)
			img = pygame.image.fromstring(img.tostring(), imgsz, 'RGBX')
			pygame.image.save(img, self.tmp_file)
			# ... and then show the image.
			self.screen.clear()
			self.screen.draw_image(self.tmp_file)
			self.display.fill(self.screen)
			self.display.show()
			# Clear the buffer for the next round!
			self.imagebuffer = array.array('l')

	def set_image_palette(self, r, g, b):

		"""
		Sets the image palette.

		TODO: What this function actually does is highly mysterious. Figure it
		out!

		Arguments:
		r		--	The red channel.
		g		--	The green channel.
		b		--	The blue channel.
		"""

		self.imagebuffer = array.array('l')
		self.clear_cal_display()
		sz = len(r)
		i = 0
		self.pal = []
		while i < sz:
			rf = int(b[i])
			gf = int(g[i])
			bf = int(r[i])
			self.pal.append((rf<<16) | (gf<<8) | (bf))
			i += 1
Esempio n. 11
0
                trials[run][i][ii][0] = prefix + '_' + str(
                    ii) + '.jpg'  #image name

            trials[run][i][ii][1] = conds[ii]  # trial type
            trials[run][i][ii][2] = itis[ii]  # iti time
            trials[run][i][ii][3] = onsets[ii]  # signal onset time
            trials[run][i][ii][4] = [[]] * 3
            trials[run][i][ii][5] = block
            # now pre-generate the screens!
            # Note: this is code efficient but not memory efficient (i.e. I am lazy and would rather pre-load almost twice the number of screens, because this is why we have RAM)

            tempstim = Screen()
            #tempstim.draw_image(RESDIR + trials[run][i][ii][0], pos=DISPCENTRE)# draw face on center of screen

            tempstim.draw_image(os.path.join(RESDIR, trials[run][i][ii][0]),
                                pos=DISPCENTRE,
                                scale=0.5)  # draw face on center of screen
            trials[run][i][ii][4][0] = tempstim

            tempsig = Screen()
            #tempsig.draw_image(RESDIR + trials[run][i][ii][0], pos=DISPCENTRE)# draw face on center of screen
            tempsig.draw_image(os.path.join(RESDIR, trials[run][i][ii][0]),
                               pos=DISPCENTRE,
                               scale=0.5)  # draw face on center of screen

            tempfeed = Screen()
            tempfeed.draw_image(os.path.join(RESDIR, trials[run][i][ii][0]),
                                pos=DISPCENTRE,
                                scale=0.5)  #
            #RESPMAP 0 = go squares, no-go circles
Esempio n. 12
0
inst_scr.draw_text(instructions, fontsize=MAIN_FONTSIZE, center=True)
instruction_screens.append(inst_scr)

# Second screen with text and images.
inst_scr = Screen()
instructions = \
"""
Let's practice. 

Remember the way this snake is facing! 

When you are ready press a button to continue. 
"""
inst_scr.draw_text(instructions, fontsize=MAIN_FONTSIZE, pos = (DISPCENTRE[0], DISPCENTRE[1]-200))
fpath = os.path.join(RESDIR, STIMNAMES[0] + ".png")
inst_scr.draw_image(fpath, pos=(DISPCENTRE[0], DISPCENTRE[1]+150), scale = 0.7)
inst_scr.screen[2].ori = 100
instruction_screens.append(inst_scr)

# prac screen 1 
inst_scr = Screen()
instructions = \
"""
Can you remember which way the snake faced just now? 

Press the red and green keys in you right hand to turn the snake.
Press the yellow key in your left hand to respond. 
"""
inst_scr.draw_text(instructions, fontsize=MAIN_FONTSIZE, pos = (DISPCENTRE[0], DISPCENTRE[1]-200))
fpath = os.path.join(RESDIR, STIMNAMES[0] + ".png")
inst_scr.draw_image(fpath, pos=(DISPCENTRE[0], DISPCENTRE[1]+150), scale = 0.7)
Esempio n. 13
0
	kb.get_key()
	eventfuncs[i]()
	scr.clear()
	scr.draw_text("Function %s works! Press space to test the next" % str(eventfuncs[i]))
	disp.fill(scr)
	disp.show()
	kb.get_key()


# # # # #
# test gaze contingency

# AOI
scr.clear()
scr.draw_text("There should be an image in the centre of the screen", pos=(DISPSIZE[0]/2, DISPSIZE[1]/10))
scr.draw_image(imagefile) # imginfo: 400x600 px; kitten head position relative to image x=40, y=160, w=130, h=140
x = (DISPSIZE[0]/2 - 200) + 40 # centre minus half of the image width, plus kitten head X position in image
y = (DISPSIZE[1]/2 - 300) + 160 # centre minus half of the image height, plus kitten head Y position in image
aoi = AOI('rectangle',(x,y),(130,140))
disp.fill(scr)
t1 = disp.show()
log.write(["AOI", t1])
key = None
tracker.start_recording()
while key != 'space':
	# check for key input
	key, presstime = kb.get_key(keylist=['space'],timeout=1)
	# get gaze position
	gazepos = tracker.sample()
	# check if the gaze position is within the aoi
	if aoi.contains(gazepos):
Esempio n. 14
0
class StimScreen:
    """Custom class for stimulus screens in this experiment."""

    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)

    def update(self, locs, oris, linewidth=None, stimtypes=None):
        """Updates the locations, colours, line colours, and line widths of
        this stimulus array.
        
        Arguments
        
        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), or
                            None to leave the width as it is. Default value is
                            None.
        
        stimtypes    -      String or a list of strings that determines the
                            type of stimulus. Options are 'gabor' and 'noise',
                            or None to not update.
                            Default is None.
        """

        # Convert the linewidth to a list (if necessary).
        if type(linewidth) in [int, float]:
            linewidth = len(self._stimindexnrs) * [int(linewidth)]

        # Convert the stimulus types to a list (if necessary).
        if type(stimtypes) in [str, unicode]:
            stimtypes = len(self._stimindexnrs) * [stimtypes]

        # Loop through all stimuli.
        #     stimnr is a number between 0 and nstim
        #     stimindexnr refers to the index of a stimulus in self.screen
        for stimnr, stimindexnr in enumerate(self._stimindexnrs):

            # Update the stimulus location.
            self.screen[stimindexnr].pos = pos2psychopos(locs[stimnr])
            self.screen[self._outlineindexnrs[stimnr]].pos = pos2psychopos(
                locs[stimnr])

            #            # Update the stimulus colour.
            #            self.screen[stimindexnr].fillColor = rgb2psychorgb(list(oris[stimnr]))

            # Update the stimulus orientation.
            self.screen[stimindexnr].setOri(oris[stimnr])

            # Update the stimulus line width and colour.
            if linewidth != None:
                self.screen[self._outlineindexnrs[
                    stimnr]].lineWidth = linewidth[stimnr]
                if linewidth[stimnr] == PROBELINEWIDTH:
                    self.screen[self._outlineindexnrs[stimnr]].lineColor = \
                        (1,-1,-1)
                else:
                    self.screen[self._outlineindexnrs[stimnr]].lineColor = \
                        (0,0,0)

            # Update the stimulus texture.
            if stimtypes != None:
                if stimtypes[stimnr] == 'gabor':
                    self.screen[stimindexnr].setTex('sin')
                else:
                    self.screen[stimindexnr].setTex(self._noisetex)