def set_rect(self, rect): """ desc: Sets the widget geometry. arguments: rect: desc: A (left, top, width, height) tuple. type: tuple """ self.rect = rect _path = safe_str(self.path, enc=misc.filesystem_encoding()) if not os.path.isfile(_path): raise osexception(u'"%s" does not exist' % _path) if self.adjust: x, y, w, h = self.rect try: img = Image.open(_path) img_w, img_h = img.size except: try: import pygame img = pygame.image.load(_path) except: raise osexception( u'Failed to open image "%s". Perhaps the file is not an image, or the image format is not supported.' \ % self.path) img_w, img_h = img.get_size() scale_x = 1.*w/img_w scale_y = 1.*h/img_h self.scale = min(scale_x, scale_y) else: self.scale = 1
def image(self, fname, center=True, x=None, y=None, scale=None): _fname = safe_str(fname, enc=misc.filesystem_encoding()) if not os.path.isfile(_fname): raise osexception(u'"%s" does not exist' % fname) try: surface = pygame.image.load(_fname) except pygame.error: raise osexception(u"'%s' is not a supported image format" % fname) if scale is not None: try: surface = pygame.transform.smoothscale( surface, (int(surface.get_width() * scale), int(surface.get_height() * scale)) ) except: debug.msg(u"smooth scaling failed for '%s'" % fname, reason=u"warning") surface = pygame.transform.scale( surface, (int(surface.get_width() * scale), int(surface.get_height() * scale)) ) size = surface.get_size() x, y = self.to_xy(x, y) if center: x -= size[0] / 2 y -= size[1] / 2 self.surface.blit(surface, (x, y))
def from_string(self, string): """ desc: Parses a definition string. arguments: string: A definition string. """ self.variables = {} self.comments = [] self.reset() for line in string.split(u'\n'): if not self.parse_variable(line): l = self.split(line) if len(l) > 0: if l[0] == u'draw': if len(l) == 1: raise osexception( u'Incomplete draw command: \'%s\'' % line) element_type = l[1] if not hasattr(self.element_module(), element_type): raise osexception( u'Unknown sketchpad element: \'%s\'' \ % element_type) element_class = getattr(self.element_module(), element_type) element = element_class(self, line) self.elements.append(element) self.elements.sort(key=lambda element: -element.z_index)
def set_widget(self, widget, pos, colspan=1, rowspan=1): """<DOC> Adds a widget to the form. Arguments: widget -- The widget to add. pos -- The position to add the widget, which can be an index or a (column, row) tuple. Keyword arguments: colspan -- The number of columns that the widget should span (default=1). rowspan -- The number of rows that the widget should span (default=1). </DOC>""" index = self.cell_index(pos) if index >= len(self.widgets): raise osexception( \ u'Widget position (%s, %s) is outside of the form' % pos) if type(colspan) != int or colspan < 1 or colspan > len(self.cols): raise osexception( \ u'Column span %s is invalid (i.e. too large, too small, or not a number)' \ % colspan) if type(rowspan) != int or rowspan < 1 or rowspan > len(self.rows): raise osexception( \ u'Row span %s is invalid (i.e. too large, too small, or not a number)' \ % rowspan) self.widgets[index] = widget self.span[index] = colspan, rowspan widget.set_rect(self.get_rect(index))
def synth(experiment, osc="sine", freq=440, length=100, attack=0, decay=5): """ desc: | A factory that synthesizes a sound and returns it as a `sampler object`. For a full description of keywords, see `python_workspace_api.synth`. For backwards compatibility, this function behaves as though it is a back-end. arguments: experiment: desc: The experiment object. type: experiment returns: desc: A `sampler` object. type: sampler """ if np is None: raise osexception( u'The synth is not available, because numpy is missing.') if attack < 0 or attack > length: raise osexception( u'Attack must be a numeric value between 0 and the sound length') if decay < 0 or decay > length: raise osexception( u'Decay must be a numeric value between 0 and the sound length') # We need to multiply the rate by two to get a stereo signal rate = 2*experiment.var.get(u'sampler_frequency', 48100) signal = osc_gen(osc, key_to_freq(freq), length, rate) _envelope = envelope(length, attack, decay, rate) sound = to_int_16(signal * _envelope) return sampler(experiment, sound)
def _color(color): """ desc: Creates a PyGame color object. returns: A pygame color object. """ if isinstance(color, unicode): return pygame.Color(str(color)) if isinstance(color, str): return pygame.Color(color) if isinstance(color, int): return pygame.Color(color, color, color, 255) if isinstance(color, float): i = int(255 * color) return pygame.Color(i, i, i, 255) if isinstance(color, tuple): if len(color) == 3: return pygame.Color(color[0], color[1], color[2], 255) if len(color) > 3: return pygame.Color(color[0], color[1], color[2], color[3]) raise osexception(u'Unknown color: %s' % color) if isinstance(color, pygame.Color): return color raise osexception(u'Unknown color: %s' % color)
def prepare(self): """ desc: Executes the prepare script. The code that you enter in the 'prepare' tab of an inline_script item in the GUI is used as a body for this function. """ item.item.prepare(self) # 'self' must always be registered, otherwise we get confusions between # the various inline_script items. self.experiment.python_workspace[u'self'] = self # Compile prepare script try: self.cprepare = self.experiment.python_workspace._compile( self.var.get(u'_prepare', _eval=False)) except Exception as e: raise osexception(u'Failed to compile inline script', line_offset=-1, item=self.name, phase=u'prepare', exception=e) # Compile run script try: self.crun = self.experiment.python_workspace._compile( self.var.get(u'_run', _eval=False)) except Exception as e: raise osexception(u'Failed to compile inline script', line_offset=-1, item=self.name, phase=u'run', exception=e) # Run prepare script try: self.experiment.python_workspace._exec(self.cprepare) except Exception as e: raise osexception(u'Error while executing inline script', line_offset=-1, item=self.name, phase=u'prepare', exception=e)
def process_user_input_customized(self, event=None): """ Allows the user to insert custom code. Code is stored in the event_handler variable. Arguments: event -- a tuple containing the type of event (key or mouse button press) and the value of the key or mouse button pressed (which character or mouse button) """ # Listen for escape presses and collect keyboard and mouse presses if no event has been passed to the function # If only one button press or mouse press is in the event que, the resulting event variable will just be a tuple # Otherwise the collected event tuples will be put in a list, which the user can iterate through with his custom code # This way the user will have either # 1. a single tuple with the data of the event (either collected here from the event que or passed from process_user_input) # 2. a list of tuples containing all key and mouse presses that have been pulled from the event queue if event is None: events = pygame.event.get() event = [] # List to contain collected info on key and mouse presses for ev in events: if ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE: self.main_player.playing = False raise osexception(u"The escape key was pressed") elif ev.type == pygame.KEYDOWN or ev.type == pygame.MOUSEBUTTONDOWN: # Exit on ESC press if ev.type == pygame.KEYDOWN: event.append(("key", pygame.key.name(ev.key))) elif ev.type == pygame.MOUSEBUTTONDOWN: event.append(("mouse", ev.button)) # If there is only one tuple in the list of collected events, take it out of the list if len(event) == 1: event = event[0] continue_playback = True # Variables for user to use in custom script try: self.main_player.python_workspace['continue_playback'] = True self.main_player.python_workspace['frame'] = self.main_player.frame_no self.main_player.python_workspace['times_played'] = self.main_player.times_played self.main_player.python_workspace['paused'] = self.main_player.paused self.main_player.python_workspace['event'] = event except Exception as e: raise osexception("Error assigning variables in media_player: {}".format(e)) # Add more convenience functions? try: self.main_player.python_workspace._exec(self.custom_event_code) except Exception as e: self.main_player.playing = False raise osexception(u"Error while executing event handling code: %s" % e) # Get potentially altered value of continue_playback from the workspace continue_playback = self.main_player.python_workspace['continue_playback'] if type(continue_playback) != bool: continue_playback = False pygame.event.pump() return continue_playback
def _prepare_allowed_responses(self): """ desc: Processes the allowed_responses variable, and checks whether it is valid. returns: desc: A list of allowed responses. type: list """ allowed_responses = safe_decode( self.var.get(u'allowed_responses', default=u'')) if allowed_responses == u'': return if py3: allowed_responses = [r.strip() \ for r in allowed_responses.split(';')] else: allowed_responses = [safe_decode(r.strip()) \ for r in safe_encode(allowed_responses).split(';')] for r in allowed_responses: if not self.validate_response(r): raise osexception(u'Invalid value in allowed_responses: %s' % r) # If allowed responses are provided, the list should not be empty if not allowed_responses: raise osexception(u'allowed_responses should not be an empty list') return allowed_responses
def prepare(self): """The preparation phase of the plug-in.""" item.item.prepare(self) try: if self.get(u"jitter_mode") == u"Uniform": self._duration = int(self.get(u"duration") + \ random.uniform(0, self.get(u"jitter")) - \ self.get(u"jitter")*0.5) elif self.get(u"jitter_mode") == u"Std. Dev.": self._duration = int(self.get(u"duration") + \ random.gauss(0, self.get(u"jitter"))) else: raise osexception( \ u'Unknown jitter mode in advanced_delay %s' % self.name) except: raise osexception( \ u"Invalid duration and/ or jitter in advanced_delay '%s'" % \ self.name) if self._duration < 0: self._duration = 0 self.experiment.set(u"delay_%s" % self.name, self._duration) debug.msg(u"delay for %s ms" % self._duration)
def __init__(self, experiment, src): """<DOC> Initializes the sampler with a specified file. Arguments: experiment -- An instance of libopensesame.experiment.experiment. src -- A path to a .wav or .ogg file. Example: >>> from openexp.sampler import sampler >>> src = exp.get_file('my_sound.ogg') >>> my_sampler = sampler(exp, src) </DOC>""" if src != None: if not os.path.exists(src): raise osexception(u"openexp._sampler.legacy.__init__() the file '%s' does not exist" % src) if os.path.splitext(src)[1].lower() not in (".ogg", ".wav"): raise osexception(u"openexp._sampler.legacy.__init__() the file '%s' is not an .ogg or .wav file" % src) self.sound = mixer.Sound(src) self.experiment = experiment self.keyboard = keyboard(experiment) self._stop_after = 0 self._fade_in = 0 self._volume = 1.0
def prepare(self): """Prepare for the run phase""" item.item.prepare(self) # Prepare the form try: cols = [float(i) for i in unicode(self.cols).split(';')] rows = [float(i) for i in unicode(self.rows).split(';')] margins = [float(i) for i in unicode(self.margins).split(';')] except: raise osexception( \ _('cols, rows, and margins should be numeric values separated by a semi-colon')) self._form = widgets.form(self.experiment, cols=cols, rows=rows, \ margins=margins, spacing=self.spacing, theme=self.theme, item=self) # Prepare the widgets for _w in self._widgets: # Evaluate all keyword arguments w = {} for var, val in _w.iteritems(): w[var] = self.eval_text(val) _type = w['type'] col = w['col'] row = w['row'] colspan = w['colspan'] rowspan = w['rowspan'] del w['type'] del w['col'] del w['row'] del w['colspan'] del w['rowspan'] # Translate paths into full file names if 'path' in w: w['path'] = self.experiment.get_file(w['path']) # Process focus keyword if 'focus' in w: focus = True del w['focus'] else: focus = False # Create the widget and add it to the form try: _w = eval('widgets.%s(self._form, **w)' % _type) except Exception as e: raise osexception( \ 'Failed to create widget "%s": %s' % (_type, e)) self._form.set_widget(_w, (col, row), colspan=colspan, \ rowspan=rowspan) # Add as focus widget if focus: self.focus_widget = _w return True
def prepare(self): """Prepares for playback.""" item.item.prepare(self) if safe_decode(self.var.sample).strip() == u'': raise osexception( u'No sample has been specified in sampler "%s"' % self.name) sample = self.experiment.get_file(self.var.sample) if debug.enabled: self.sampler = openexp.sampler.sampler(self.experiment, sample) else: try: self.sampler = openexp.sampler.sampler(self.experiment, sample) except Exception as e: raise osexception( u'Failed to load sample in sampler "%s": %s' % (self.name, \ e)) pan = self.var.pan if pan == -20: pan = u'left' elif pan == 20: pan = u'right' self.sampler.pan = pan self.sampler.volume = self.var.volume self.sampler.pitch = self.var.pitch self.sampler.fade_in = self.var.fade_in self.sampler.duration = self.var.stop_after self.sampler.block = self.block generic_response.generic_response.prepare(self)
def prepare(self): """See item.""" base_response_item.prepare(self) if safe_decode(self.var.sample).strip() == u'': raise osexception( u'No sample has been specified in sampler "%s"' % self.name) sample = self.experiment.pool[self.var.sample] try: self.sampler = openexp_sampler(self.experiment, sample) except Exception as e: raise osexception(u'Failed to load sample: %s' % sample, exception=e) pan = self.var.pan if pan == -20: pan = u'left' elif pan == 20: pan = u'right' self.sampler.pan = pan self.sampler.volume = self.var.volume self.sampler.pitch = self.var.pitch self.sampler.fade_in = self.var.fade_in self.sampler.duration = self.var.stop_after self.sampler.block = self.var.duration == u'sound'
def validate_geometry(self): """ Checks whether the form has a valid geometry. Exceptions: osexception -- When the geometry is invalid. """ for index1 in range(len(self.widgets)): if self.widgets[index1] is None: continue l = self.get_cell(index1) colspan, rowspan = self.span[index1] for col in range(l[0], l[0]+colspan): for row in range(l[1], l[1]+rowspan): index2 = self.cell_index((col, row)) if index1 == index2: continue if len(self.widgets) <= index2: raise osexception( u'The widget at position (%d, %s) falls outside of your form' \ % (l[0], l[1])) if self.widgets[index2] is not None: raise osexception( u'The widget at position (%d, %d) overlaps with another widget' \ % (l[0], l[1]))
def prepare(self): """Prepares for playback.""" item.item.prepare(self) if self.sample.strip() == u'': raise osexception( \ u'No sample has been specified in sampler "%s"' % self.name) sample = self.experiment.get_file(self.eval_text(self.sample)) if debug.enabled: self.sampler = openexp.sampler.sampler(self.experiment, sample) else: try: self.sampler = openexp.sampler.sampler(self.experiment, sample) except Exception as e: raise osexception( \ u'Failed to load sample in sampler "%s": %s' % (self.name, \ e)) pan = self.get(u'pan') if pan == -20: pan = u'left' elif pan == 20: pan = u'right' self.sampler.pan(pan) self.sampler.volume(self.get(u'volume')) self.sampler.pitch(self.get(u'pitch')) self.sampler.fade_in(self.get(u'fade_in')) self.sampler.stop_after(self.get(u'stop_after')) generic_response.generic_response.prepare(self)
def from_string(self, string): """ desc: Parses a definition string. arguments: string: A definition string. """ self.variables = {} self.comments = [] self.reset() if string is None: return for line in string.split(u'\n'): if self.parse_variable(line): continue cmd, arglist, kwdict = self.syntax.parse_cmd(line) if cmd != u'draw': continue if len(arglist) == 0: raise osexception(u'Incomplete draw command: \'%s\'' % line) element_type = arglist[0] if not hasattr(self.element_module(), element_type): raise osexception( u'Unknown sketchpad element: \'%s\'' % element_type) element_class = getattr(self.element_module(), element_type) element = element_class(self, line) self.elements.append(element) self.elements.sort(key=lambda element: -element.z_index)
def prepare(self): """ Prepare the item. In this case this means drawing a fixation dot to an offline canvas. """ # Pass the word on to the parent item.item.prepare(self) if self.module == None: try: self.module = imp.load_source("file", os.path.join( \ self.experiment.pool_folder, self.file)) except Exception as e: raise osexception( \ "Failed to import '%s' in the prepare phase of external_script item '%s': %s" \ % (self.file, self.name, e)) try: getattr(self.module, self.prepare_func)(self) except Exception as e: raise osexception( \ "Failed to run function '%s(item)' in the prepare phase of external_script item '%s': %s" \ % (self.prepare_func, self.name, e)) # Report success return True
def key_to_freq(self, key): """<DOC> Converts a key (e.g., A1) to a frequency. Arguments: key -- A string like "A1", "eb2", etc. Returns: An integer value containing the frequency in hertz. Example: >>> from openexp.synth import synth >>> my_synth = synth(exp) >>> print('An a2 is %d Hz' % my_synth.key_to_freq('a2')) </DOC>""" if type(key) != str or len(key) < 2: raise osexception( \ "synth.key_to_freq(): '%s' is not a valid note, expecting something like 'A1'") n = key[:-1].lower() try: o = int(key[-1]) except: raise osexception( \ "synth.key_to_freq(): '%s' is not a valid note, expecting something like 'A1'") if n == "a": f = 440.0 elif n == "a#" or n == "bb": f = 466.16 elif n == "b": f = 493.92 elif n == "c": f = 523.28 elif n == "c#" or n == "db": f = 554.40 elif n == "d": f = 587.36 elif n == "d#" or n == "eb": f = 698.47 elif n == "e": f = 659.48 elif n == "f": f = 698.48 elif n == "f#" or n == "gb": f = 740.00 elif n == "g": f = 784.00 elif n == "ab" or n == "g#": f == 830.64 if o < 1: o = 0.5 ** (abs(o) + 1) freq = f * o else: freq = f ** o return freq
def set_response(self, response=None, response_time=None, correct=None): """<DOC> Processes a response in such a way that feedback variables are updated # as well. Keyword arguments: response -- The response value. (default=None) response_time -- The response time. (default=None) correct -- The correctness value. (default=None) Example: >>> from openexp.keyboard import keyboard >>> my_keyboard = keyboard(exp) >>> t1 = self.time() >>> button, timestamp = my_keyboard.get_key() >>> if button == 'left': >>> correct = 1 >>> else: >>> correct = 0 >>> rt = timestamp - t1 >>> self.set_response(response=button, response_time=rt, \ >>> correct=correct) </DOC>""" # Handle response variables. self.experiment.set(u'total_responses', self.experiment.get( \ u'total_responses') + 1) self.experiment.set(u'response', response) self.experiment.set(u'response_time', response_time) if response_time != None: if type(response_time) not in (int, float): raise osexception(u'response should be a numeric value or None') self.experiment.set(u'total_response_time', self.experiment.get( \ u'total_response_time') + self.get(u'response_time')) if correct != None: if correct not in (0, 1, True, False, None): raise osexception( \ u'correct should be 0, 1, True, False, or None') if correct: self.experiment.set(u'total_correct', self.experiment.get( \ u'total_correct') + 1) self.experiment.set(u'correct', 1) else: self.experiment.set(u'correct', 0) # Set feedback variables self.experiment.set(u'acc', 100.0 * self.experiment.get( \ u'total_correct') / self.experiment.get(u'total_responses')) self.experiment.set(u'avg_rt', self.experiment.get( \ u'total_response_time') / self.experiment.get(u'total_responses')) self.experiment.set(u'accuracy', self.experiment.get(u'acc')) self.experiment.set(u'average_response_time', self.experiment.get( \ u'avg_rt')) # Copy the response variables to variables with a name suffix. self.experiment.set(u'correct_%s' % self.get(u'name'), \ self.experiment.get(u'correct')) self.experiment.set(u'response_%s' % self.get(u'name'), \ self.experiment.get(u'response')) self.experiment.set(u'response_time_%s' % self.get(u'name'), \ self.experiment.get(u'response_time'))
def prepare(self): """The preparation phase of the plug-in.""" item.item.prepare(self) # Sanity check on the duration value, which should be a positive numeric # value. if type(self.get('duration')) not in (int, float) or \ self.get('duration') < 0: raise osexception( \ u'Duration should be a positive numeric value in advanced_delay %s' \ % self.name) if self.get(u'jitter_mode') == u'Uniform': self._duration = random.uniform(self.get(u'duration')-self.get( \ u'jitter')/2, self.get(u'duration')+self.get(u'jitter')/2) elif self.get(u'jitter_mode') == u'Std. Dev.': self._duration = random.gauss(self.get(u'duration'), self.get( \ u'jitter')) else: raise osexception( \ u'Unknown jitter mode in advanced_delay %s' % self.name) # Don't allow negative durations. if self._duration < 0: self._duration = 0 self._duration = int(self._duration) self.experiment.set(u'delay_%s' % self.name, self._duration) debug.msg(u"delay for %s ms" % self._duration)
def get_file(self, path): """<DOC> Returns the path to a file. First checks if the file is in the file pool # and then the folder of the current experiment (if any). Otherwise, # simply returns the path. Arguments: path -- The filename. Returns: The full path to the file. Example: >>> image_path = exp.get_file('my_image.png') >>> my_canvas = exp.offline_canvas() >>> my_canvas.image(image_path) </DOC>""" if not isinstance(path, basestring): raise osexception( \ u"A string should be passed to experiment.get_file(), not '%s'" \ % path) if isinstance(path, str): path = path.decode(self.encoding) if path.strip() == u'': raise osexception( \ u"An empty string was passed to experiment.get_file(). Please specify a valid filename.") if os.path.exists(os.path.join(self.pool_folder, path)): return os.path.join(self.pool_folder, path) elif self.experiment_path != None and os.path.exists(os.path.join( \ self.experiment_path, path)): return os.path.join(self.experiment_path, path) else: return path
def from_string(self, string): """ Reads the entire experiment from a string. Arguments: string -- The definition string. """ debug.msg(u"building experiment") s = iter(string.split("\n")); line = next(s, None) while line != None: get_next = True try: l = self.split(line) except ValueError as e: raise osexception( \ u"Failed to parse script. Maybe it contains illegal characters or unclosed quotes?", \ exception=e) if len(l) > 0: self.parse_variable(line) # Parse definitions if l[0] == u"define": if len(l) != 3: raise osexception( \ u'Failed to parse definition', line=line) item_type = l[1] item_name = self.sanitize(l[2]) line, def_str = self.read_definition(s) get_next = False self.parse_definition(item_type, item_name, def_str) # Advance to next line if get_next: line = next(s, None)
def float_list(l, desc, min_len=None, max_len=None): """ Converts a variable to a list of floats if possible. Arguments: a -- The variable to convert. desc -- A description to clarify the osexception. Keyword arguments: min_len -- The minimum length of the list. (default=None) max_len -- The maximum length of the list. (default=None) Raises: A osexception if the variable could not be converted. Returns: A list of floats. """ try: l = list(l) except: raise osexception( \ u'Expecting a list or compatible type not "%s" for "%s"' % (l, \ desc)) if min_len is not None and len(l) < min_len: raise osexception( \ u'Expecting a list of at least %d items for "%s"' % (min_len, desc)) if max_len is not None and len(l) > max_len: raise osexception( \ u'Expecting a list of at most %d items for "%s"' % (max_len, desc)) return l
def validate_geometry(self): """ Checks whether the form has a valid geometry. Exceptions: osexception -- When the geometry is invalid. """ for index1 in range(len(self.widgets)): if self.widgets[index1] == None: continue l = self.get_cell(index1) colspan, rowspan = self.span[index1] for col in range(l[0], l[0]+colspan): for row in range(l[1], l[1]+rowspan): index2 = self.cell_index((col, row)) if index1 == index2: continue print '%s, %s (%s)' % (col, row, index2) if len(self.widgets) <= index2: raise osexception( \ u'One or more widgets fall outside of your form') if self.widgets[index2] != None: raise osexception( \ u'Two or more widgets in your form are overlapping')
def run(self): """ Everything in this function is run in a new process, therefore all import statements are put in here. The function reroutes all output to stdin and stderr to the pipe to the main process so OpenSesame can handle all prints and errors. """ import os import sys from libopensesame import misc from libopensesame.experiment import experiment from libopensesame.exceptions import osexception # Under Windows, change the working directory to the OpenSesame folder, # so that the new process can find the main script. if os.name == u'nt': os.chdir(misc.opensesame_folder()) # Reroute output to OpenSesame main process, so everything will be # printed in the Debug window there. pipeToMainProcess = OutputChannel(self.output) sys.stdout = pipeToMainProcess sys.stderr = pipeToMainProcess # First initialize the experiment and catch any resulting Exceptions try: exp = experiment(string=self.script, pool_folder= self.pool_folder, experiment_path=self.experiment_path, fullscreen=self.fullscreen, auto_response=self.auto_response, subject_nr=self.subject_nr, logfile=self.logfile) except Exception as e: if not isinstance(e, osexception): e = osexception(u'Unexpected error', exception=e) # Communicate the exception and exit with error self.output.put(e) sys.exit(1) print(u'Starting experiment as %s' % self.name) # Run the experiment and catch any Exceptions. e_run = None exp.set_output_channel(self.output) try: exp.run() print('done!') except Exception as e_run: if not isinstance(e_run, osexception): e_run = osexception(u'Unexpected error', exception=e_run) exp.transmit_workspace() # End the experiment and catch any Exceptions. These exceptions are just # printed out and not explicitly passed on to the user, because they are # less important than the run-related exceptions. try: exp.end() except Exception as e_exp: print(u'An Exception occurred during exp.end(): %s' % e_exp) # Communicate the exception and exit with error if e_run is not None: self.output.put(e_run) sys.exit(1) # Exit with success sys.exit(0)
def prepare(self): """Prepares the text display canvas.""" # Pass the word on to the parent item.prepare(self) # Create an offline canvas self.c = openexp.canvas.canvas(self.experiment, self.get( \ u"background"), self.get(u"foreground")) self.c.set_font(self.get(u"font_family"), self.get(u"font_size")) # Make sure that the content is a unicode string that is evaluated # for variables and then split into separated lines, using either the # os-specific or the Unix-style line separator. content = self.unistr(self.get(u'content')) content = content.replace(os.linesep, u'\n') content = self.eval_text(content).split(u"\n") # Do line wrapping _content = [] for line in content: while len(line) > self.get(u"maxchar"): i = line.rfind(" ", 0, self.get(u"maxchar")) if i < 0: raise osexception( \ u"Failed to do line wrapping in text_display '%s'. Perhaps one of the words is longer than the maximum number of characters per line?" \ % self.name) _content.append(line[:i]) line = line[i+1:] _content.append(line) content = _content if self.get(u"align") != u"center": try: max_width = 0 max_height = 0 for line in content: size = self.c.text_size(line) max_width = max(max_width, size[0]) max_height = max(max_height, size[1]) except: raise osexception( \ u"Failed to use alignment '%s' in text_display '%s'. Perhaps this alignment is not supported by the back-end. Please use 'center' alignment." \ % (self.get(u"align"), self.name)) line_nr = -len(content) / 2 for line in content: if self.get(u"align") == u"center": self.c.textline(line, line_nr) elif self.get(u"align") == u"left": self.c.text(line, False, self.c.xcenter()-0.5*max_width, \ self.c.ycenter()+1.5*line_nr*max_height) else: width = self.c.text_size(line)[0] self.c.text(line, False, self.c.xcenter()+0.5*max_width-width, \ self.c.ycenter()+1.5*line_nr*max_height) line_nr += 1 generic_response.prepare(self)
def get_click(self, buttonlist=None, timeout=None, visible=None): if buttonlist == None: buttonlist = self.buttonlist if timeout == None: timeout = self.timeout if visible == None: visible = self.visible enable_escape = self.experiment.get_check('enable_escape', 'no', \ ['yes', 'no']) == 'yes' if self.cursor == None: pygame.mouse.set_visible(visible) elif visible: pygame.mouse.set_visible(False) start_time = pygame.time.get_ticks() time = start_time while True: time = pygame.time.get_ticks() # Draw a cusom cursor if necessary if self.cursor != None and visible: surface = self.experiment.last_shown_canvas.copy() surface.blit(self.cursor, pygame.mouse.get_pos()) self.experiment.surface.blit(surface, (0,0)) pygame.display.flip() # Process the input for event in pygame.event.get(): if event.type == KEYDOWN and event.key == pygame.K_ESCAPE: raise osexception( \ "The escape key was pressed.") if event.type == MOUSEBUTTONDOWN: # Check escape sequence. If the top-left and top-right # corner are clicked successively within 2000ms, the # experiment is aborted if enable_escape and event.pos[0] < 64 and event.pos[1] \ < 64: _time = pygame.time.get_ticks() while pygame.time.get_ticks() - _time < 2000: for event in pygame.event.get(): if event.type == MOUSEBUTTONDOWN: if event.pos[0] > self.experiment.get( \ 'width')-64 and event.pos[1] < 64: raise osexception( \ "The escape sequence was clicked/ tapped") if (buttonlist == None or event.button in buttonlist): if self.cursor is None: pygame.mouse.set_visible(self.visible) return event.button, event.pos, time if timeout != None and time-start_time >= timeout: break if self.cursor == None: pygame.mouse.set_visible(self.visible) return None, None, time
def run(self): """Run the item""" # Parse the option list option_list = self.var.options.split(u'\n') # split by return # Filter out empty options option_list = list(filter(lambda option: option != u'', option_list)) # option_list.pop(len(option_list)-1) # remove last (empty) option if len(option_list) == 0: raise osexception( u'You must specify at least one response option in form_multiple_choice item "%s"' \ % self.name) # Determine whether a button is shown and determine the number of rows rows = len(option_list) + 2 if self.var.advance_immediately == u'no' \ or self.var.allow_multiple == u'yes': show_button = True click_accepts = False rows += 1 else: show_button = False click_accepts = True # Determine the group for the checkboxes if self.var.allow_multiple == u'no': group = u'response_group' else: group = None # The variable in which the response is stored var = self.var.form_var # Build the form try: margins = [float(i) for i in str(self.var.margins).split(u';')] except: raise osexception( _(u'margins should be numeric values separated by a semi-colon')) if self.var.timeout == u'infinite': timeout = None else: timeout = self.var.timeout form = widgets.form(self.experiment, cols=1, rows=rows, spacing=self.var.spacing, margins=margins, theme=self.var._theme, item=self, timeout=timeout, clicks=self.var.form_clicks==u'yes') form.set_widget(widgets.label(form, self.var.form_title), (0,0)) form.set_widget(widgets.label(form, self.var.question), (0,1)) i = 2 for option in option_list: form.set_widget(widgets.checkbox(form, option, group=group, click_accepts=click_accepts, var=var), (0,i)) i += 1 if show_button: form.set_widget(widgets.button(form, self.var.button_text), (0,i)) # Go! form._exec()
def prepare(self): """ desc: Prepare the item. """ item.item.prepare(self) self.prepare_timeout() self._require_state_change = self.require_state_change == u'yes' # Prepare the allowed responses self._allowed_responses = None if u'allowed_responses' in self.var: self._allowed_responses = [] for r in safe_decode(self.var.allowed_responses).split(u';'): if r.strip() != u'': try: r = int(r) except: raise osexception( u"'%s' is not a valid response in srbox '%s'. Expecting a number in the range 0 .. 5." \ % (r, self.name)) if r < 0 or r > 255: raise osexception( u"'%s' is not a valid response in srbox '%s'. Expecting a number in the range 0 .. 5." \ % (r, self.name)) self._allowed_responses.append(r) if not self._allowed_responses: self._allowed_responses = None debug.msg(u"allowed responses set to %s" % self._allowed_responses) # Prepare keyboard for dummy-mode and flushing self._keyboard = openexp.keyboard.keyboard(self.experiment) if self.var._dummy == u'yes': self._resp_func = self._keyboard.get_key return # Prepare the device string dev = self.var.dev if dev == u"autodetect": dev = None # Dynamically create an srbox instance if not hasattr(self.experiment, "srbox"): self.experiment.srbox = libsrbox.libsrbox(self.experiment, dev) self.experiment.cleanup_functions.append(self.close) self.python_workspace[u'srbox'] = self.experiment.srbox # Prepare the light byte s = "010" # Control string for i in range(5): if str(5 - i) in str(self.var.lights): s += "1" else: s += "0" self._lights = chr(int(s, 2)) debug.msg(u"lights string set to %s (%s)" % (s, self.var.lights)) # Prepare auto response if self.experiment.auto_response: self._resp_func = self.auto_responder else: self._resp_func = self.experiment.srbox.get_button_press
def _match_env(env): """ Allows for easy translation between various envelope names Arguments: env -- an envelope name Exception: Throws an osexception if an unknown envelope was specified Returns: A standard envelope name ("c", "g", "r" or "l") """ global env_synonyms if env not in env_synonyms: raise osexception(u"'%s' is not a valid envelope" % env) return env_synonyms[env]
def _activate(self): """ visible: False desc: A wrapper around [activate] to catch Exceptions. """ try: self.activate() except Exception as e: if not isinstance(e, osexception): e = osexception(msg=u'Extension error', exception=e) self.notify( u'Extension %s misbehaved on activate (see debug window for stack trace)' \ % self.name()) self.console.write(e)
def set_value(self, val): """ desc: Sets the rating scale value. arguments: val: desc: The value. type: int """ if val != None and (val >= len(self.nodes) or val < 0): raise osexception( \ u'Trying to select a non-existing node (%s). Did you specify an incorrect default value?' \ % val) self.value = val self.set_var(val)
def from_string(self, string): """See item.""" self.variables = {} self.comments = [] self.reset() if string is None: return for line in string.split(u'\n'): self.parse_variable(line) cmd, arglist, kwdict = self.experiment.syntax.parse_cmd(line) if cmd == u'log' and len(arglist) > 0: for var in arglist: if not self.experiment.syntax.valid_var_name( safe_decode(var)): raise osexception(u'Invalid variable name: %s' % var) self.logvars += arglist
def get_joyinput(self, joybuttonlist=None, timeout=None): """See _libjoystick.basejoystick""" if joybuttonlist == None or joybuttonlist == []: joybuttonlist = self._joybuttonlist if timeout == None: timeout = self.timeout pos = [] ballpos = [] hatpos = [] eventtype = None start_time = pygame.time.get_ticks() time = start_time while timeout == None or time - start_time <= timeout: time = pygame.time.get_ticks() for event in pygame.event.get(): if event.type == KEYDOWN: if event.key == pygame.K_ESCAPE: raise osexception(u"The escape key was pressed.") if event.type == JOYBUTTONDOWN: if joybuttonlist == None or event.button + 1 in \ joybuttonlist: eventtype = u'joybuttonpress' bpress = event.button + 1 return eventtype, bpress, time if event.type == JOYAXISMOTION: eventtype = u'joyaxismotion' for axis in range(self.js.get_numaxes()): pos.append(self.js.get_axis(axis)) return eventtype, pos, time if event.type == JOYBALLMOTION: eventtype = u'joyballmotion' for ball in range(self.js.get_numballs()): ballpos.append(self.js.get_ball(ball)) return eventtype, ballpos, time if event.type == JOYHATMOTION: eventtype = u'joyhatmotion' for hat in range(self.js.get_numhats()): hatpos.append(self.js.get_hat(hat)) return eventtype, hatpos, time return eventtype, None, time
def set_var(self, val, var=None): """ desc: Sets an experimental variable. arguments: val: desc: A value. type: [str, unicode] keywords: var: desc: A variable name, or `None` to use widget default. type: [str, unicode, NoneType] """ if var is None: var = self.var if var is None: return # Set the response variable l_val = [] # When this function is called via the constructor, the checkbox is not # yet part of the form. Therefore, we need to add it explicitly to the # widget list. widget_list = self.form.widgets[:] if self not in self.form.widgets: widget_list += [self] for widget in widget_list: if widget is not None and widget.type == u'checkbox' and \ widget.var == self.var: if widget.group != self.group and self.group is not None: raise osexception(_( \ u'All checkbox widgets without a group or within the same group should have the same variable.')) if widget.checked or widget.checked == u'yes': l_val.append(safe_decode(widget.text)) val = u';'.join(l_val) if val == u'': val = u'no' button.set_var(self, val, var=var)
def handle_starttag(self, tag, attrs): """ Handle an opening tag Arguments: tag -- the closing tag attrs -- the tag attributes """ if tag not in self.valid_start_tags: return if tag == u'br': self.text.append(self.paragraph) self.paragraph = [] return self.current_tag = tag if tag == u'span': style = {} for var, val in attrs: if var == u'style': var = u'font_family' elif var == u'bold': var = u'font_bold' elif var == u'italic': var = u'font_italic' elif var == u'bold': var = u'font_underline' elif var == u'size': var = u'font_size' try: val = int(val) except: raise osexception(u'Invalid font size: %s' % val) style[str(var)] = val self.push_style(**style) elif tag == u'b': self.push_style(font_bold=True) elif tag == u'i': self.push_style(font_italic=True) elif tag == u'u': self.push_style(font_underline=True) else: debug.msg(u'Unrecognized tag: %s' % tag)
def init_display(experiment): if experiment.resolution() != resolution: raise osexception( (u'The droid back-end requires a resolution of %d x %d. Your ' u'display will be scaled automatically to fit devices with ' u'different resolutions.') % resolution ) # Intialize PyGame if not pygame.display.get_init(): pygame.init() experiment.window = pygame.display.set_mode(resolution) experiment.surface = pygame.display.get_surface() # Set the time functions to use pygame experiment._time_func = pygame.time.get_ticks experiment._sleep_func = pygame.time.delay experiment.time = experiment._time_func experiment.sleep = experiment._sleep_func # Initialze the Android device if necessary if android is not None: android.init() android.map_key(android.KEYCODE_BACK, pygame.K_ESCAPE) dpi = android.get_dpi() else: # A dummy dpi if we are not on Android dpi = 96 # Log the device characteristics info = pygame.display.Info() diag = hypot(info.current_w, info.current_h) / dpi experiment.var.device_resolution_width = info.current_w experiment.var.device_resolution_height = info.current_h experiment.var.device_dpi = dpi experiment.var.device_screen_diag = diag experiment.var.device_is_tablet = u'yes' if diag >= 6 else u'no' # Start with a splash screen splash = pygame.image.load(experiment.resource('android-splash.jpg')) x = resolution[0]/2 - splash.get_width()/2 y = resolution[1]/2 - splash.get_height()/2 experiment.surface.blit(splash, (x, y)) for i in range(10): pygame.display.flip() pygame.time.delay(100) if android is not None and android.check_pause(): android.wait_for_resume()
def init_display(experiment): global _experiment, _old_gamma _experiment = experiment # Set the PsychoPy monitor, default to testMonitor monitor = experiment.var.get(u'psychopy_monitor', u'testMonitor') waitblanking = experiment.var.get(u'psychopy_waitblanking', u'yes', \ [u'yes', u'no']) == u'yes' screen = experiment.var.get(u'psychopy_screen', 0) # Print some information to the debug window print(u'openexp._canvas.psycho.init_display(): waitblanking = %s' % \ waitblanking) print(u'openexp._canvas.psycho.init_display(): monitor = %s' % monitor) print(u'openexp._canvas.psycho.init_display(): screen = %s' % screen) # Initialize the PsychoPy window and set various functions experiment.window = visual.Window(experiment.resolution(), screen=screen, waitBlanking=waitblanking, fullscr=experiment.var.fullscreen==u'yes', monitor=monitor, units=u'pix', rgb=color(experiment, experiment.var.background).backend_color, winType=u'pyglet', allowStencil=True) event.Mouse(visible=False, win=experiment.window) experiment.window.winHandle.set_caption(u'OpenSesame (PsychoPy backend)') # Set Gamma value if specified gamma = experiment.var.get(u'psychopy_gamma', u'unchanged') if type(gamma) in (int, float) and gamma > 0: _old_gamma = experiment.window.gamma experiment.window.setGamma(gamma) elif gamma != u'unchanged': raise osexception( \ u'Gamma should be a positive numeric value or "unchanged"') # Register the built-in OpenSesame fonts. for font in [u'sans', u'serif', u'mono', u'arabic', u'hebrew', u'hindi', u'chinese-japanese-korean']: font_path = experiment.resource(u'%s.ttf' % font) register_font(font_path) # Override the default quit function, so that the application is not exited core.quit = _psychopy_clean_quit # Optionally change the logging level to avoid a lot of warnings in the # debug window if experiment.var.get(u'psychopy_suppress_warnings', u'yes'): logging.console.setLevel(logging.CRITICAL)
def __getitem__(self, extension_name): """ desc: Emulates a dict interface for retrieving extensions. arguments: extension_name: desc: The extension name. type: str returns: type: base_extension """ for ext in self._extensions: if ext.name() == extension_name: return ext raise osexception(u'Extension %s does not exist' % extension_name)
def __init__(self, coroutines, _item, start_time, end_time, abort_on_end=False): """ desc: Constructor. arguments: item: desc: An item object. type: item """ if not hasattr(_item, u'coroutine'): raise osexception( u'%s not supported by coroutines' % _item.item_type) self._item = _item base_task.__init__(self, coroutines, start_time, end_time, abort_on_end) self.coroutines.event(u'initialize %s' % _item.coroutine)
def execute(self): """See base_runner.execute().""" # Exceptions during the run phase are important and returned so that the # user is notified. e = None try: self.experiment.run() except Exception as e: if not isinstance(e, osexception): e = osexception(u'Unexpected error', e) # Exceptions during the end phase are less important and only printed # to the debug window. try: self.experiment.end() except Exception as _e: debug.msg(u'Exception during experiment.end(): %s' % _e) return e
def image(self, fname, center=True, x=None, y=None, scale=None): x, y = self.to_xy(x, y) if not center: _fname = safe_decode(fname) try: surf = pygame.image.load(_fname) except pygame.error: raise osexception(u"'%s' is not a supported image format" % fname) if scale is None: x += surf.get_width() / 2 y -= surf.get_height() / 2 else: x += scale * surf.get_width() / 2 y -= scale * surf.get_height() / 2 stim = stimuli.Picture(fname, position=(x, y)) if scale is not None: stim.scale((scale, scale)) self.add_stim(stim)
def get_property(self, name, _type=str, fallback=None): """ desc: Gets an element property. arguments: name: The property name. keywords: _type: The property type. fallback: A fallback value, in case the value cannot be cast to the requested type. returns: The property in the specified type, or None if the property doesn't exist. """ properties = self.eval_properties() if name not in properties: return None val = properties[name] if _type == str: return str(val) if _type == int: try: return int(val) except ValueError: return fallback if _type == float: try: return float(val) except ValueError: return fallback if _type == bool: if isinstance(val, str): if val in (u'yes', u'1'): return True if val in (u'no', u'0'): return False return fallback return bool(val) raise osexception(u'Unknown type: %s' % _type)
def fade_in(self, ms): """<DOC> Sets the fade-in time in milliseconds. Arguments: ms -- An integer value specifying the duration in milliseconds. Example: >>> from openexp.sampler import sampler >>> src = exp.get_file('my_sound.ogg') >>> my_sampler = sampler(exp, src) >>> my_sampler.fade_in(100) </DOC>""" if type(ms) != int or ms < 0: raise osexception( \ u"openexp._sampler.legacy.fade_in() requires a positive integer") self._fade_in = ms
def get_file(self, path): """ desc: | Returns the full path to a file. The logic is as follows: 1. First checks if `path` is a file in the file pool. 2. If not, check if `path` is a file in the folder of the current experiment (if any). 3. If not, check if `path` is a file in the `__pool__` subfolder of the current experiment. 4. If not, simply return `path`. arguments: path: desc: A filename. This can be any type, but will be coerced to `unicode` if it is not `unicode`. returns: desc: The full path to the file. type: unicode example: | image_path = exp.get_file('my_image.png') my_canvas = exp.offline_canvas() my_canvas.image(image_path) """ path = self.unistr(path) if path.strip() == u'': raise osexception( u"An empty string was passed to experiment.get_file(). Please " u"specify a valid filename.") if os.path.exists(os.path.join(self.pool_folder, path)): return os.path.join(self.pool_folder, path) if self.experiment_path != None: if os.path.exists(os.path.join(self.experiment_path, path)): return os.path.join(self.experiment_path, path) if self.fallback_pool_folder != None and os.path.exists( os.path.join(self.experiment_path, self.fallback_pool_folder, path)): return os.path.join(self.experiment_path, self.fallback_pool_folder, path) return path
def get_click(self): if android is None: pygame.mouse.set_visible(self.visible) buttonlist = self.buttonlist timeout = self.timeout enable_escape = self.experiment.var.get(u'enable_escape', u'no', [u'yes', u'no']) == u'yes' start_time = pygame.time.get_ticks() time = start_time while True: time = pygame.time.get_ticks() # Process the input for event in pygame.event.get(): if event.type == KEYDOWN: if event.key == pygame.K_ESCAPE: self.experiment.pause() continue pygame.event.post(event) if event.type == MOUSEBUTTONDOWN: # Check escape sequence. If the top-left and top-right # corner are clicked successively within 2000ms, the # experiment is aborted if enable_escape and event.pos[0] < 64 and event.pos[1] \ < 64: _time = pygame.time.get_ticks() while pygame.time.get_ticks() - _time < 2000: for event in pygame.event.get(): if event.type == MOUSEBUTTONDOWN: if event.pos[0] > \ self.experiment.var.width-64 and \ event.pos[1] < 64: raise osexception( u"The escape sequence was clicked/ tapped" ) if buttonlist is None or event.button in buttonlist: return event.button, self.from_xy(event.pos), time if timeout is not None and time - start_time >= timeout: break # Allow Android interrupt if android is not None and android.check_pause(): android.wait_for_resume() return None, None, time
def prepare(self): """Prepares for playback.""" item.item.prepare(self) try: self.sampler = openexp.synth.synth(self.experiment, \ self.get(u'osc'), self.get(u'freq'), self.get(u'length'), \ self.get(u'attack'), self.get(u'decay')) except Exception as e: raise osexception( \ u"Failed to generate sound in synth '%s': %s" % (self.name, e)) pan = self.get(u'pan') if pan == -20: pan = u'left' elif pan == 20: pan = u'right' self.sampler.pan(pan) self.sampler.volume(self.get(u'volume')) generic_response.generic_response.prepare(self)
def _match_env(env): """ desc: Translation between various envelope names. arguments: env: desc: An envelope name. type: [str, unicode] returns: desc: A standard envelope name ("c", "g", "r" or "l") type: unicode """ global env_synonyms if env not in env_synonyms: raise osexception(u"'%s' is not a valid envelope" % env) return env_synonyms[env]
def _init_canvas_elements(self): """ desc: Initializes all canvas elements. """ _path = safe_str(self.path, enc=misc.filesystem_encoding()) if not os.path.exists(_path): raise osexception( u'No valid path has been specified in image widget') x, y, w, h = self.rect x += w / 2 y += h / 2 print(_path) self.canvas.add_element( ImageElement(_path, x=x, y=y, scale=self.scale, center=True).construct(self.canvas)) if self.frame: self._update_frame(self.rect)
def __init__(self, experiment, buttonlist=None, timeout=None, visible=False): self.experiment = experiment self.set_buttonlist(buttonlist) self.set_timeout(timeout) self.set_visible(visible) if self.experiment.get_check('custom_cursor', 'no') == 'yes': if self.experiment.expyriment.screen._fullscreen: raise osexception( 'The xpyriment mouse back-end does not support custom cursors in fullscreen mode (you can change this in the back-end settings)' ) self.cursor = stimuli.Picture( self.experiment.resource('cursor.png')) else: self.cursor = None
def stop_after(self, ms): """<DOC> Specifies a duration after which the sampler stops playing. Arguments: ms -- An integer value specifying the duration in milliseconds. Example: >>> from openexp.sampler import sampler >>> src = exp.get_file('my_sound.ogg') >>> my_sampler = sampler(exp, src) >>> my_sampler.stop_after(100) </DOC>""" if type(ms) != int or ms < 0: raise osexception( \ u"openexp._sampler.legacy.stop_after() requires a positive integer") self._stop_after = ms
def render(self): """ desc: Draws the widget. """ x, y, w, h = self.rect cx = x+w/2 cy = y+h/2 _h = self.form.theme_engine.box_size() if self.orientation == u'horizontal': # Some ugly maths, but basically it evenly spaces the checkboxes and # draws a frame around it. dx = (1*w-3*_h)/(len(self.nodes)-1) self.form.theme_engine.frame(x, cy-.5*_h, w, 2*_h, style=u'light') _x = x+_h i = 0 for node in self.nodes: self.form.theme_engine.box(_x, cy, checked=(self.value == i)) text_height = self.form.canvas.text_size(node)[1] self.form.canvas.text(node, center=True, x=_x+self.box_size/2, \ y=cy-text_height) self.pos_list.append( (_x, cy) ) _x += dx i += 1 elif self.orientation == u'vertical': dy = (1*h-3*_h)/(len(self.nodes)-1) self.form.theme_engine.frame(cx-.5*_h, y, 2*_h, h, style=u'light') _y = y+_h i = 0 for node in self.nodes: self.form.theme_engine.box(cx, _y, checked=(self.value == i)) text_width = self.form.canvas.text_size(node)[0] self.form.canvas.text(node, center=True, x=cx-text_width, y=_y+self.box_size/2) self.pos_list.append( (cx, _y) ) _y += dy i += 1 else: raise osexception( \ u'rating_scale orientation must be "horizontal" or "vertical", not "%s"' % \ self.orientation)
def __init__(self, form): """<DOC> Constructor. Arguments: form -- The parent form. </DOC>""" self.type = u'widget' self.form = form self.rect = None self.focus = False self.var = None # Check if the form parameter is valid if not isinstance(form, _form): raise osexception( \ u'The first parameter passed to the constructor of a form widget should be a form, not "%s"' \ % form)
def shift(self, key, mods=[u"shift"]): """ DEPRECATED This function has been deprecated as of 0.27.4. Shift is handled transparently by keyboard.get_key() Arguments: key -- A key. Keyword arguments: mods -- A list of keyboard modifiers. Exception: This function always raises an exception """ raise osexception( \ u"keyboard.shift() is deprecated")
def time(self): """ desc: Returns a timestamp for the current time. This timestamp only has a relative meaning, i.e. you can use it to determine the interval between two moments, but not the actual time. Whether the timestamp is a `float` or `int` depends on the back-end. returns: desc: A timestamp of the current time. type: [int, float] example: | print('The time is %s' % self.time()) """ # This function is set by item.prepare() raise osexception( \ u"item.time(): This function should be set by the canvas backend.")
def run(self): """<DOC> Executes the run script. The code that you enter in the 'run' tab of # an inline_script item in the GUI is used as a body for this function. </DOC>""" global _globals, _locals # 'self' must always be registered, otherwise we get confusions between # the various inline_script items. _globals[u'self'] = self if self.experiment.transparent_variables == u'yes': self.start_transparency() try: exec(self.crun, _globals) except Exception as e: raise osexception(u'Error while executing inline script', item= \ self.name, phase=u'run', exception=e) if self.experiment.transparent_variables == u'yes': self.end_transparency()
def drop_get_item_snippet(self, data): """ desc: Gets the item and list of newly created items for item-snippet drops. arguments: data: desc: The drop data. type: dict returns: desc: An (name, new_items) tuple. type: tuple """ for item_dict in data[u'items']: if not self.experiment.items.valid_type(item_dict[u'item-type']): raise osexception( _(u'Unknown item type: %s') % item_dict[u'item-type']) rename = [] new_items = [] main_item = None for item_dict in data[u'items']: item = self.experiment.items.new(item_dict[u'item-type'], item_dict[u'item-name'], item_dict[u'script'], catch_exceptions=False) if item_dict[u'item-name'] == data[u'main-item-name']: main_item = item # If the item didn't get the suggested name if item.name != item_dict[u'item-name']: rename.append((item_dict[u'item-name'], item.name)) new_items.append(item) self.extension_manager.fire(u'new_item', name=item.name, _type=item.item_type) # Inform all newly created items of any renames that occurred for old_name, new_name in rename: for item in new_items: item.rename(old_name, new_name) return main_item, [item.name for item in new_items]
def run(self): """ desc: Executes the run script. The code that you enter in the 'run' tab of an inline_script item in the GUI is used as a body for this function. """ self.set_item_onset() # 'self' must always be registered, otherwise we get confusions between # the various inline_script items. self.experiment.python_workspace[u'self'] = self try: self.experiment.python_workspace._exec(self.crun) except Exception as e: raise osexception(u'Error while executing inline script', line_offset=-1, item=self.name, phase=u'run', exception=e)
def libjoystick(experiment, **kwargs): """ A factory that returns a back-end specific joystick module. Arguments: experiment -- The experiment object. Keyword arguments: **kwargs -- A keyword-argument dictionary. """ if experiment.get(u'canvas_backend') == u'psycho': raise osexception( u'The joystick plug-in does not yet support the psycho back-end') backend = u'legacy' cls = plugins.load_cls(__file__, cls=backend, mod=backend, pkg=u'_libjoystick') return cls(experiment, **kwargs)