def wait(self, codes=None, duration=None, no_clear_buffer=False, bitwise_comparison=False, check_for_control_keys=True): """Wait for responses defined as codes. Notes ----- If bitwise_comparision = True, the function performs a bitwise comparison (logical and) between codes and received input and waits until a certain bit pattern is set. This will also by default check for control keys (quit and pause). Thus, keyboard events will be cleared from the cue and cannot be received by a Keyboard().check() anymore! Parameters ---------- codes : int or list, optional bit pattern to wait for if codes is not set (None) the function returns for any event that differs from the baseline duration : int, optional maximal time to wait in ms no_clear_buffer : bool, optional do not clear the buffer (default = False) bitwise_comparison : bool, optional make a bitwise comparison (default = False) check_for_control_keys : bool, optional checks if control key has been pressed (default=True) Returns ------- key : int key code (or None) that quitted waiting rt : int reaction time """ start = Clock._cpu_time() rt = None if not no_clear_buffer: self.clear() while True: expyriment._active_exp._execute_wait_callback() if duration is not None: if int((Clock._cpu_time() - start) * 1000) > duration: return None, None found = self.check(codes, bitwise_comparison) if found is not None: rt = int((Clock._cpu_time() - start) * 1000) break if check_for_control_keys: if Keyboard.process_control_keys(): break if self._logging: expyriment._active_exp._event_file_log( "{0},received,{1},wait".format( self.__class__.__name__, found)) return found, rt
def wait_press(self, buttons=None, duration=None): """Wait for gamepad button press. Returns the found button and the reaction time. Parameters ---------- buttons : int or list, optional specific buttons to wait for duration : int, optional maximal time to wait in ms Returns ------- button : int button _id of the pressed button rt : int reaction time in ms """ start = get_time() rt = None _button = None self.clear() if buttons is None: buttons = range(self.get_numbuttons()) if type(buttons) is not list: buttons = [buttons] done = False while not done: expyriment._active_exp._execute_wait_callback() for button in buttons: if self.get_button(button): _button = button rt = int((get_time() - start) * 1000) done = True break if _button is not None or Keyboard.process_control_keys(): done = True break if duration: if int((get_time() - start) * 1000) >= duration: done = True break time.sleep(0.0005) if self._logging: expyriment._active_exp._event_file_log( "Gamepad,received,{0},wait_press".format(_button)) return _button, rt
def wait(self, code=None, bitwise_comparison=False): """Wait for a trigger. Returns the code received and the reaction time [code, rt]. If bitwise_comparison = True, the function performs a bitwise comparison (logical and) between code and received input and waits until a certain bit pattern is set. Parameters code -- a specific code to wait for (int) (optional) bitwise_comparison -- make a bitwise comparison (default=False) See Also -------- design.experiment.register_wait_callback_function """ if expyriment.control.defaults._skip_wait_functions: return None, None start = get_time() found = None rt = None if code is None: code = self._default_code self.interface.clear() while True: rtn_callback = expyriment._active_exp._execute_wait_callback() if isinstance(rtn_callback, expyriment.control.CallbackQuitEvent): return rtn_callback, int((get_time() - start) * 1000) read = self.interface.poll() if read is not None: if code is None: #return for every event rt = int((get_time() - start) * 1000) found = read break elif compare_codes(read, code, bitwise_comparison): rt = int((get_time() - start) * 1000) found = read break if Keyboard.process_control_keys(): break if self._logging: expyriment._active_exp._event_file_log( "TriggerInput,received,{0},wait".format(found)) return found, rt
def wait(self, code=None, bitwise_comparison=False): """Wait for a trigger. Returns the code received and the reaction time [code, rt]. If bitwise_comparison = True, the function performs a bitwise comparison (logical and) between code and received input and waits until a certain bit pattern is set. Parameters code -- a specific code to wait for (int) (optional) bitwise_comparison -- make a bitwise comparison (default=False) See Also -------- design.experiment.register_wait_callback_function """ if expyriment.control.defaults._skip_wait_functions: return None, None start = get_time() found = None rt = None if code is None: code = self._default_code self.interface.clear() while True: rtn_callback = expyriment._active_exp._execute_wait_callback() if isinstance(rtn_callback, expyriment.control.CallbackQuitEvent): return rtn_callback, int((get_time() - start) * 1000) read = self.interface.poll() if read is not None: if code is None: # return for every event rt = int((get_time() - start) * 1000) found = read break elif compare_codes(read, code, bitwise_comparison): rt = int((get_time() - start) * 1000) found = read break if Keyboard.process_control_keys(): break if self._logging: expyriment._active_exp._event_file_log("TriggerInput,received,{0},wait".format(found)) return found, rt
def wait_press(self, buttons=None, duration=None): """Wait for gamepad button press. Returns the found button and the reaction time. Parameters ---------- buttons : int or list, optional specific buttons to wait for duration : int, optional maximal time to wait in ms Returns ------- button : int button _id of the pressed button rt : int reaction time in ms See Also -------- design.experiment.register_wait_callback_function """ if expyriment.control.defaults._skip_wait_functions: return None, None start = get_time() rt = None _button = None self.clear() if buttons is None: buttons = range(self.get_numbuttons()) try: buttons = list(buttons) except: buttons = [buttons] done = False while not done: rtn_callback = expyriment._active_exp._execute_wait_callback() if isinstance(rtn_callback, expyriment.control.CallbackQuitEvent): _button = rtn_callback rt = int((get_time() - start) * 1000) done = True for button in buttons: if self.get_button(button): _button = button rt = int((get_time() - start) * 1000) done = True break if _button is not None or Keyboard.process_control_keys(): done = True break if duration: if int((get_time() - start) * 1000) >= duration: done = True break time.sleep(0.0005) if self._logging: expyriment._active_exp._event_file_log( "Gamepad,received,{0},wait_press".format(_button)) return _button, rt
def process_quit_event(click_position=None): """Check if mouse exit action has been performed If Mouse.quit_rect_location is defined (i.e. 0, 1, 2 or 3), clicking quickly three times (i.e., within 1 second) in one of the corners of the screen forces the experiment to quit. The function is called automatically by all mouse get event and wait methods (similar to Keyboard.process_control_keys). If no mouse functions are called by your program, this function can be polled to ensure quitting experiment by mouse. Mouse quit events are especially useful for experiments on devices without hardware keyboard, such as tablet PCs or smartphones. Parameters ---------- click_position : tuple of int (x,y), optional clicked location to be processed. If not defined, the Pygame event queue will be checked for mouse down events and the current position is taken Returns ------- out : bool, optional True if exit action has been performed False otherwise Notes ----- To switch on or off the detection of mouse quit events, please use the static class property `quit_rect_location' (see below). The detection of mouse quit events is activated by default under Android. Static class properties ~~~~~~~~~~~~~~~~~~~~~~~ `Mouse.quit_rect_location` = int, optional Location of the quit click action field or None. 0 = upper left corner, 1 = upper right corner (0) (1) 2 = lower right corner, 3 = lower left corner (3) (2) otherwise the detection of mouse quit events is deactivated. Default value under Android is 1, otherwise None `Mouse.quit_click_rect_size` : tuple (int, int) size of the field (rect) that detects the quit action by triple clicking in one corner of the screen. (default = (30, 30)) Changing the static class properties affects always all mouse instances. """ if Mouse.quit_rect_location not in [0,1,2,3] or \ expyriment._active_exp is None: return False if click_position is None: # check Pygame queu pos = None pygame.event.pump() screen_size = expyriment._active_exp.screen.surface.get_size() for event in pygame.event.get(pygame.MOUSEBUTTONDOWN): if event.button > 0: pos = pygame.mouse.get_pos() pos = (pos[0] - screen_size[0] / 2, -pos[1] + screen_size[1] / 2) break if pos is None: return False else: return Mouse.process_quit_event(click_position=pos) # determine threshold x & y if Mouse.quit_rect_location == 0 or Mouse.quit_rect_location == 3: # left threshold_x = -expyriment._active_exp.screen.center_x + \ Mouse.quit_click_rect_size[0] else:# right threshold_x = expyriment._active_exp.screen.center_x - \ Mouse.quit_click_rect_size[0] if Mouse.quit_rect_location == 0 or Mouse.quit_rect_location == 1: # upper threshold_y = expyriment._active_exp.screen.center_y - \ Mouse.quit_click_rect_size[1] else:# lower threshold_y = -expyriment._active_exp.screen.center_y + \ Mouse.quit_click_rect_size[1] # check if (Mouse.quit_rect_location == 0 and \ click_position[0] < threshold_x and\ click_position[1] > threshold_y) \ or (Mouse.quit_rect_location == 1 and \ click_position[0] > threshold_x and \ click_position[1] > threshold_y) \ or (Mouse.quit_rect_location == 2 and \ click_position[0] > threshold_x and \ click_position[1] < threshold_y) \ or (Mouse.quit_rect_location == 3 and \ click_position[0] < threshold_x and \ click_position[1] < threshold_y): Mouse._quit_action_events.append(get_time()) if len(Mouse._quit_action_events)>=3: diff = get_time()-Mouse._quit_action_events.pop(0) if (diff < 1): # simulate quit key simulated_key = pygame.event.Event(pygame.KEYDOWN,\ {'key': Keyboard.get_quit_key()}) return Keyboard.process_control_keys( key_event=simulated_key) return False
def wait_event(self, wait_button=True, wait_motion=True, buttons=None, duration=None, wait_for_buttonup=False): """Wait for a mouse event (i.e., motion, button press or wheel event) Parameters ---------- wait_button : bool, optional set 'False' to ignore for a button presses (default=True) wait_motion : bool, optional set 'False' to ignore for a mouse motions (default=True) buttons : int or list, optional a specific button or list of buttons to wait for duration : int, optional the maximal time to wait in ms wait_for_buttonup : bool, optional if True it waits for button-up default=False) Returns ------- event_id : int id of the event that quited waiting move : bool True if a motion occured pos : (int, int) mouse position (tuple) rt : int reaction time Notes ------ button id coding - None for no mouse button event or - 0,1,2 for left. middle and right button or - 3 for wheel up or - 4 for wheel down (wheel works only for keydown events). See Also -------- design.experiment.register_wait_callback_function """ if expyriment.control.defaults._skip_wait_functions: return None, None, None, None start = get_time() self.clear() old_pos = pygame.mouse.get_pos() btn_id = None rt = None motion_occured = False if buttons is None: buttons = [0, 1, 2, 3, 4] else: try: buttons = list(buttons) except: buttons = [buttons] while True: rtn_callback = expyriment._active_exp._execute_wait_callback() if isinstance(rtn_callback, expyriment.control.CallbackQuitEvent): btn_id = rtn_callback rt = int((get_time() - start) * 1000) break if wait_motion: motion_occured = old_pos != pygame.mouse.get_pos() if wait_button: if wait_for_buttonup: btn_id = self.get_last_button_up_event() else: btn_id = self.get_last_button_down_event() if btn_id ==-1: btn_id = None break elif btn_id in buttons or motion_occured: rt = int((get_time() - start) * 1000) break elif Keyboard.process_control_keys() or (duration is not None and \ int((get_time() - start) * 1000) >= duration): break position_in_expy_coordinates = self.position if self._logging: expyriment._active_exp._event_file_log( "Mouse,received,{0}-{1},wait_event".format(btn_id, motion_occured)) return btn_id, motion_occured, position_in_expy_coordinates, rt
def wait(self, codes=None, duration=None, no_clear_buffer=False, bitwise_comparison=False, check_for_control_keys=True): """Wait for responses defined as codes. Notes ----- If bitwise_comparision = True, the function performs a bitwise comparison (logical and) between codes and received input and waits until a certain bit pattern is set. This will also by default check for control keys (quit and pause). Thus, keyboard events will be cleared from the cue and cannot be received by a Keyboard().check() anymore! Parameters ---------- codes : int or list, optional bit pattern to wait for if codes is not set (None) the function returns for any event that differs from the baseline duration : int, optional maximal time to wait in ms no_clear_buffer : bool, optional do not clear the buffer (default = False) bitwise_comparison : bool, optional make a bitwise comparison (default = False) check_for_control_keys : bool, optional checks if control key has been pressed (default=True) Returns ------- key : int key code (or None) that quitted waiting rt : int reaction time See Also -------- design.experiment.register_wait_callback_function """ if expyriment.control.defaults._skip_wait_functions: return None, None start = get_time() rt = None if not no_clear_buffer: self.clear() while True: rtn_callback = expyriment._active_exp._execute_wait_callback() if isinstance(rtn_callback, expyriment.control.CallbackQuitEvent): found = rtn_callback rt = int((get_time() - start) * 1000) break if duration is not None: if int((get_time() - start) * 1000) > duration: return None, None found = self.check(codes, bitwise_comparison) if found is not None: rt = int((get_time() - start) * 1000) break if check_for_control_keys: if Keyboard.process_control_keys(): break if self._logging: expyriment._active_exp._event_file_log( "{0},received,{1},wait".format(self.__class__.__name__, found)) return found, rt
def wait_press(self, buttons=None, duration=None): """Wait for gamepad button press. Returns the found button and the reaction time. Parameters ---------- buttons : int or list, optional specific buttons to wait for duration : int, optional maximal time to wait in ms Returns ------- button : int button _id of the pressed button rt : int reaction time in ms See Also -------- design.experiment.register_wait_callback_function """ if expyriment.control.defaults._skip_wait_functions: return None, None start = get_time() rt = None _button = None self.clear() if buttons is None: buttons = range(self.get_numbuttons()) try: buttons = list(buttons) except: buttons = [buttons] done = False while not done: rtn_callback = expyriment._active_exp._execute_wait_callback() if isinstance(rtn_callback, expyriment.control.CallbackQuitEvent): _button = rtn_callback rt = int((get_time() - start) * 1000) done = True for button in buttons: if self.get_button(button): _button = button rt = int((get_time() - start) * 1000) done = True break if _button is not None or Keyboard.process_control_keys(): done = True break if duration: if int((get_time() - start) * 1000) >= duration: done = True break time.sleep(0.0005) if self._logging: expyriment._active_exp._event_file_log( "Gamepad,received,{0},wait_press".format(_button)) return _button, rt
def get(self, preselected_item=0): """Present the menu and return the selected item. Parameters ---------- preselected_item : int, optional item that is preselected when showing menu Returns ------- selected : int integer representing the selected item in the list """ selected = preselected_item # Keyboard if self._mouse is None: while True: self._redraw(selected) key = Keyboard().wait()[0] if key == expyriment.misc.constants.K_UP: selected -= 1 elif key == expyriment.misc.constants.K_DOWN: selected += 1 elif key in expyriment.misc.constants.K_ALL_DIGITS and\ key > expyriment.misc.constants.K_0: selected = key - expyriment.misc.constants.K_1 elif key == expyriment.misc.constants.K_RETURN: break if selected < 0: selected = 0 elif selected >= len(self._menu_items): selected = len(self._menu_items) - 1 return selected # Mouse else: pressed = None while True: pressed = None self._redraw(selected) event, pos, rt = self._mouse.wait_press() if self._scroll_menu == 0: for cnt in range(len(self._menu_items)): if 0 <= cnt < len(self._menu_items): if self._menu_items[cnt].overlapping_with_position( pos): pressed = cnt else: for cnt in range(selected - self._scroll_menu / 2, selected + 1 + self._scroll_menu / 2): if 0 <= cnt < len(self._menu_items): if self._menu_items[cnt].overlapping_with_position( pos): pressed = cnt if pressed is not None: if pressed == selected: break else: selected = pressed return self._original_items[pressed]