def __init__(self, experiment, tracker):

		"""
		Constructor

		Arguments:
		experiment -- opensesame experiment
		tracker -- an eyelink instance
		"""

		pylink.EyeLinkCustomDisplay.__init__(self)

		self.experiment = experiment
		self.my_canvas = canvas(self.experiment)
		self.my_keyboard = keyboard(self.experiment, timeout=0)
		self.my_mouse = mouse(self.experiment)

		self.__target_beep__ = synth(self.experiment, length = 50)
		self.__target_beep__done__ = synth(self.experiment, freq = 880, length = 200)
		self.__target_beep__error__ = synth(self.experiment, freq = 220, length = 200)

		self.state = None

		self.imagebuffer = array.array('l')
		self.pal = None
		self.size = (0,0)
		self.tmp_file = os.path.join(tempfile.gettempdir(), '__eyelink__.jpg')

		self.set_tracker(tracker)
		self.last_mouse_state = -1
		self.experiment.eyelink_esc_pressed = False
Example #2
0
	def _exec(self, focus_widget=None):

		"""<DOC>
		Executes the form.

		Keyword arguments:
		focus_widget -- A widget that is in the form and should receive a #
						virtual mouse click when the form is opened. This allows #
						you to activate a text_input right away, for example, so #
						that the user doesn't have to click on it anymore.

		Returns:
		Gives the return value of the form, which depends on how the user has #
		interacted with the widgets. For example, if the user has pressed a #
		button, the button text will be returned.
		</DOC>"""

		i = 0
		self.mouse = mouse(self.experiment)
		if focus_widget != None:
			self.render()
			resp = focus_widget.on_mouse_click(None)
			if resp != None:
				return
		while True:
			self.render()
			button, xy, time = self.mouse.get_click(visible=True)
			pos = self.xy_to_index(xy)
			if pos != None:
				w = self.widgets[pos]
				if w != None:
					resp = self.widgets[pos].on_mouse_click(xy)
					if resp != None:
						return resp
Example #3
0
	def prepare(self):

		"""The preparation phase of the plug-in goes here."""

		# Call the parent constructor.
		item.prepare(self)
		# User input
		self.responses = [self._yes, self._no]
		self.rows = [2] + [1]*len(self.responses)
		self.m = mouse(self.experiment)
		self.c = canvas(self.experiment)
Example #4
0
	def prepare_response_func(self):

		"""See base_response_item."""

		if self._allowed_responses is None:
			buttonlist = None
		else:
			buttonlist = [self.button_code(r) for r in self._allowed_responses]
		self._mouse = mouse(self.experiment, timeout=self._timeout,
			buttonlist=buttonlist)
		return self._mouse.get_click
Example #5
0
	def run(self):

		"""Run the item"""

		# Initialize the item
		self.set_item_onset()
		self.sri = self.time()
		self.experiment.set("slider_percent", None)
		my_canvas = canvas(self.experiment)
		my_mouse = mouse(self.experiment, timeout=20)


		# Create the app
		while True:

			# Slider dimensions
			slider_w = self.slider_width
			slider_h = self.slider_heigth
			slider_x = self.get("width")/2-slider_w/2
			slider_y = self.get("height")/2-slider_h/2
			
			# Determine the slider fill based on the mouse position
			pos, time = my_mouse.get_pos()
			x, y = pos
			slider_fill = min(slider_w, max(0, x-slider_x))

			my_canvas.set_bgcolor(self.get("bg_colour"))
			my_canvas.clear()
			# Draw the text 
			my_canvas.text(self.get("question"), y=slider_y-100, color=self.get("txt_colour"))
			my_canvas.text(self.get("accept_text"), y=slider_y+slider_h+50, color=self.get("txt_colour"))
			# Draw the slider frame
			my_canvas.set_fgcolor(self.get("fg_colour"))
			my_canvas.rect(slider_x-1, slider_y-1, slider_w+2, slider_h+2)
			# Draw the slider fill
			my_canvas.rect(slider_x, slider_y, slider_fill, slider_h, fill=True, color=self.get("sf_colour"))
			# Draw the canvas
			my_canvas.show()

			# Poll the mouse for buttonclicks
			button, position, timestamp = my_mouse.get_click(timeout = 20)
			if button != None:
				break

		slider_percent = 100.0*slider_fill/slider_w

		# Set the response
		self.experiment.set("response", slider_percent)

		# Return success
		return True
Example #6
0
	def _exec(self, focus_widget=None):

		"""
		desc:
			Executes the form.

		keywords:
			focus_widget:
				desc:	A widget that is in the form and should receive a
						virtual mouse click when the form is opened. This allows
						you to activate a text_input right away, for example, so
						that the user doesn't have to click on it anymore.
				type:	[widget, NoneType]

		returns:
			desc:	Gives the return value of the form, which depends on how the
					user interacted with the widgets. For example, if the user
					pressed a button, the button text will be returned. If a
					timeout occurred, None will be returned.
		"""

		self.start_time = None
		if len(self) == 0:
			raise osexception(u'The form contains no widgets')
		self.mouse = mouse(self.experiment, timeout=5)
		self.mouse.show_cursor()
		if focus_widget is not None:
			self.render()
			if self.timed_out():
				self.experiment.var.form_response = None
				return None
			resp = focus_widget.on_mouse_click(None)
			if resp is not None:
				return
		while True:
			self.render()
			if self.timed_out():
				self.experiment.var.form_response = None
				return None
			button, xy, time = self.mouse.get_click(visible=True)
			if xy is None:
				continue
			pos = self.xy_to_index(xy)
			if pos is not None:
				w = self.widgets[pos]
				if w is not None:
					resp = self.widgets[pos].on_mouse_click(xy)
					if resp is not None:
						self.experiment.var.form_response = resp
						return resp
		self.mouse.hide_cursor()
Example #7
0
    def _exec(self, focus_widget=None):
        """
		desc:
			Executes the form.

		keywords:
			focus_widget:
				desc:	A widget that is in the form and should receive a
						virtual mouse click when the form is opened. This allows
						you to activate a text_input right away, for example, so
						that the user doesn't have to click on it anymore.
				type:	[widget, NoneType]

		returns:
			desc:	Gives the return value of the form, which depends on how the
					user interacted with the widgets. For example, if the user
					pressed a button, the button text will be returned. If a
					timeout occurred, None will be returned.
		"""

        self.start_time = None
        if len(self) == 0:
            raise osexception(u'The form contains no widgets')
        self.mouse = mouse(self.experiment, timeout=5)
        self.mouse.show_cursor()
        if focus_widget is not None:
            self.render()
            if self.timed_out():
                self.experiment.var.form_response = None
                return None
            resp = focus_widget.on_mouse_click(None)
            if resp is not None:
                return
        while True:
            self.render()
            if self.timed_out():
                self.experiment.var.form_response = None
                return None
            button, xy, time = self.mouse.get_click(visible=True)
            if xy is None:
                continue
            pos = self.xy_to_index(xy)
            if pos is not None:
                w = self.widgets[pos]
                if w is not None:
                    resp = self.widgets[pos].on_mouse_click(xy)
                    if resp is not None:
                        self.experiment.var.form_response = resp
                        return resp
        self.mouse.hide_cursor()
Example #8
0
    def prepare_response_func(self):
        """See base_response_item."""

        if self._allowed_responses is None:
            buttonlist = None
        else:
            buttonlist = [self.button_code(r) for r in self._allowed_responses]
        self._mouse = mouse(self.experiment,
                            timeout=self._timeout,
                            buttonlist=buttonlist)
        if self.var.get(u'event_type', default=u'mouseclick') == u'mouseclick':
            return self._mouse.get_click
        if self.var.event_type == u'mouserelease':
            return self._mouse.get_click_release
        raise osexception(
            u'event_type should be "mouseclick" or "mouserelease"')
Example #9
0
    def __init__(self, mousebuttonlist=MOUSEBUTTONLIST, timeout=MOUSETIMEOUT, \
     visible=False):

        # See _mouse.basemouse.BaseMouse

        # try to copy docstring (but ignore it if it fails, as we do
        # not need it for actual functioning of the code)
        try:
            copy_docstr(BaseMouse, OSMouse)
        except:
            # we're not even going to show a warning, since the copied
            # docstring is useful for code editors; these load the docs
            # in a non-verbose manner, so warning messages would be lost
            pass

        self.experiment = osexperiment
        self.mouse = mouse(self.experiment, buttonlist=mousebuttonlist, \
         timeout=timeout)
Example #10
0
	def __init__(self, mousebuttonlist=MOUSEBUTTONLIST, timeout=MOUSETIMEOUT, \
		visible=False):

		# See _mouse.basemouse.BaseMouse

		# try to copy docstring (but ignore it if it fails, as we do
		# not need it for actual functioning of the code)
		try:
			copy_docstr(BaseMouse, OSMouse)
		except:
			# we're not even going to show a warning, since the copied
			# docstring is useful for code editors; these load the docs
			# in a non-verbose manner, so warning messages would be lost
			pass
		
		self.experiment = osexperiment
		self.mouse = mouse(self.experiment, buttonlist=mousebuttonlist, \
			timeout=timeout)
Example #11
0
def mouse(**resp_args):
    """
	desc: |
		A convenience function that creates a new `mouse` object. For a
		description of possible keywords, see:

		- %link:manual/python/mouse%

	returns:
		desc:	A `mouse` object.
		type:	mouse

	example: |
		my_mouse = mouse(keylist=[1,3], timeout=5000)
		button, time = my_mouse.get_button()
	"""

    from openexp.mouse import mouse
    return mouse(experiment, **resp_args)
Example #12
0
	def Calibrate_Run(self):		
		slmouse = mouse(self.experiment, timeout=20, visible=True)
		slmouse.show_cursor(True)
		slmouse.set_pos(pos=(0,0))
		xperc = 0;
		self.canvas['Slider'].w = (xperc / 100) * ((2 * self.canvas.width / 2.2) - 12)
		self.canvas.show()	
		
		while True:
		# Poll the mouse for buttonclicks
			button = None
			while button == None:
				button, position, timestamp = slmouse.get_click()

			button = None
			pos, mtime = slmouse.get_pos()
			x, y = pos
			
			if (x, y) in self.canvas['SliderBox']:				
				xperc = min((x + self.canvas.width / 2.2) / (2 * ((self.canvas.width / 2.2) - 6)) * 100.0,100)
				self.canvas['Slider'].w = (xperc / 100) * ((2 * self.canvas.width / 2.2) - 12)
				self.canvas['ValuePerc'].text = "("+str(round(xperc,1)) + "%)"
				self.canvas['ValuemAh'].text = str(round(5*(xperc/100.0),1)) + "mAh"
				
				self.canvas.show()	

			if (x, y) in self.canvas['TestBox']:
				#self.EE.SetLines(0) 
				self.EE.PulseLines(math.floor((xperc/100.0) * 255), self.var._duration)
				self.canvas['TestBox'].color = "blue"
				self.canvas.show()	
				time.sleep(8)
				self.canvas['TestBox'].color = "red"
				self.canvas.show()	
				
				
			if (x, y) in self.canvas['OKBox']:
				self.var.ShockerCalibrationBinvalue = math.floor((xperc/100.0) * 255)
				self.var.ShockerCalibrationmAhvalue = round(5*(xperc/100.0),1)
				print((self.var.ShockerCalibrationBinvalue,self.var.ShockerCalibrationmAhvalue))
				self.experiment.set("ShockerCalibration", self.var.ShockerCalibrationBinvalue)
				self.experiment.set("ShockermAhCalibration", self.var.ShockerCalibrationmAhvalue)
				break
def mouse(**resp_args):

	"""
	desc: |
		A convenience function that creates a new `mouse` object. For a
		description of possible keywords, see:

		- [/python/mouse/](/python/mouse/)

	returns:
		desc:	A `mouse` object.
		type:	mouse

	example: |
		my_mouse = mouse(keylist=[1,3], timeout=5000)
		button, time = my_mouse.get_button()
	"""

	from openexp.mouse import mouse
	return mouse(experiment, **resp_args)
	def __init__(self, experiment, resolution, data_file="default.edf", fg_color=(255, 255, 255), bg_color=(0, 0, 0), saccade_velocity_threshold=35, saccade_acceleration_threshold=9500):

		"""Initializes the eyelink dummy object"""

		self.experiment = experiment
		self.data_file = data_file
		self.resolution = resolution
		self.recording = False

		self.simulator = mouse(self.experiment)
		self.simulator.set_timeout(timeout=2)

		self.blinking = False # current 'blinking' condition (MOUSEBUTTONDOWN = eyes closed; MOUSEBUTTONUP = eyes open)
		self.bbpos = (resolution[0]/2,resolution[1]/2) # before 'blink' position

		# check if blinking functionality is possible
		if not hasattr(self.simulator, 'get_pressed') or not hasattr(self.simulator, 'set_poesje'):
			print("libeyelink_dummy: blink functionality not available due to missing openexp.mouse.get_pressed and/or openexp.mouse.set_pos methods")
			self.blinkfun = False
		else:
			self.blinkfun = True
	def run(self):

		"""Run the item"""

		# Initialize the item
		self.set_item_onset()
		self.sri = self.time()
		self.experiment.set("slider_percent", None)
		slmouse = mouse(self.experiment, timeout=20)

		# Run slider
		while True:
			
			# Determine the slider fill based on the mouse position
			pos, time = slmouse.get_pos()
			x, y = pos
			slider_fill = min(self.slider_w, max(0, x-self.slider_x))

			# Draw the slider fill
			self.canvas.rect(self.slider_x, self.slider_y, slider_fill, self.slider_h, fill=True, color=self.get("sf_colour"))

			# Draw the canvas
			self.canvas.show()

			# Reset slider fill
			self.canvas.rect(self.slider_x, self.slider_y, slider_fill, self.slider_h, fill=True, color=self.get("bg_colour"))

			# Poll the mouse for buttonclicks
			button, position, timestamp = slmouse.get_click(timeout = 1)
			if button != None:
				break

		slider_percent = round(100.0 * (float(slider_fill)/float(self.slider_w)),2)

		# Set the response and response time
		self.experiment.set("response", slider_percent)

		# Return success
		return True
Example #16
0
 def run(self):
     mmouse = mouse(self.experiment)
     mmouse.show_cursor()
     self.c.show()
     runner = RunGame(mode=self.var.mode, \
         frame  = self.experiment.window, \
         duration = self.var.duration, \
         language = self.lang, \
         fullscreen = self.fullscreen, \
         show_timer = self.var.show_timer
     )
     gameresults = runner.run()()
     if gameresults != "keyboard interrupt":
         cr = self.experiment.var.personal_record if 'personal_record' in self.experiment.var.vars(
         ) else 0
         if self.var.show_feedbacks == 'yes':
             pr = runner.feedback_screen(gameresults, cr)
             self.experiment.var.set('personal_record', pr)
         for k, v in gameresults.iteritems():
             self.experiment.var.set(k, v)
     else:
         self.experiment.pause()
Example #17
0
    def _exec(self,
              logging_resolution=10,
              timeout=None,
              reset_mouse=True,
              start_unit='grid',
              start_coordinates=(6.0, 4.5),
              click_required=True,
              mouse_buttons_allowed=[1, 3],
              track_clicks=False,
              max_initiation_time=None,
              warning_widget=None):

        # Specify timeout settings
        if timeout != None:
            timeout = int(timeout)
            timeleft = timeout
        else:
            timeleft = logging_resolution

        # Calculate start coordinates (if mouse should be reset)
        if reset_mouse:

            # Check if start_coordinates are in allowed range
            if start_unit in ['grid', 'widget']:
                if start_coordinates[0] > len(self.cols) - 1:
                    raise osexception(
                        'start x coordinate exceeds number of colums - 1 (first column has value 0)'
                    )
                if start_coordinates[1] > len(self.rows) - 1:
                    raise osexception(
                        'start y coordinate exceeds number of rows - 1 (first row has value 0)'
                    )

            # Unit: grid
            # move mouse cursor to the left upper corner of the grid position
            # (if float is given, linear interpolation is performed)
            if start_unit == 'grid':

                start_index = self.cell_index(
                    (int(start_coordinates[0]), int(start_coordinates[1])))
                startx_mouse, starty_mouse, w, h = self.get_rect(start_index)

                # if form coordinates are provided as float, use linear interpolation
                # (as internal form function only accepts integers)
                if isinstance(start_coordinates[0], float):
                    start_index_upper = self.cell_index(
                        (int(start_coordinates[0]) + 1,
                         int(start_coordinates[1])))
                    startx_upper, y, w, h = self.get_rect(start_index_upper)
                    startx_mouse += int(
                        (startx_upper - startx_mouse) *
                        (start_coordinates[0] - int(start_coordinates[0])))

                if isinstance(start_coordinates[1], float):
                    start_index_upper = self.cell_index(
                        (int(start_coordinates[0]),
                         int(start_coordinates[1]) + 1))
                    x, starty_upper, w, h = self.get_rect(start_index_upper)
                    starty_mouse += int(
                        (starty_upper - starty_mouse) *
                        (start_coordinates[1] - int(start_coordinates[1])))

            # Unit: widget
            # move mouse cursor to the center of the widget for which starting coordinates are provided
            # (if no widget has the start coordinates for this position, mouse is centered on the position of the grid)
            elif start_unit == 'widget':
                start_index = self.cell_index(
                    (int(start_coordinates[0]), int(start_coordinates[1])))
                startx_mouse, starty_mouse, w, h = self.get_rect(start_index)
                startx_mouse += w / 2
                starty_mouse += h / 2

            # Unit: pixel
            # move mouse cursor to the position specified in pixel
            elif start_unit == 'pixel':
                startx_mouse = start_coordinates[0]
                starty_mouse = start_coordinates[1]

            else:
                raise osexception(
                    'start_unit should be one of the following: grid, widget, pixel'
                )

            # Convert pixel values to integers
            startx_mouse = int(startx_mouse)
            starty_mouse = int(starty_mouse)

        # Render form
        self.render()

        # Initialize mouse
        self.mouse = mouse(self.experiment, visible=True)

        # Initialize clock
        self.clock = self.experiment._clock

        # Reset mouse (if specified)
        if reset_mouse:

            # Set mouse position
            self.mouse.set_pos((startx_mouse, starty_mouse))

            # Set up variables including their first values
            timestamps = [self.clock.time()]
            xpos = [startx_mouse]
            ypos = [starty_mouse]

        # Get mouse position otherwise
        else:

            # Get mouse position
            position, timestamp = self.mouse.get_pos()

            # Set up variables including their first values
            timestamps = [timestamp]
            xpos = [position[0]]
            ypos = [position[1]]

        # Show mouse
        self.mouse.show_cursor(show=True)

        # Set tracking variables
        tracking = True
        mouse_on_start = True
        warning_printed = False
        resp = None
        initiation_time = None

        if track_clicks:
            clicks = []
            clicks_timestamps = []

        # Start tracking
        while tracking and timeleft > 0:

            # Collect mouse response
            if timeout == None:
                # (timeout corresponds to interval with which mouse coordinates are recored)
                mouse_button, xy, time = self.mouse.get_click(
                    buttonlist=None, timeout=logging_resolution)
            else:
                # (timeout corresponds to interval with which mouse coordinates are recored,
                #  or time left - whatever is smaller)
                mouse_button, xy, time = self.mouse.get_click(
                    buttonlist=None,
                    timeout=min([logging_resolution, timeleft]))

            # Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
            # (as get_click returns None for xy if there was no mouse click)
            if xy != None:
                position = xy
                timestamp = time
            else:
                position, timestamp = self.mouse.get_pos()

            # Append values
            timestamps.append(timestamp)
            xpos.append(position[0])
            ypos.append(position[1])

            # Check if mouse has left the starting position, and, if so, determine initiation time
            if mouse_on_start == True:
                mouse_on_start = (position[0] == xpos[0]) and (position[1]
                                                               == ypos[0])
                if mouse_on_start == False:
                    # difference between last (not current) timestamp and timestamp at start
                    initiation_time = timestamps[-2] - timestamps[0]

            # If mouse is still on starting position and initiation time is exceeded, show warning
            if max_initiation_time != None:
                if mouse_on_start == True and warning_printed == False:
                    if (timestamp - timestamps[0]) > max_initiation_time:
                        self.set_widget(warning_widget[0],
                                        warning_widget[1],
                                        colspan=warning_widget[2],
                                        rowspan=warning_widget[3])
                        self.render()
                        warning_printed = True

            # If mouse clicks should be recorded, save them
            if track_clicks:
                if mouse_button != None:
                    clicks.append(mouse_button)
                    clicks_timestamps.append(timestamp)

            # If there was a mouse click, determine the button that was clicked
            # and if click was on a button, end tracking and finish form
            # (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
            if click_required == False or mouse_button in mouse_buttons_allowed:

                pos = self.xy_to_index(position)

                if pos != None:
                    w = self.widgets[pos]
                    if w != None:
                        resp = self.widgets[pos].on_mouse_click(xy)
                        if resp != None:
                            tracking = False

            # Update timeleft
            if timeout != None:
                timeleft = timeout - (timestamp - timestamps[0])

        # Calculate response time
        resp_time = timestamps[-1] - timestamps[0]

        # Set form_response variable
        self.experiment.var.form_response = resp

        if track_clicks == False:
            return resp, resp_time, initiation_time, timestamps, xpos, ypos
        else:
            return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #18
0
	def _exec(self,
		logging_resolution=10, timeout=None,
		reset_mouse=True, start_unit='grid', start_coordinates=(6.0,4.5),
		click_required=True, mouse_buttons_allowed=[1,3],
		track_clicks=False,
		max_initiation_time=None, warning_widget=None):
	    
		"""Executes MT_form object and returns results.

    	Executes the MT_form object to display the form, collect responses, and
		return the response, response time, and mouse-tracking data.

	    Args:
	        logging_resolution (int): Time interval (in ms) between recordings 
				of the mouse position.
			timeout (int): Response timeout (in ms). Use None (default) if there
				is no timeout.
			reset_mouse (bool): Reset mouse position when tracking starts.
			start_coordinates (tuple): The x- and y- coordinates the cursor
				should be reset to.
			start_unit (str): The unit used to define the start coordinates. 
				By default ("grid"), it corresponds to the form grid units, and
				the mouse cursor is reset to the left upper corner of the
				specified grid position (if a float is given, linear
				interpolation is performed). An alternative that also uses the
				form grid unit is "widget", whereby the mouse cursor is reset to
				the center of the widget for which starting coordinates are
				provided (if no widget has the start coordinates for this
				position, the mouse is centered on the position of the grid).
				Finally, "pixel" can be used to specify the start coordinates in
				pixel metric (in sketchpad metric).
			click_required (bool): Click required to indicate response. If False, 
				a response can be indicated just by entering the area of one 
				of the buttons with the mouse.
			mouse_buttons_allowed (list): The (physical) mouse buttons that 
				can be used to click one of the buttons.
			track_clicks (bool): Enable separate tracking of mouse clicks. 
				If True, the physical mouse button that was clicked will be 
				returned along with a corresponding timestamp as a separate 
				list.
			max_initiation_time (int): If specified, a custom warning message 
				will be displayed if no mouse movement was initiated after the 
				specified time limit (in ms).
			warning_widget (list): Custom widget that is displayed if the
				initiation time is exceeded. A list containing all the arguments
				required by the form.set_widget function.
	    
		Returns:
			resp (str): The text of the buttton that was clicked.
			resp_time (int): Response time (in ms).
			initiation_time (int): Time (in ms) until a movement was initiated.
			timestamps (list): Timestamps (in ms) for each recorded position.
			xpos (list): x-positions for each recorded position.
			ypos (list): y-positions for each recorded position.
			clicks (list): (Physical) mouse button for each mouse click. 
				Only returned if track_clicks is True.
			clicks_timestamps (list): Timestamp (in ms) for each mouse click. 
				Only returned if track_clicks is True.
	    """	
			

		# Specify timeout settings
		if timeout != None:
			timeout = int(timeout)
			timeleft = timeout
		else:
			timeleft = logging_resolution
		
		# Calculate start coordinates (if mouse should be reset)
		if reset_mouse:
		
			# Check if start_coordinates are in allowed range
			if start_unit in ['grid', 'widget']:
				if start_coordinates[0] > len(self.cols)-1:
					raise osexception('start x coordinate exceeds number of colums - 1 (first column has value 0)')
				if  start_coordinates[1] > len(self.rows)-1:
					raise osexception('start y coordinate exceeds number of rows - 1 (first row has value 0)')
			
			# Unit: grid
			# move mouse cursor to the left upper corner of the grid position
			# (if float is given, linear interpolation is performed)
			if start_unit=='grid':
				
				start_index = self.cell_index((int(start_coordinates[0]),int(start_coordinates[1])))
				startx_mouse, starty_mouse, w, h = self.get_rect(start_index)
				
				# if form coordinates are provided as float, use linear interpolation
				# (as internal form function only accepts integers)
				if isinstance(start_coordinates[0], float):
					start_index_upper = self.cell_index((int(start_coordinates[0])+1,int(start_coordinates[1])))
					startx_upper, y, w, h = self.get_rect(start_index_upper)			
					startx_mouse += int((startx_upper-startx_mouse) * (start_coordinates[0]-int(start_coordinates[0])))
					
				if isinstance(start_coordinates[1], float):
					start_index_upper = self.cell_index((int(start_coordinates[0]),int(start_coordinates[1])+1))
					x, starty_upper, w, h = self.get_rect(start_index_upper)			
					starty_mouse += int((starty_upper-starty_mouse) * (start_coordinates[1]-int(start_coordinates[1])))

			# Unit: widget
			# move mouse cursor to the center of the widget for which starting coordinates are provided
			# (if no widget has the start coordinates for this position, mouse is centered on the position of the grid)
			elif start_unit=='widget':
				start_index = self.cell_index((int(start_coordinates[0]),int(start_coordinates[1])))
				startx_mouse, starty_mouse, w, h = self.get_rect(start_index)
				startx_mouse += w/2
				starty_mouse += h/2
			
			# Unit: pixel
			# move mouse cursor to the position specified in pixel
			elif start_unit=='pixel':
				startx_mouse = start_coordinates[0]
				starty_mouse = start_coordinates[1]
			
			else:
				raise osexception('start_unit should be one of the following: grid, widget, pixel')
			
			# Convert pixel values to integers
			startx_mouse = int(startx_mouse)
			starty_mouse = int(starty_mouse)
					
		
		# Render form
		self.render()
		
		# Initialize mouse
		self.mouse = mouse(self.experiment,visible=True)
		
		# Initialize clock
		self.clock = self.experiment._clock
		
		# Reset mouse (if specified)
		if reset_mouse:
		
			# Set mouse position
			self.mouse.set_pos((startx_mouse,starty_mouse))
			
			# Set up variables including their first values
			timestamps = [self.clock.time()]
			xpos = [startx_mouse]
			ypos = [starty_mouse]
		
		
		# Get mouse position otherwise		
		else:
		
			# Get mouse position
			position, timestamp = self.mouse.get_pos()
			
			# Set up variables including their first values
			timestamps = [timestamp]
			xpos = [position[0]]
			ypos = [position[1]]
		
		# Show mouse
		self.mouse.show_cursor(show=True)
		
		# Set tracking variables
		tracking = True
		mouse_on_start = True
		warning_printed = False
		resp = None
		initiation_time = None
		
		if track_clicks:
			clicks = []
			clicks_timestamps = []

		
		# Start tracking
		while tracking and timeleft>0:
			
			# Collect mouse response
			if timeout==None:
				# (timeout corresponds to interval with which mouse coordinates are recored)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None,timeout=logging_resolution)
			else:
				# (timeout corresponds to interval with which mouse coordinates are recored,
				#  or time left - whatever is smaller)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None,timeout=min([logging_resolution,timeleft]))
			
			# Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
			# (as get_click returns None for xy if there was no mouse click)
			if xy != None:
				position = xy
				timestamp = time
			else:
				position, timestamp = self.mouse.get_pos()
			
			# Append values
			timestamps.append(timestamp)
			xpos.append(position[0])
			ypos.append(position[1])
			
			# Check if mouse has left the starting position, and, if so, determine initiation time
			if mouse_on_start == True:
				mouse_on_start = (position[0] == xpos[0]) and (position[1] == ypos[0])
				if mouse_on_start == False:
					# difference between last (not current) timestamp and timestamp at start
					initiation_time = timestamps[-2]-timestamps[0]
			
			# If mouse is still on starting position and initiation time is exceeded, show warning
			if max_initiation_time != None:
				if mouse_on_start == True and warning_printed == False:
					if (timestamp-timestamps[0])>max_initiation_time:
						self.set_widget(warning_widget[0],warning_widget[1],colspan=warning_widget[2],rowspan=warning_widget[3])
						self.render()
						warning_printed = True
			
			# If mouse clicks should be recorded, save them
			if track_clicks:
				if mouse_button != None:
					clicks.append(mouse_button)
					clicks_timestamps.append(timestamp)
			
			# If there was a mouse click, determine the button that was clicked
			# and if click was on a button, end tracking and finish form
			# (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
			if click_required == False or mouse_button in mouse_buttons_allowed:
				
				pos = self.xy_to_index(position)
				
				if pos != None:
					w = self.widgets[pos]
					if w != None:
						resp = self.widgets[pos].on_mouse_click(xy)
						if resp != None:
							tracking = False
			
			# Update timeleft
			if timeout != None:
				timeleft = timeout-(timestamp-timestamps[0])
			
		# Calculate response time
		resp_time = timestamps[-1]-timestamps[0]
		
		# Set form_response variable
		self.experiment.var.form_response = resp
		
		if track_clicks == False:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos
		else:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #19
0
    def _exec(self, focus_widget=None):
        """
		desc:
			Executes the form.

		keywords:
			focus_widget:
				desc:	A widget that is in the form and should receive a
						virtual mouse click when the form is opened. This allows
						you to activate a text_input right away, for example, so
						that the user doesn't have to click on it anymore.
				type:	[widget, NoneType]

		returns:
			desc:	Gives the return value of the form, which depends on how the
					user interacted with the widgets. For example, if the user
					pressed a button, the button text will be returned. If a
					timeout occurred, None will be returned.
		"""

        if isinstance(focus_widget, WidgetFactory):
            focus_widget = focus_widget.construct(self)
        if len(self) == 0:
            raise osexception(u'The form contains no widgets')
        ms = mouse(self.experiment, timeout=0)
        ms.show_cursor()
        kb = keyboard(self.experiment, timeout=0)
        kb.show_virtual_keyboard()
        coroutines = {w: w.coroutine() for w in self.widgets if w is not None}
        for coroutine in coroutines.values():
            coroutine.send(None)
        self.canvas.show()
        self.start_time = None
        mousedown = False
        while True:
            if self.timed_out():
                resp = None
                break
            msg = None
            # Handle mouse clicks, including waiting until the mouse is released
            # after a mouse click.
            if mousedown:
                while any(ms.get_pressed()):
                    pass
                mousedown = False
            button, xy, timestamp = ms.get_click(visible=True)
            if button is not None:
                mousedown = True
                # Switch the focus to the newly clicked widget (if any)
                widget = self.xy_to_widget(xy)
                if widget is None:
                    continue
                if focus_widget is not None:
                    focus_widget.focus = False
                widget.focus = True
                focus_widget = widget
                msg = {
                    u'type': u'click',
                    u'pos': xy,
                    u'button': button,
                    u'timestamp': timestamp
                }
            # Handle key presses clicks
            elif focus_widget is not None:
                key, timestamp = kb.get_key()
                if key is not None:
                    msg = {
                        u'type': u'key',
                        u'key': key,
                        u'timestamp': timestamp
                    }
            # Send message (if any)
            if msg is None:
                continue
            resp = coroutines[focus_widget].send(msg)
            self.canvas.show()
            if resp is not None and self._validator():
                break
        kb.show_virtual_keyboard(False)
        ms.show_cursor(False)
        for coroutine in coroutines.values():
            try:
                coroutine.send({u'type': u'stop'})
            except StopIteration:
                pass
        self.experiment.var.form_response = resp
        return resp
Example #20
0
from openexp.mouse import mouse
from openexp.canvas import canvas
from openexp.keyboard import keyboard
from openexp.sampler import sampler
from random import random, shuffle

# variables

myMouse = mouse(exp, visible=True)
index = 99
myCanvas = self.copy_sketchpad('planche1')
myKeyboard = keyboard(exp, timeout=None)
cases = []
for i in range(30):
    cases.append(0)
startTime = self.time()
totalTime = 0
interval = False
complexity = False  # true = easy
duration = False  # true = quick
Interruption = False
clicks = 0
numberInterruptions2 = 0
clickTrigger = clicks[numberInterruptions2]
goodClicks = 0
isInterruption = False
hasEndInterruption = False
endInterruption = False
currentInterruption = 0
displayResponseTime = 500
displayNumberTime = 1000
Example #21
0
	def _exec(self,
		logging_resolution=10, timeout=None,
		boundaries={'upper':None,'lower':None,'left':None,'right':None},
		reset_mouse=True, start_coordinates=(0,0),
		click_required=True, mouse_buttons_allowed=[1, 3],
		track_clicks=False,
		max_initiation_time=None, warning_textline=None):
	    
		"""Executes MT_response object and returns results.

    	Executes the MT_response object and returns the response, response time,
		and mouse-tracking data.

	    Args:
	        logging_resolution (int): Time interval (in ms) between recordings 
				of the mouse position.
			timeout (int): Response timeout (in ms). Use None (default) if there
				is no timeout.
			boundaries (dict): Contains optional vertical and horizontal 
				boundaries. Tracking stops if the cursor moves beyond one of 
				these.
			reset_mouse (bool): Reset mouse position when tracking starts.
			start_coordinates (tuple): The x- and y- coordinates (in sketchpad 
				metric) the cursor should be reset to.
			click_required (bool): Click required to indicate response. If False, 
				a response can be indicated just by entering the area of one 
				of the buttons with the mouse.
			mouse_buttons_allowed (list): The (physical) mouse buttons that 
				can be used to click one of the buttons.
			track_clicks (bool): Enable separate tracking of mouse clicks. 
				If True, the physical mouse button that was clicked will be 
				returned along with a corresponding timestamp as a separate 
				list.
			max_initiation_time (int): If specified, a custom warning message 
				will be displayed if no mouse movement was initiated after the 
				specified time limit (in ms).
			warning_textline (list): Custom warning message to be displayed. List
				containing the name of the currently displayed canvas/sketchpad 
				as the first element and input for the canvas.text function as 
				the second argument.
	    
		Returns:
			resp (str): The name (key) of the buttton that was clicked.
			resp_time (int): Response time (in ms).
			initiation_time (int): Time (in ms) until a movement was initiated.
			timestamps (list): Timestamps (in ms) for each recorded position.
			xpos (list): x-positions for each recorded position.
			ypos (list): y-positions for each recorded position.
			clicks (list): (Physical) mouse button for each mouse click. 
				Only returned if track_clicks is True.
			clicks_timestamps (list): Timestamp (in ms) for each mouse click. 
				Only returned if track_clicks is True.
	    """	
		
		# Initialize mouse
		self.mouse = mouse(self.experiment, visible=True)
		
		# Initialize clock
		self.clock = self.experiment._clock
		
		# Specify timeout settings
		if timeout != None:
			timeout = int(timeout)
			timeleft = timeout
		else:
			timeleft = logging_resolution
		
		# Check if any boundary values are specified
		check_boundaries = any(val!=None for val in boundaries.values())
			
		# Check if timeout or boundaries are specified in case there are no buttons
		if self.buttons == None:
			if timeout == None and check_boundaries == False:
				raise osexception('As no buttons are specified, either a timeout or boundaries have to be specified.')
		
		# Prepare boundaries if boundary values are specified
		if check_boundaries:
		
			check_boundaries_x = False
			if any(boundaries[label] != None for label in ['left', 'right']):
				check_boundaries_x = True
				boundaries_x = [-float('Inf'), float('Inf')]
				if boundaries['left'] != None:
					boundaries_x[0] = int(boundaries['left'])
				if boundaries['right'] != None:
					boundaries_x[1] = int(boundaries['right'])
				
			check_boundaries_y = False
			if any(boundaries[label] != None for label in ['upper', 'lower']):
				check_boundaries_y = True
				boundaries_y = [-float('Inf'), float('Inf')]
				# As OpenSesame's screen coordinates increase when mouse moves toward the bottom of the screen
				# assign the value of 'upper' boundary as the lower value (and vice versa)
				if boundaries['upper'] != None:
					boundaries_y[0] = int(boundaries['upper'])
				if boundaries['lower'] != None:
					boundaries_y[1] = int(boundaries['lower'])
		
		# Reset mouse (if specified)
		if reset_mouse:
			# Move mouse cursor to the position specified in pixel
			startx_mouse = int(start_coordinates[0])
			starty_mouse = int(start_coordinates[1])
						
			# Set mouse position
			self.mouse.set_pos((startx_mouse, starty_mouse))
			
			# Set up variables including their first values
			timestamps = [self.clock.time()]
			xpos = [startx_mouse]
			ypos = [starty_mouse]
		
		# Get mouse position otherwise
		else:
			# Set up variables including their first values
			position, timestamp = self.mouse.get_pos()
			timestamps = [timestamp]
			xpos = [position[0]]
			ypos = [position[1]]
			
		# Show mouse
		self.mouse.show_cursor(show=True)
		
		# Set tracking variables
		tracking = True
		mouse_on_start = True
		warning_printed = False
		resp = None
		initiation_time = None
		
		if track_clicks:
			clicks = []
			clicks_timestamps = []
		
		# Start tracking
		while tracking and timeleft > 0:
			
			# Collect mouse response
			if timeout==None:
				# (timeout corresponds to interval with which mouse coordinates are recorded)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None, timeout=logging_resolution)
			else:
				# (timeout corresponds to interval with which mouse coordinates are recorded,
				#  or time left - whatever is smaller)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None, timeout=min([logging_resolution, timeleft]))
			
			# Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
			# (as get_click returns None for xy if there was no mouse click)
			if xy != None:
				position = xy
				timestamp = time
			else:
				position, timestamp = self.mouse.get_pos()
			
			# Append values
			timestamps.append(timestamp)
			xpos.append(position[0])
			ypos.append(position[1])
				
			# Check if mouse has left the starting position, and, if so, determine initiation time
			if mouse_on_start == True:
				mouse_on_start = (position[0] == xpos[0]) and (position[1] == ypos[0])
				if mouse_on_start == False:
					# difference between last (not current) timestamp and timestamp at start
					initiation_time = timestamps[-2]-timestamps[0]

			
			# If mouse is still on starting position and initiation time is exceeded, show warning
			if max_initiation_time != None:
				if mouse_on_start == True and warning_printed == False:
					if (timestamp-timestamps[0]) > max_initiation_time:
						warning_canvas = self.experiment.items[warning_textline[0]].canvas
						warning_canvas.text(**warning_textline[1])
						warning_canvas.show()
						warning_printed = True
			
			# If mouse clicks should be recorded, save them
			if track_clicks:
				if mouse_button != None:
					clicks.append(mouse_button)
					clicks_timestamps.append(timestamp)
			
			# If boundaries should be checked, determine if mouse position is outside the boundaries
			if check_boundaries:
				if check_boundaries_x:
					if position[0] < boundaries_x[0] or position[0] > boundaries_x[1]:
						tracking = False
				if check_boundaries_y:
					if position[1] < boundaries_y[0] or position[1] > boundaries_y[1]:
						tracking = False
			
			# If there was a mouse click, determine if the click was in the range of one of the "buttons"
			# (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
			if click_required == False or mouse_button in mouse_buttons_allowed:
				if self.buttons != None:
					if position != None:
						resp = None
						for button in self.buttons:
							vals = self.buttons[button]
							if position[0] >= vals[0] and position[0] <= vals[2] and position[1] >= vals[1] and position[1] <= vals[3]:
								resp = button
						if resp != None:
							tracking = False
							
			# Update timeleft
			if timeout != None:
				timeleft = timeout-(timestamp-timestamps[0])

			
		# Calculate response time
		resp_time = timestamps[-1] - timestamps[0]
		
		if track_clicks == False:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos
		else:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #22
0
    def run(self):

        """The run phase of the plug-in goes here."""

        # self.set_item_onset() sets the time_[item name] variable. Optionally,
        # you can pass a timestamp, such as returned by canvas.show().
        # self.set_item_onset(self.c.show())

        # The following is the opening screen of the experiment
        # Needs a good bit of work
        exp = self.experiment
        from openexp.mouse import mouse
        from openexp.canvas import canvas
        from openexp.keyboard import keyboard
        import urllib

        # import socket
        # import errno
        import os
        import time

        # Using more than one timing method?
        from pygame.mouse import get_pressed
        from random import randint

        subject_number = randint(1, 99999)

        try:
            import android
        except ImportError:
            android = None

            # Define global variables/methods
        my_mouse = mouse(exp, visible=True)
        self.c = canvas(exp, auto_prepare=False)
        self.c = canvas(self.experiment, self.get(u"background"), self.get(u"foreground"))
        my_keyboard = keyboard(exp)
        exp.set("run_experiment", 1)

        global my_mouse, my_canvas, my_keyboard, urllib, event
        global pickle, os, android, time, get_pressed, subject_number
        # print 'Path = '+str(os.path.curdir)

        sdcard_folders = ["/sdcard/", "/mnt/sdcard/"]
        for path in sdcard_folders:
            if os.path.isdir(path):
                print path
                break
        if os.path.exists(os.path.join(path, "datafile.txt")):
            data_path = os.path.join(path, "datafile.txt")
        elif os.path.exists("datafile.txt"):
            data_path = "datafile.txt"
        else:
            data_path = None
        global data_path
        if data_path:
            print "Unsent data detected"
            my_canvas.clear()
            self.c.text("Unsent data detected. Send now?")
            self.c.text("Yes", x=150, y=125)
            self.c.text("No", x=1050, y=125)
            self.c.show()
            while 1:
                button, position, timestamp = my_mouse.get_click()
                x, y = position
                if x < 350 and y < 200:
                    # Yes
                    try:
                        print "Opening data..."
                        execfile(data_path)
                        global data_log
                        print "Opened"
                        # Try to send it
                        send_data(data_log, True)
                    except IOError as e:
                        self.c.clear()
                        self.c.text("No data found.\nTap to continue.")
                        # Hopefully, this doesn't happen!
                        self.c.show()
                        my_mouse.get_click()
                    break
                if x > 930 and y < 200:
                    # No
                    # This overwrites old data.
                    # Add a warning about this.
                    break
            self.c.clear()
            self.c.text("Continue to experiment?")
            self.c.text("Yes", x=150, y=125)
            self.c.text("No", x=1050, y=125)
            self.c.show()
            waiting = True
            while waiting:
                button, position, timestamp = my_mouse.get_click()
                x, y = position
                if x < 350 and y < 200:
                    exp.set("run_experiment", 1)
                    break
                if x > 930 and y < 200:
                    exp.set("run_experiment", 0)
                    break

        data_log = []
        trial_id = 0
        global data_log, trial_id
Example #23
0
    def _exec(self,
              logging_resolution=10,
              timeout=None,
              boundaries={
                  'upper': None,
                  'lower': None,
                  'left': None,
                  'right': None
              },
              reset_mouse=True,
              start_coordinates=(0, 0),
              click_required=True,
              mouse_buttons_allowed=[1, 3],
              track_clicks=False,
              max_initiation_time=None,
              warning_textline=None):

        # Initialize mouse
        self.mouse = mouse(self.experiment, visible=True)

        # Initialize clock
        self.clock = self.experiment._clock

        # Specify timeout settings
        if timeout != None:
            timeout = int(timeout)
            timeleft = timeout
        else:
            timeleft = logging_resolution

        # Check if any boundary values are specified
        check_boundaries = any(val != None for val in boundaries.values())

        # Check if timeout or boundaries are specified in case there are no buttons
        if self.buttons == None:
            if timeout == None and check_boundaries == False:
                raise osexception(
                    'As no buttons are specified, either a timeout or boundaries have to be specified.'
                )

        # Prepare boundaries if boundary values are specified
        if check_boundaries:

            check_boundaries_x = False
            if any(boundaries[label] != None for label in ['left', 'right']):
                check_boundaries_x = True
                boundaries_x = [-float('Inf'), float('Inf')]
                if boundaries['left'] != None:
                    boundaries_x[0] = int(boundaries['left'])
                if boundaries['right'] != None:
                    boundaries_x[1] = int(boundaries['right'])

            check_boundaries_y = False
            if any(boundaries[label] != None for label in ['upper', 'lower']):
                check_boundaries_y = True
                boundaries_y = [-float('Inf'), float('Inf')]
                # As OpenSesame's screen coordinates increase when mouse moves toward the bottom of the screen
                # assign the value of 'upper' boundary as the lower value (and vice versa)
                if boundaries['upper'] != None:
                    boundaries_y[0] = int(boundaries['upper'])
                if boundaries['lower'] != None:
                    boundaries_y[1] = int(boundaries['lower'])

        # Reset mouse (if specified)
        if reset_mouse:
            # Move mouse cursor to the position specified in pixel
            startx_mouse = int(start_coordinates[0])
            starty_mouse = int(start_coordinates[1])

            # Set mouse position
            self.mouse.set_pos((startx_mouse, starty_mouse))

            # Set up variables including their first values
            timestamps = [self.clock.time()]
            xpos = [startx_mouse]
            ypos = [starty_mouse]

        # Get mouse position otherwise
        else:
            # Set up variables including their first values
            position, timestamp = self.mouse.get_pos()
            timestamps = [timestamp]
            xpos = [position[0]]
            ypos = [position[1]]

        # Show mouse
        self.mouse.show_cursor(show=True)

        # Set tracking variables
        tracking = True
        mouse_on_start = True
        warning_printed = False
        resp = None
        initiation_time = None

        if track_clicks:
            clicks = []
            clicks_timestamps = []

        # Start tracking
        while tracking and timeleft > 0:

            # Collect mouse response
            if timeout == None:
                # (timeout corresponds to interval with which mouse coordinates are recorded)
                mouse_button, xy, time = self.mouse.get_click(
                    buttonlist=None, timeout=logging_resolution)
            else:
                # (timeout corresponds to interval with which mouse coordinates are recorded,
                #  or time left - whatever is smaller)
                mouse_button, xy, time = self.mouse.get_click(
                    buttonlist=None,
                    timeout=min([logging_resolution, timeleft]))

            # Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
            # (as get_click returns None for xy if there was no mouse click)
            if xy != None:
                position = xy
                timestamp = time
            else:
                position, timestamp = self.mouse.get_pos()

            # Append values
            timestamps.append(timestamp)
            xpos.append(position[0])
            ypos.append(position[1])

            # Check if mouse has left the starting position, and, if so, determine initiation time
            if mouse_on_start == True:
                mouse_on_start = (position[0] == xpos[0]) and (position[1]
                                                               == ypos[0])
                if mouse_on_start == False:
                    # difference between last (not current) timestamp and timestamp at start
                    initiation_time = timestamps[-2] - timestamps[0]

            # If mouse is still on starting position and initiation time is exceeded, show warning
            if max_initiation_time != None:
                if mouse_on_start == True and warning_printed == False:
                    if (timestamp - timestamps[0]) > max_initiation_time:
                        warning_canvas = self.experiment.items[
                            warning_textline[0]].canvas
                        warning_canvas.text(**warning_textline[1])
                        warning_canvas.show()
                        warning_printed = True

            # If mouse clicks should be recorded, save them
            if track_clicks:
                if mouse_button != None:
                    clicks.append(mouse_button)
                    clicks_timestamps.append(timestamp)

            # If boundaries should be checked, determine if mouse position is outside the boundaries
            if check_boundaries:
                if check_boundaries_x:
                    if position[0] < boundaries_x[0] or position[
                            0] > boundaries_x[1]:
                        tracking = False
                if check_boundaries_y:
                    if position[1] < boundaries_y[0] or position[
                            1] > boundaries_y[1]:
                        tracking = False

            # If there was a mouse click, determine if the click was in the range of one of the "buttons"
            # (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
            if click_required == False or mouse_button in mouse_buttons_allowed:
                if self.buttons != None:
                    if position != None:
                        resp = None
                        for button in self.buttons:
                            vals = self.buttons[button]
                            if position[0] >= vals[0] and position[0] <= vals[
                                    2] and position[1] >= vals[1] and position[
                                        1] <= vals[3]:
                                resp = button
                        if resp != None:
                            tracking = False

            # Update timeleft
            if timeout != None:
                timeleft = timeout - (timestamp - timestamps[0])

        # Calculate response time
        resp_time = timestamps[-1] - timestamps[0]

        if track_clicks == False:
            return resp, resp_time, initiation_time, timestamps, xpos, ypos
        else:
            return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #24
0
	def _exec(self,
		logging_resolution=10,timeout=None,
		reset_mouse=True,start_unit='grid',start_coordinates=(6.0,4.5),
		click_required=True,mouse_buttons_allowed=[1,3],
		track_clicks=False,
		max_initiation_time=None,warning_widget=None):
		
		# Specify timeout settings
		if timeout != None:
			timeout = int(timeout)
			timeleft = timeout
		else:
			timeleft = logging_resolution
		
		# Calculate start coordinates (if mouse should be reset)
		if reset_mouse:
		
			# Check if start_coordinates are in allowed range
			if start_unit in ['grid', 'widget']:
				if start_coordinates[0] > len(self.cols)-1:
					raise osexception('start x coordinate exceeds number of colums - 1 (first column has value 0)')
				if  start_coordinates[1] > len(self.rows)-1:
					raise osexception('start y coordinate exceeds number of rows - 1 (first row has value 0)')
			
			# Unit: grid
			# move mouse cursor to the left upper corner of the grid position
			# (if float is given, linear interpolation is performed)
			if start_unit=='grid':
				
				start_index = self.cell_index((int(start_coordinates[0]),int(start_coordinates[1])))
				startx_mouse, starty_mouse, w, h = self.get_rect(start_index)
				
				# if form coordinates are provided as float, use linear interpolation
				# (as internal form function only accepts integers)
				if isinstance(start_coordinates[0], float):
					start_index_upper = self.cell_index((int(start_coordinates[0])+1,int(start_coordinates[1])))
					startx_upper, y, w, h = self.get_rect(start_index_upper)			
					startx_mouse += int((startx_upper-startx_mouse) * (start_coordinates[0]-int(start_coordinates[0])))
					
				if isinstance(start_coordinates[1], float):
					start_index_upper = self.cell_index((int(start_coordinates[0]),int(start_coordinates[1])+1))
					x, starty_upper, w, h = self.get_rect(start_index_upper)			
					starty_mouse += int((starty_upper-starty_mouse) * (start_coordinates[1]-int(start_coordinates[1])))

			# Unit: widget
			# move mouse cursor to the center of the widget for which starting coordinates are provided
			# (if no widget has the start coordinates for this position, mouse is centered on the position of the grid)
			elif start_unit=='widget':
				start_index = self.cell_index((int(start_coordinates[0]),int(start_coordinates[1])))
				startx_mouse, starty_mouse, w, h = self.get_rect(start_index)
				startx_mouse += w/2
				starty_mouse += h/2
			
			# Unit: pixel
			# move mouse cursor to the position specified in pixel
			elif start_unit=='pixel':
				startx_mouse = start_coordinates[0]
				starty_mouse = start_coordinates[1]
			
			else:
				raise osexception('start_unit should be one of the following: grid, widget, pixel')
			
			# Convert pixel values to integers
			startx_mouse = int(startx_mouse)
			starty_mouse = int(starty_mouse)
					
		
		# Render form
		self.render()
		
		# Initialize mouse
		self.mouse = mouse(self.experiment,visible=True)
		
		# Initialize clock
		self.clock = self.experiment._clock
		
		# Reset mouse (if specified)
		if reset_mouse:
		
			# Set mouse position
			self.mouse.set_pos((startx_mouse,starty_mouse))
			
			# Set up variables including their first values
			timestamps = [self.clock.time()]
			xpos = [startx_mouse]
			ypos = [starty_mouse]
		
		
		# Get mouse position otherwise		
		else:
		
			# Get mouse position
			position, timestamp = self.mouse.get_pos()
			
			# Set up variables including their first values
			timestamps = [timestamp]
			xpos = [position[0]]
			ypos = [position[1]]
		
		# Show mouse
		self.mouse.show_cursor(show=True)
		
		# Set tracking variables
		tracking = True
		mouse_on_start = True
		warning_printed = False
		resp = None
		initiation_time = None
		
		if track_clicks:
			clicks = []
			clicks_timestamps = []

		
		# Start tracking
		while tracking and timeleft>0:
			
			# Collect mouse response
			if timeout==None:
				# (timeout corresponds to interval with which mouse coordinates are recored)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None,timeout=logging_resolution)
			else:
				# (timeout corresponds to interval with which mouse coordinates are recored,
				#  or time left - whatever is smaller)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None,timeout=min([logging_resolution,timeleft]))
			
			# Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
			# (as get_click returns None for xy if there was no mouse click)
			if xy != None:
				position = xy
				timestamp = time
			else:
				position, timestamp = self.mouse.get_pos()
			
			# Append values
			timestamps.append(timestamp)
			xpos.append(position[0])
			ypos.append(position[1])
			
			# Check if mouse has left the starting position, and, if so, determine initiation time
			if mouse_on_start == True:
				mouse_on_start = (position[0] == xpos[0]) and (position[1] == ypos[0])
				if mouse_on_start == False:
					# difference between last (not current) timestamp and timestamp at start
					initiation_time = timestamps[-2]-timestamps[0]
			
			# If mouse is still on starting position and initiation time is exceeded, show warning
			if max_initiation_time != None:
				if mouse_on_start == True and warning_printed == False:
					if (timestamp-timestamps[0])>max_initiation_time:
						self.set_widget(warning_widget[0],warning_widget[1],colspan=warning_widget[2],rowspan=warning_widget[3])
						self.render()
						warning_printed = True
			
			# If mouse clicks should be recorded, save them
			if track_clicks:
				if mouse_button != None:
					clicks.append(mouse_button)
					clicks_timestamps.append(timestamp)
			
			# If there was a mouse click, determine the button that was clicked
			# and if click was on a button, end tracking and finish form
			# (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
			if click_required == False or mouse_button in mouse_buttons_allowed:
				
				pos = self.xy_to_index(position)
				
				if pos != None:
					w = self.widgets[pos]
					if w != None:
						resp = self.widgets[pos].on_mouse_click(xy)
						if resp != None:
							tracking = False
			
			# Update timeleft
			if timeout != None:
				timeleft = timeout-(timestamp-timestamps[0])
			
		# Calculate response time
		resp_time = timestamps[-1]-timestamps[0]
		
		# Set form_response variable
		self.experiment.var.form_response = resp
		
		if track_clicks == False:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos
		else:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #25
0
	def _exec(self,
		logging_resolution=10, timeout=None,
		boundaries={'upper':None,'lower':None,'left':None,'right':None},
		reset_mouse=True, start_coordinates=(0,0),
		click_required=True, mouse_buttons_allowed=[1, 3],
		track_clicks=False,
		max_initiation_time=None, warning_textline=None):
	    
		"""Executes MT_response object and returns results.

    	Executes the MT_response object and returns the response, response time,
		and mouse-tracking data.

	    Args:
	        logging_resolution (int): Time interval (in ms) between recordings 
				of the mouse position.
			timeout (int): Response timeout (in ms). Use None (default) if there
				is no timeout.
			boundaries (dict): Contains optional vertical and horizontal 
				boundaries. Tracking stops if the cursor moves beyond one of 
				these.
			reset_mouse (bool): Reset mouse position when tracking starts.
			start_coordinates (tuple): The x- and y- coordinates (in sketchpad 
				metric) the cursor should be reset to.
			click_required (bool): Click required to indicate response. If False, 
				a response can be indicated just by entering the area of one 
				of the buttons with the mouse.
			mouse_buttons_allowed (list): The (physical) mouse buttons that 
				can be used to click one of the buttons.
			track_clicks (bool): Enable separate tracking of mouse clicks. 
				If True, the physical mouse button that was clicked will be 
				returned along with a corresponding timestamp as a separate 
				list.
			max_initiation_time (int): If specified, a custom warning message 
				will be displayed if no mouse movement was initiated after the 
				specified time limit (in ms).
			warning_textline (list): Custom warning message to be displayed. List
				containing the name of the currently displayed canvas/sketchpad 
				as the first element and input for the canvas.text function as 
				the second argument.
	    
		Returns:
			resp (str): The name (key) of the buttton that was clicked.
			resp_time (int): Response time (in ms).
			initiation_time (int): Time (in ms) until a movement was initiated.
			timestamps (list): Timestamps (in ms) for each recorded position.
			xpos (list): x-positions for each recorded position.
			ypos (list): y-positions for each recorded position.
			clicks (list): (Physical) mouse button for each mouse click. 
				Only returned if track_clicks is True.
			clicks_timestamps (list): Timestamp (in ms) for each mouse click. 
				Only returned if track_clicks is True.
	    """	
		
		# Initialize mouse
		self.mouse = mouse(self.experiment, visible=True)
		self.mouse.show_cursor(show=True)
		
		# Initialize clock
		self.clock = self.experiment._clock
		
		# Specify timeout settings
		if timeout != None:
			timeout = int(timeout)
			timeleft = timeout
		else:
			timeleft = logging_resolution
		
		# Check if any boundary values are specified
		check_boundaries = any(val!=None for val in boundaries.values())
			
		# Check if timeout or boundaries are specified in case there are no buttons
		if self.buttons == None:
			if timeout == None and check_boundaries == False:
				raise osexception('As no buttons are specified, either a timeout or boundaries have to be specified.')
		
		# Prepare boundaries if boundary values are specified
		if check_boundaries:
		
			check_boundaries_x = False
			if any(boundaries[label] != None for label in ['left', 'right']):
				check_boundaries_x = True
				boundaries_x = [-float('Inf'), float('Inf')]
				if boundaries['left'] != None:
					boundaries_x[0] = int(boundaries['left'])
				if boundaries['right'] != None:
					boundaries_x[1] = int(boundaries['right'])
				
			check_boundaries_y = False
			if any(boundaries[label] != None for label in ['upper', 'lower']):
				check_boundaries_y = True
				boundaries_y = [-float('Inf'), float('Inf')]
				# As OpenSesame's screen coordinates increase when mouse moves toward the bottom of the screen
				# assign the value of 'upper' boundary as the lower value (and vice versa)
				if boundaries['upper'] != None:
					boundaries_y[0] = int(boundaries['upper'])
				if boundaries['lower'] != None:
					boundaries_y[1] = int(boundaries['lower'])
		
		# Reset mouse (if specified)
		if reset_mouse:
			# Move mouse cursor to the position specified in pixel
			startx_mouse = int(start_coordinates[0])
			starty_mouse = int(start_coordinates[1])
						
			# Set mouse position
			self.mouse.set_pos((startx_mouse, starty_mouse))
			
			# Set up variables including their first values
			timestamps = [self.clock.time()]
			xpos = [startx_mouse]
			ypos = [starty_mouse]
		
		# Get mouse position otherwise
		else:
			# Set up variables including their first values
			position, timestamp = self.mouse.get_pos()
			timestamps = [timestamp]
			xpos = [position[0]]
			ypos = [position[1]]
			
		# Show mouse
		self.mouse.show_cursor(show=True)
		
		# Set tracking variables
		tracking = True
		mouse_on_start = True
		warning_printed = False
		resp = None
		initiation_time = None
		
		if track_clicks:
			clicks = []
			clicks_timestamps = []
		
		# Start tracking
		while tracking and timeleft > 0:
			
			# Collect mouse response
			if timeout==None:
				# (timeout corresponds to interval with which mouse coordinates are recorded)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None, timeout=logging_resolution)
			else:
				# (timeout corresponds to interval with which mouse coordinates are recorded,
				#  or time left - whatever is smaller)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None, timeout=min([logging_resolution, timeleft]))
			
			# Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
			# (as get_click returns None for xy if there was no mouse click)
			if xy != None:
				position = xy
				timestamp = time
			else:
				position, timestamp = self.mouse.get_pos()
			
			# Append values
			timestamps.append(timestamp)
			xpos.append(position[0])
			ypos.append(position[1])
				
			# Check if mouse has left the starting position, and, if so, determine initiation time
			if mouse_on_start == True:
				mouse_on_start = (position[0] == xpos[0]) and (position[1] == ypos[0])
				if mouse_on_start == False:
					# difference between last (not current) timestamp and timestamp at start
					initiation_time = timestamps[-2]-timestamps[0]

			
			# If mouse is still on starting position and initiation time is exceeded, show warning
			if max_initiation_time != None:
				if mouse_on_start == True and warning_printed == False:
					if (timestamp-timestamps[0]) > max_initiation_time:
						warning_canvas = self.experiment.items[warning_textline[0]].canvas
						warning_canvas.text(**warning_textline[1])
						warning_canvas.show()
						warning_printed = True
			
			# If mouse clicks should be recorded, save them
			if track_clicks:
				if mouse_button != None:
					clicks.append(mouse_button)
					clicks_timestamps.append(timestamp)
			
			# If boundaries should be checked, determine if mouse position is outside the boundaries
			if check_boundaries:
				if check_boundaries_x:
					if position[0] < boundaries_x[0] or position[0] > boundaries_x[1]:
						tracking = False
				if check_boundaries_y:
					if position[1] < boundaries_y[0] or position[1] > boundaries_y[1]:
						tracking = False
			
			# If there was a mouse click, determine if the click was in the range of one of the "buttons"
			# (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
			if click_required == False or mouse_button in mouse_buttons_allowed:
				if self.buttons != None:
					if position != None:
						resp = None
						for button in self.buttons:
							vals = self.buttons[button]
							if position[0] >= vals[0] and position[0] <= vals[2] and position[1] >= vals[1] and position[1] <= vals[3]:
								resp = button
						if resp != None:
							tracking = False
							
			# Update timeleft
			if timeout != None:
				timeleft = timeout-(timestamp-timestamps[0])

			
		# Calculate response time
		resp_time = timestamps[-1] - timestamps[0]
		
		if track_clicks == False:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos
		else:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #26
0
	def _exec(self,
		logging_resolution=10,timeout=None,
		boundaries = {'upper':None,'lower':None,'left':None,'right':None},
		reset_mouse=True,start_coordinates=(0,0),
		click_required=True,mouse_buttons_allowed=[1,3],
		track_clicks=False,
		max_initiation_time=None,warning_textline=None):
		
		# Initialize mouse
		self.mouse = mouse(self.experiment,visible=True)
		
		# Initialize clock
		self.clock = self.experiment._clock
		
		# Specify timeout settings
		if timeout != None:
			timeout = int(timeout)
			timeleft = timeout
		else:
			timeleft = logging_resolution
		
		# Check if any boundary values are specified
		check_boundaries = any(val!=None for val in boundaries.values())
			
		# Check if timeout or boundaries are specified in case there are no buttons
		if self.buttons == None:
			if timeout == None and check_boundaries == False:
				raise osexception('As no buttons are specified, either a timeout or boundaries have to be specified.')
		
		# Prepare boundaries if boundary values are specified
		if check_boundaries:
		
			check_boundaries_x = False
			if any(boundaries[label]!= None for label in ['left','right']):
				check_boundaries_x = True
				boundaries_x = [-float('Inf'),float('Inf')]
				if boundaries['left'] != None:
					boundaries_x[0] = int(boundaries['left'])
				if boundaries['right'] != None:
					boundaries_x[1] = int(boundaries['right'])
				
			check_boundaries_y = False
			if any(boundaries[label]!= None for label in ['upper','lower']):
				check_boundaries_y = True
				boundaries_y = [-float('Inf'),float('Inf')]
				# As OpenSesame's screen coordinates increase when mouse moves toward the bottom of the screen
				# assign the value of 'upper' boundary as the lower value (and vice versa)
				if boundaries['upper'] != None:
					boundaries_y[0] = int(boundaries['upper'])
				if boundaries['lower'] != None:
					boundaries_y[1] = int(boundaries['lower'])
		
		# Reset mouse (if specified)
		if reset_mouse:
			# Move mouse cursor to the position specified in pixel
			startx_mouse = int(start_coordinates[0])
			starty_mouse = int(start_coordinates[1])
						
			# Set mouse position
			self.mouse.set_pos((startx_mouse,starty_mouse))
			
			# Set up variables including their first values
			timestamps = [self.clock.time()]
			xpos = [startx_mouse]
			ypos = [starty_mouse]
		
		# Get mouse position otherwise
		else:
			# Set up variables including their first values
			position, timestamp = self.mouse.get_pos()
			timestamps = [timestamp]
			xpos = [position[0]]
			ypos = [position[1]]
			
		# Show mouse
		self.mouse.show_cursor(show=True)
		
		# Set tracking variables
		tracking = True
		mouse_on_start = True
		warning_printed = False
		resp = None
		initiation_time = None
		
		if track_clicks:
			clicks = []
			clicks_timestamps = []
		
		# Start tracking
		while tracking and timeleft>0:
			
			# Collect mouse response
			if timeout==None:
				# (timeout corresponds to interval with which mouse coordinates are recorded)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None,timeout=logging_resolution)
			else:
				# (timeout corresponds to interval with which mouse coordinates are recorded,
				#  or time left - whatever is smaller)
				mouse_button, xy, time = self.mouse.get_click(buttonlist=None,timeout=min([logging_resolution,timeleft]))
			
			# Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
			# (as get_click returns None for xy if there was no mouse click)
			if xy != None:
				position = xy
				timestamp = time
			else:
				position, timestamp = self.mouse.get_pos()
			
			# Append values
			timestamps.append(timestamp)
			xpos.append(position[0])
			ypos.append(position[1])
				
			# Check if mouse has left the starting position, and, if so, determine initiation time
			if mouse_on_start == True:
				mouse_on_start = (position[0] == xpos[0]) and (position[1] == ypos[0])
				if mouse_on_start == False:
					# difference between last (not current) timestamp and timestamp at start
					initiation_time = timestamps[-2]-timestamps[0]

			
			# If mouse is still on starting position and initiation time is exceeded, show warning
			if max_initiation_time != None:
				if mouse_on_start == True and warning_printed == False:
					if (timestamp-timestamps[0])>max_initiation_time:
						warning_canvas = self.experiment.items[warning_textline[0]].canvas
						warning_canvas.text(**warning_textline[1])
						warning_canvas.show()
						warning_printed = True
			
			# If mouse clicks should be recorded, save them
			if track_clicks:
				if mouse_button != None:
					clicks.append(mouse_button)
					clicks_timestamps.append(timestamp)
			
			# If boundaries should be checked, determine if mouse position is outside the boundaries
			if check_boundaries:
				if check_boundaries_x:
					if position[0] < boundaries_x[0] or position[0] > boundaries_x[1]:
						tracking = False
				if check_boundaries_y:
					if position[1] < boundaries_y[0] or position[1] > boundaries_y[1]:
						tracking = False
			
			# If there was a mouse click, determine if the click was in the range of one of the "buttons"
			# (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
			if click_required == False or mouse_button in mouse_buttons_allowed:
				if self.buttons != None:
					if position != None:
						resp = None
						for button in self.buttons:
							vals = self.buttons[button]
							if position[0]>=vals[0] and position[0]<=vals[2] and position[1]>=vals[1] and position[1]<=vals[3]:
								resp = button
						if resp != None:
							tracking = False
							
			# Update timeleft
			if timeout != None:
				timeleft = timeout-(timestamp-timestamps[0])

			
		# Calculate response time
		resp_time = timestamps[-1]-timestamps[0]
		
		if track_clicks == False:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos
		else:
			return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps
Example #27
0
    def _exec(self,
              logging_resolution=10,
              timeout=None,
              reset_mouse=True,
              start_unit='grid',
              start_coordinates=(6.0, 4.5),
              click_required=True,
              mouse_buttons_allowed=[1, 3],
              track_clicks=False,
              max_initiation_time=None,
              warning_widget=None):
        """Executes MT_form object and returns results.

    	Executes the MT_form object to display the form, collect responses, and
		return the response, response time, and mouse-tracking data.

	    Args:
	        logging_resolution (int): Time interval (in ms) between recordings 
				of the mouse position.
			timeout (int): Response timeout (in ms). Use None (default) if there
				is no timeout.
			reset_mouse (bool): Reset mouse position when tracking starts.
			start_coordinates (tuple): The x- and y- coordinates the cursor
				should be reset to.
			start_unit (str): The unit used to define the start coordinates. 
				By default ("grid"), it corresponds to the form grid units, and
				the mouse cursor is reset to the left upper corner of the
				specified grid position (if a float is given, linear
				interpolation is performed). An alternative that also uses the
				form grid unit is "widget", whereby the mouse cursor is reset to
				the center of the widget for which starting coordinates are
				provided (if no widget has the start coordinates for this
				position, the mouse is centered on the position of the grid).
				Finally, "pixel" can be used to specify the start coordinates in
				pixel metric (in sketchpad metric).
			click_required (bool): Click required to indicate response. If False, 
				a response can be indicated just by entering the area of one 
				of the buttons with the mouse.
			mouse_buttons_allowed (list): The (physical) mouse buttons that 
				can be used to click one of the buttons.
			track_clicks (bool): Enable separate tracking of mouse clicks. 
				If True, the physical mouse button that was clicked will be 
				returned along with a corresponding timestamp as a separate 
				list.
			max_initiation_time (int): If specified, a custom warning message 
				will be displayed if no mouse movement was initiated after the 
				specified time limit (in ms).
			warning_widget (list): Custom widget that is displayed if the
				initiation time is exceeded. A list containing all the arguments
				required by the form.set_widget function.
	    
		Returns:
			resp (str): The text of the buttton that was clicked.
			resp_time (int): Response time (in ms).
			initiation_time (int): Time (in ms) until a movement was initiated.
			timestamps (list): Timestamps (in ms) for each recorded position.
			xpos (list): x-positions for each recorded position.
			ypos (list): y-positions for each recorded position.
			clicks (list): (Physical) mouse button for each mouse click. 
				Only returned if track_clicks is True.
			clicks_timestamps (list): Timestamp (in ms) for each mouse click. 
				Only returned if track_clicks is True.
	    """

        # Specify timeout settings
        if timeout != None:
            timeout = int(timeout)
            timeleft = timeout
        else:
            timeleft = logging_resolution

        # Calculate start coordinates (if mouse should be reset)
        if reset_mouse:

            # Check if start_coordinates are in allowed range
            if start_unit in ['grid', 'widget']:
                if start_coordinates[0] > len(self.cols) - 1:
                    raise osexception(
                        'start x coordinate exceeds number of colums - 1 (first column has value 0)'
                    )
                if start_coordinates[1] > len(self.rows) - 1:
                    raise osexception(
                        'start y coordinate exceeds number of rows - 1 (first row has value 0)'
                    )

            # Unit: grid
            # move mouse cursor to the left upper corner of the grid position
            # (if float is given, linear interpolation is performed)
            if start_unit == 'grid':

                start_index = self.cell_index(
                    (int(start_coordinates[0]), int(start_coordinates[1])))
                startx_mouse, starty_mouse, w, h = self.get_rect(start_index)

                # if form coordinates are provided as float, use linear interpolation
                # (as internal form function only accepts integers)
                if isinstance(start_coordinates[0], float):
                    start_index_upper = self.cell_index(
                        (int(start_coordinates[0]) + 1,
                         int(start_coordinates[1])))
                    startx_upper, y, w, h = self.get_rect(start_index_upper)
                    startx_mouse += int(
                        (startx_upper - startx_mouse) *
                        (start_coordinates[0] - int(start_coordinates[0])))

                if isinstance(start_coordinates[1], float):
                    start_index_upper = self.cell_index(
                        (int(start_coordinates[0]),
                         int(start_coordinates[1]) + 1))
                    x, starty_upper, w, h = self.get_rect(start_index_upper)
                    starty_mouse += int(
                        (starty_upper - starty_mouse) *
                        (start_coordinates[1] - int(start_coordinates[1])))

            # Unit: widget
            # move mouse cursor to the center of the widget for which starting coordinates are provided
            # (if no widget has the start coordinates for this position, mouse is centered on the position of the grid)
            elif start_unit == 'widget':
                start_index = self.cell_index(
                    (int(start_coordinates[0]), int(start_coordinates[1])))
                startx_mouse, starty_mouse, w, h = self.get_rect(start_index)
                startx_mouse += w / 2
                starty_mouse += h / 2

            # Unit: pixel
            # move mouse cursor to the position specified in pixel
            elif start_unit == 'pixel':
                startx_mouse = start_coordinates[0]
                starty_mouse = start_coordinates[1]

            else:
                raise osexception(
                    'start_unit should be one of the following: grid, widget, pixel'
                )

            # Convert pixel values to integers
            startx_mouse = int(startx_mouse)
            starty_mouse = int(starty_mouse)

        # Render form
        self.render()

        # Initialize mouse
        self.mouse = mouse(self.experiment, visible=True)

        # Initialize clock
        self.clock = self.experiment._clock

        # Reset mouse (if specified)
        if reset_mouse:

            # Set mouse position
            self.mouse.set_pos((startx_mouse, starty_mouse))

            # Set up variables including their first values
            timestamps = [self.clock.time()]
            xpos = [startx_mouse]
            ypos = [starty_mouse]

        # Get mouse position otherwise
        else:

            # Get mouse position
            position, timestamp = self.mouse.get_pos()

            # Set up variables including their first values
            timestamps = [timestamp]
            xpos = [position[0]]
            ypos = [position[1]]

        # Show mouse
        self.mouse.show_cursor(show=True)

        # Set tracking variables
        tracking = True
        mouse_on_start = True
        warning_printed = False
        resp = None
        initiation_time = None

        if track_clicks:
            clicks = []
            clicks_timestamps = []

        # Start tracking
        while tracking and timeleft > 0:

            # Collect mouse response
            if timeout == None:
                # (timeout corresponds to interval with which mouse coordinates are recored)
                mouse_button, xy, time = self.mouse.get_click(
                    buttonlist=None, timeout=logging_resolution)
            else:
                # (timeout corresponds to interval with which mouse coordinates are recored,
                #  or time left - whatever is smaller)
                mouse_button, xy, time = self.mouse.get_click(
                    buttonlist=None,
                    timeout=min([logging_resolution, timeleft]))

            # Retrieve and save mouse coordinates and timestamp using get_pos if there was no click
            # (as get_click returns None for xy if there was no mouse click)
            if xy != None:
                position = xy
                timestamp = time
            else:
                position, timestamp = self.mouse.get_pos()

            # Append values
            timestamps.append(timestamp)
            xpos.append(position[0])
            ypos.append(position[1])

            # Check if mouse has left the starting position, and, if so, determine initiation time
            if mouse_on_start == True:
                mouse_on_start = (position[0] == xpos[0]) and (position[1]
                                                               == ypos[0])
                if mouse_on_start == False:
                    # difference between last (not current) timestamp and timestamp at start
                    initiation_time = timestamps[-2] - timestamps[0]

            # If mouse is still on starting position and initiation time is exceeded, show warning
            if max_initiation_time != None:
                if mouse_on_start == True and warning_printed == False:
                    if (timestamp - timestamps[0]) > max_initiation_time:
                        self.set_widget(warning_widget[0],
                                        warning_widget[1],
                                        colspan=warning_widget[2],
                                        rowspan=warning_widget[3])
                        self.render()
                        warning_printed = True

            # If mouse clicks should be recorded, save them
            if track_clicks:
                if mouse_button != None:
                    clicks.append(mouse_button)
                    clicks_timestamps.append(timestamp)

            # If there was a mouse click, determine the button that was clicked
            # and if click was on a button, end tracking and finish form
            # (or check if mouse has "touched" a button even though there was no mouse click -  if no mouse click was required)
            if click_required == False or mouse_button in mouse_buttons_allowed:

                pos = self.xy_to_index(position)

                if pos != None:
                    w = self.widgets[pos]
                    if w != None:
                        resp = self.widgets[pos].on_mouse_click(xy)
                        if resp != None:
                            tracking = False

            # Update timeleft
            if timeout != None:
                timeleft = timeout - (timestamp - timestamps[0])

        # Calculate response time
        resp_time = timestamps[-1] - timestamps[0]

        # Set form_response variable
        self.experiment.var.form_response = resp

        if track_clicks == False:
            return resp, resp_time, initiation_time, timestamps, xpos, ypos
        else:
            return resp, resp_time, initiation_time, timestamps, xpos, ypos, clicks, clicks_timestamps