def _key_callback(self, symbol, modifiers, event_time): # check the key and time (if this is needed) keys = val(self.keys) correct_resp = val(self.correct_resp) sym_str = key.symbol_string(symbol) if None in keys or sym_str in keys: # it's all good!, so save it self.pressed = sym_str self.press_time = event_time # fill the base time val self.base_time = val(self.base_time_src) if self.base_time is None: # set it to the state time self.base_time = self.state_time # calc RT if something pressed self.rt = event_time['time']-self.base_time if self.pressed in correct_resp: self.correct = True # let's leave b/c we're all done #self.interval = 0 self.leave()
def _enter(self): # get the parent enter super(Wait, self)._enter() # set the duration self.duration = random.uniform(val(self.wait_duration), val(self.wait_duration)+val(self.jitter))
def _mouse_callback(self, x, y, button, modifiers, event_time): # check the mouse and time (if this is needed) buttons = val(self.buttons) correct_resp = val(self.correct_resp) button_str = mouse.buttons_string(button) if None in buttons or button_str in buttons: # it's all good!, so save it self.pressed = button_str self.press_time = event_time # fill the base time val self.base_time = val(self.base_time_src) if self.base_time is None: # set it to the state time self.base_time = self.state_time # calc RT if something pressed self.rt = event_time['time']-self.base_time if self.pressed in correct_resp: self.correct = True # let's leave b/c we're all done #self.interval = 0 self.leave()
def _callback(self, dt): if self.check: self.check = False # check the outcome each time if not self.outcome: # we should stop now #self.interval = 0 self.leave() return # process the children # start those that are not active and not done reset_next = False num_done = 0 for i,c in enumerate(self.children): if c.done: num_done += 1 # set whether we should reset the next reset_next = c.reset_next continue if not c.active: if i > 0 and \ not self.children[i-1].done and \ self.children[i-1].duration < 0: # we have to wait until it's done break # start the next one if reset_next: c.reset_clock = True c.enter() break # set whether we should reset the next reset_next = c.reset_next if num_done == len(self.children): # we're done with this sequence finished = False if not self.iterable is None: # see if we're done with the loop if self.i+1 >= len(val(self.iterable,recurse=False)): # we're really done finished = True self.leave() # reset to start if inside another loop self.i = 0 else: # dump log dump([self.get_log()],self.get_log_stream()) # set to next self.i += 1 self.current.item = val(self.iterable[self.i]) # update everything for the next loop if not finished: self._enter() pass
def _callback(self, dt): # eval the log_items and write the log keyvals = [(k,val(v)) for k,v in self.log_items.iteritems()] log = dict(keyvals) if self.log_dict: log.update(val(self.log_dict)) # log it to the correct file dump([log], self._get_stream()) pass
def _callback(self, dt): # eval the log_items and write the log keyvals = [(k, val(v)) for k, v in self.log_items.iteritems()] log = dict(keyvals) if self.log_dict: log.update(val(self.log_dict)) # log it to the correct file dump([log], self._get_stream()) pass
def _callback(self, dt): if not self.waiting: self.exp.window.mouse_callbacks.append(self._mouse_callback) self.waiting = True wait_duration = val(self.wait_duration) if ((wait_duration > 0 and now() >= self.state_time+wait_duration) or (val(self.wait_until))): # we're done self.leave()
def _update_callback(self, dt): # children must implement drawing the showable to make it shown # grab the vstate and associated shown vstate = val(self.vstate) shown = val(vstate.shown) # if something is shown, then delete it if shown: shown.delete() return shown
def _enter(self): # get the parent enter super(Loop, self)._enter() # set to current item if not self.iterable is None: self.current.item = val(self.iterable[self.i]) # reset outcome so we re-evaluate if called in loop self.outcome = val(self.cond)
def _enter(self): if _pyo_server is None: # try and init it with defaults # print some warning init_audio_server() # process the vars self.duration = val(self.dur) self._fader = pyo.Fader(fadein=val(self.fadein), fadeout=val(self.fadeout), dur=self.duration, mul=val(self.volume)) self._sine = pyo.Sine(freq=val(self.freq), mul=self._fader).out()
def _callback(self, dt): # set the exp var self.variable = val(self.var) self.value = val(self.val) if isinstance(self.variable, str): # set the experiment variable self.exp._vars[self.variable] = self.value elif isinstance(self.variable, Ref): # set the ref self.variable.set(self.value) else: raise ValueError( 'Unrecognized variable type. Must either be string or Ref')
def _update_callback(self, dt): # calc corners from x,y and width,height width = val(self.width) height = val(self.height) x1 = val(self.x) y1 = val(self.y) anchor_x = val(self.anchor_x) anchor_y = val(self.anchor_y) if anchor_x == 'center': x1 -= width//2 elif anchor_x == 'right': x1 -= width if anchor_y == 'center': y1 -= height//2 elif anchor_y == 'top': y1 -= height x2 = x1+width y2 = y1+height color = list(val(self.color)) self.shown = self.exp.window.batch.add(4, pyglet.gl.GL_QUADS, val(self.group), ('v2i', [x1, y1, x2, y1, x2, y2, x1, y2]), ('c4B', color * 4)) return self.shown
def _callback(self, dt): if not self.waiting: self.exp.window.key_callbacks.append(self._key_callback) self.waiting = True if self.base_time is None: self.base_time = val(self.base_time_src) if self.base_time is None: # set it to the state time self.base_time = self.state_time wait_duration = val(self.wait_duration) if (not wait_duration is None) and (now() >= self.base_time + wait_duration): self.leave() elif val(self.wait_until): self.leave()
def _enter(self): # get the parent enter super(Loop, self)._enter() # reset outcome so we re-evaluate if called in loop self.outcome = val(self.cond) # see if shuffle if not self.iterable is None and \ val(self.shuffle) and \ not self._shuffled: # eval and make a shallow copy self.iterable = val(self.iterable, recurse=False)[:] random.shuffle(self.iterable) self._shuffled = True
def _callback(self, dt): # set the exp var if self.eval_var: self.variable = val(self.var) else: self.variable = self.var self.value = val(self.val) if isinstance(self.variable, str): # set the experiment variable self.exp._vars[self.variable] = self.value elif isinstance(self.variable, Ref): # set the ref self.variable.set(self.value) else: raise ValueError('Unrecognized variable type. Must either be string or Ref')
def __init__(self, sound_file, start=0, stop=None, volume=.5, loop=False, duration=0, parent=None, save_log=True): # init the parent class super(SoundFile, self).__init__(interval=0, parent=parent, duration=val(duration), save_log=save_log) # save the vars self.sound_file = sound_file self.start = start self.stop = stop self.volume = volume self.duration = duration self.loop = loop self.sound_start = None # set the log attrs self.log_attrs.extend( ['sound_file', 'volume', 'start', 'stop', 'loop', 'sound_start'])
def __init__(self, duration=1.0, freq=400, fadein=.1, fadeout=.1, volume=.5, parent=None, save_log=True): # init the parent class super(Beep, self).__init__(interval=0, parent=parent, duration=val(duration), save_log=save_log) # save the vars self.dur = duration self.freq = freq self.fadein = fadein self.fadeout = fadeout self.volume = volume self.sound_start = None # set the log attrs self.log_attrs.extend( ['freq', 'volume', 'fadein', 'fadeout', 'sound_start'])
def get_log(self): """ Evaluate all the log attributes and generate a dict. """ keyvals = [(a,val(getattr(self,a))) if hasattr(self,a) else (a,None) for a in self.log_attrs] return dict(keyvals)
def transform_param(self, name, value): value = val(value) # normalize color specifier... if value is not None and "color" in name: return normalize_color_spec(value) else: return value
def _enter(self): # reset outcome so we re-evaluate if called in loop # this will evaluate each conditional, we'll enter the first one that # evaluates to True. Note that the last one is always True because it's # the Else # must evaluate each cond self.outcome = [not v is False for v in val(self.cond)] super(If, self)._enter()
def _update_callback(self, dt): # children must implement drawing the showable to make it shown self.vstate = val(self.vstate) self.shown = self.vstate.shown self.shown.delete() self.shown = None self.vstate.shown = None return self.shown
def _enter(self): if _pyo_server is None: # try and init it with defaults # print some warning init_audio_server() if self.generate_filename: self.filename = self.exp.reserve_data_filename("rec", "wav") #TODO: when state names are implemented, use state name for file title self.filepath = os.path.join(self.exp.subj_dir, val(self.filename))
def iter_i(self): self._outcome = val(self._cond) if self._iterable is None: i = 0 while self._outcome: yield i i += 1 self._outcome = val(self._cond) else: if not self._outcome: return if isinstance(self._iterable, int): count = self._iterable else: count = len(self._iterable) for i in xrange(count): yield i
def Get(variable): """Retrieve an experiment variable. Parameters ---------- variable : str Name of variable to retrieve. Can be a Reference evaluated at runtime. """ gfunc = lambda: Experiment.last_instance()._vars[val(variable)] return Ref(gfunc=gfunc)
def _enter(self): if _pyo_server is None: # try and init it with defaults # print some warning init_audio_server() # process the vars sound_file = val(self.sound_file) start = val(self.start) stop = val(self.stop) # init the sound table (two steps to get mono in both speakers) sndtab = pyo.SndTable(initchnls=_pyo_server.getNchnls()) sndtab.setSound(path=sound_file, start=start, stop=stop) # set the duration if not looping if val(self.loop): # set callback for stopping sound raise NotImplemented("Looping sounds is currently not supported.") else: self.duration = sndtab.getDur() # read in sound info self._snd = pyo.TableRead(sndtab, freq=sndtab.getRate(), loop=val(self.loop), mul=val(self.volume))
def print_traceback(self, child=None, t=None): # Use the current time, if none is provided. if t is None: t = clock.now() if self._parent is None: # If we are the root of the state tree, print the header. print " SMILE Traceback:" else: # Otherwise, let our parent print its traceback first. self._parent.print_traceback(self, t) # Get a string for the parenthesized state name, or an empty string if # the state has no custom name... if self._name is None: name_spec = "" else: name_spec = " (%s)" % self._name # Nested function to format time values as strings... def tstr(tm): if (isinstance(tm, dict) and len(tm) == 2 and "time" in tm and "error" in tm): if tm["error"] is None: error = "" else: error = ", error=%fs" % tm["error"] tm = tm["time"] else: error = "" if type(tm) not in (float, int): return repr(tm) offset = t - tm if offset < 0.0: return "%fs from now%s" % (-offset, error) else: return "%fs ago%s" % (offset, error) # Print traceback state header. print " %s%s - file: %s, line: %d" % ( type(self).__name__, name_spec, self._instantiation_filename, self._instantiation_lineno) # Print out log attributes... for attr_name in self._log_attrs: value = val(getattr(self, attr_name)) if attr_name.endswith("_time"): print " %s: %s" % (attr_name, tstr(value)) else: print " %s: %r" % (attr_name, value)
def _enter(self): # load the media self._source = pyglet.media.load(val(self.movstr)) # pop off any current sources while self._player.source: self._player.next() # queue source self._player.queue(self._source) # process enter from parent (VisualState) super(Movie, self)._enter()
def _enter(self): # process any possible refs in the provided args self.keys = val(self.keys) if not self.keys is None: if not isinstance(self.keys, list): # turn into list self.keys = [self.keys] self.keysym = [getattr(key,k) for k in self.keys] self.correct_resp = val(self.correct_resp) if not self.correct_resp is None and \ not isinstance(self.correct_resp, list): # turn into list self.correct_resp = [self.correct_resp] # set defaults self.pressed = '' self.press_time = None self.correct = False self.rt = None pass
def _callback(self, dt): if self.check: self.check = False # check the outcome each time if not self.outcome: # we should stop now #self.interval = 0 self.leave() return # process the children # start those that are not active and not done num_done = 0 for i, c in enumerate(self.children): if c.done: num_done += 1 continue if not c.active: if i > 0 and \ not self.children[i-1].done and \ self.children[i-1].duration < 0: # we have to wait until it's done break # start the next one c.enter() break if num_done == len(self.children): # we're done with this sequence finished = False if not self.iterable is None: # see if we're done with the loop if self.i + 1 >= len(val(self.iterable, recurse=False)): # we're really done finished = True self.leave() # reset to start if inside another loop self.i = 0 else: # dump log dump([self.get_log()], self.get_log_stream()) # set to next self.i += 1 # update everything for the next loop if not finished: self._enter() pass
def _callback(self, dt): # Convert code if necessary code = val(self.pulse_code) if type(code)==str: if code[0]=="S": # Use first 4 bits ncode = int(code[1:]) if ncode < 0 or ncode > 16: ncode = 15 elif code[0]=="R": # Use last 4 bits ncode = int(code[1:]) if ncode < 0 or ncode > 16: ncode = 15 ncode = ncode >> 4 else: # Convert to an integer ncode = int(code) else: ncode = int(code) # send the code if have_parallel: # Create a parallel port object (locks it exclusively) self._pport = parallel.Parallel(port=self.pulse_port) # send the port code and time it start_time = now() self._pport.setData(ncode) end_time = now() # set the pulse time time_err = (end_time - start_time)/2. self.pulse_time = event_time(start_time+time_err, time_err) # schedule the off time clock.schedule_once(self._pulse_off_callback, val(self.pulse_duration))
def _callback(self, dt): # Convert code if necessary code = val(self.pulse_code) if type(code) == str: if code[0] == "S": # Use first 4 bits ncode = int(code[1:]) if ncode < 0 or ncode > 16: ncode = 15 elif code[0] == "R": # Use last 4 bits ncode = int(code[1:]) if ncode < 0 or ncode > 16: ncode = 15 ncode = ncode >> 4 else: # Convert to an integer ncode = int(code) else: ncode = int(code) # send the code if have_parallel: # Create a parallel port object (locks it exclusively) self._pport = parallel.Parallel(port=self.pulse_port) # send the port code and time it start_time = now() self._pport.setData(ncode) end_time = now() # set the pulse time time_err = (end_time - start_time) / 2. self.pulse_time = event_time(start_time + time_err, time_err) # schedule the off time clock.schedule_once(self._pulse_off_callback, val(self.pulse_duration))
def _update_callback(self, dt): # children must implement drawing the showable to make it shown if not self.shown is None: # update with the values pass else: # make the new shown and return it self.img = pyglet.resource.image(val(self.imgstr), flip_x=val(self.flip_x), flip_y=val(self.flip_y)) self.shown = pyglet.sprite.Sprite(self.img, x=val(self.x), y=val(self.y), batch=self.exp.window.batch) self.shown.scale = val(self.scale) self.shown.rotation = val(self.rotation) self.shown.opacity = val(self.opacity) return self.shown
def _update_callback(self, dt): # calc corners from x,y and width,height width = val(self.width) height = val(self.height) x1 = val(self.x) y1 = val(self.y) anchor_x = val(self.anchor_x) anchor_y = val(self.anchor_y) if anchor_x == 'center': x1 -= width//2 elif anchor_x == 'right': x1 -= width if anchor_y == 'center': y1 -= height//2 elif anchor_y == 'top': y1 -= height x2 = x1+width y2 = y1+height # specify the dots num_dots = val(self.num_dots) dot_size = val(self.dot_size) buf = int(math.ceil(dot_size/2.)) # make list of point pairs points = [[random.randint(x1+buf,x2-buf), random.randint(y1+buf,y2-buf)] for i in xrange(num_dots)] # flatten the points into a single list points = [item for sublist in points for item in sublist] # make a list of the dot colors color = list(val(self.color)) # draw the dots self.shown = self.exp.window.batch.add(num_dots, pyglet.gl.GL_POINTS, grPointSize(dot_size), ('v2i', points), ('c4B', color*num_dots)) return self.shown
def __init__(self, duration=1.0, freq=400, fadein=.05, fadeout=.05, volume=.5, parent=None, save_log=True): # init the parent class super(Beep, self).__init__(interval=0, parent=parent, duration=val(duration), save_log=save_log) # save the vars self.dur = duration self.freq = freq self.fadein = fadein self.fadeout = fadeout self.volume = volume self.sound_start = None # set the log attrs self.log_attrs.extend(['freq', 'volume', 'fadein', 'fadeout', 'sound_start'])
def __init__(self, sound_file, start=0, stop=None, volume=.5, loop=False, duration=0, parent=None, save_log=True): # init the parent class super(SoundFile, self).__init__(interval=0, parent=parent, duration=val(duration), save_log=save_log) # save the vars self.sound_file = sound_file self.start = start self.stop = stop self.volume = volume self.duration = duration self.loop = loop self.sound_start = None # set the log attrs self.log_attrs.extend(['sound_file', 'volume', 'start', 'stop', 'loop', 'sound_start'])
def Get(variable): """Retrieve an experiment variable. Parameters ---------- variable : str Name of variable to retrieve. Can be a Reference evaluated at runtime. Example ------- with Parallel(): txt = Text('Press a key as quickly as you can!') key = KeyPress(base_time=txt['last_flip']['time']) Unshow(txt) Set('good',key['rt']<0.5) with If(Get('good')) as if_state: with if_state.true_state: Show(Text('Good job!'), duration=1.0) with if_state.false_state: Show(Text('Better luck next time.'), duration=1.0) Text will be shown on the screen, instructing the participant to press a key as quickly as they can. The participant will press a key while the text is on the screen, then the text will be removed. The 'Set' state will be used to define a variable for assessing the participant's reaction time for the key press that just occurred, and the 'Get' state accesses that new variable. If the participant's reaction time was faster than 0.5 seconds, the text 'Good job!' will appear on the screen. If the participant's reaction time was slower than 0.5 seconds, the text 'Better luck next time.' will appear on the screen. Log Parameters -------------- All parameters above are available to be accessed and manipulated within the experiment code, and will be automatically recorded in the state.yaml and state.csv files. Refer to State class docstring for addtional logged parameters. """ gfunc = lambda : Experiment.last_instance()._vars[val(variable)] return Ref(gfunc=gfunc)
def Get(variable): """Retrieve an experiment variable. Parameters ---------- variable : str Name of variable to retrieve. Can be a Reference evaluated at runtime. Example ------- with Parallel(): txt = Text('Press a key as quickly as you can!') key = KeyPress(base_time=txt['last_flip']['time']) Unshow(txt) Set('good',key['rt']<0.5) with If(Get('good')) as if_state: with if_state.true_state: Show(Text('Good job!'), duration=1.0) with if_state.false_state: Show(Text('Better luck next time.'), duration=1.0) Text will be shown on the screen, instructing the participant to press a key as quickly as they can. The participant will press a key while the text is on the screen, then the text will be removed. The 'Set' state will be used to define a variable for assessing the participant's reaction time for the key press that just occurred, and the 'Get' state accesses that new variable. If the participant's reaction time was faster than 0.5 seconds, the text 'Good job!' will appear on the screen. If the participant's reaction time was slower than 0.5 seconds, the text 'Better luck next time.' will appear on the screen. Log Parameters -------------- All parameters above are available to be accessed and manipulated within the experiment code, and will be automatically recorded in the state.yaml and state.csv files. Refer to State class docstring for addtional logged parameters. """ gfunc = lambda: Experiment.last_instance()._vars[val(variable)] return Ref(gfunc=gfunc)
def enter(self): """ Gets the starting time from the parent state """ self.state_time = self.get_parent_state_time() self.start_time = self.state_time # add the callback to the schedule delay = self.state_time - now() if delay < 0 or issubclass(self.__class__,RunOnEnter): # parents states (and states like Logging) run immediately delay = 0 if self.interval < 0: # schedule it for every event loop schedule_delayed(self.callback, delay) else: # schedule the interval (0 means once) schedule_delayed_interval(self.callback, delay, self.interval) # say we're active self.active = True # if we don't have the exp reference, get it now if self.exp is None: from experiment import Experiment self.exp = Experiment.last_instance() # compute the duration self.duration = val(self.raw_duration) # custom enter code self._enter() # update the parent time if necessary # moved to after _enter in case we update duration if self.duration > 0: self.advance_parent_state_time(self.duration) pass
def _callback(self, dt): # process the refs #kwargs = {key: val(value) for (key, value) in self.kwargs} print 'DEBUG:', val(self.kwargs)
def get_log(self): keyvals = [(a, val(getattr(self, a))) if hasattr(self, a) else (a, None) for a in self.log_attrs] return dict(keyvals)
def _update_callback(self, dt): # children must implement drawing the showable to make it shown if False: #self.shown: # update with the values pass else: # make the new shown and return it self.shown = pyglet.text.Label(val(self.textstr), font_name=val(self.font_name), font_size=val(self.font_size), color=val(self.color), x=val(self.x), y=val(self.y), anchor_x=val(self.anchor_x), anchor_y=val(self.anchor_y), bold=val(self.bold), italic=val(self.italic), halign=val(self.halign), width=val(self.width), height=val(self.height), multiline=val(self.multiline), dpi=val(self.dpi), group=val(self.group), batch=self.exp.window.batch) return self.shown
def _update_callback(self, dt): self.shown = val(self.vstate).shown setattr(self.shown, val(self.attr), val(self.value))
def _callback(self, dt): duration = val(self.new_time) - self.get_parent_state_time() if duration > 0: self.advance_parent_state_time(duration)
def _update_callback(self, dt): # children must implement drawing the showable to make it shown if not self.shown is None: # update with the values if not self._player.playing: if self.shown: self.shown.delete() self.shown = None self.leave() return None if self._player.source: img = self._player.get_texture() else: img = None if img is None: self._player.pause() if self.shown: self.shown.delete() self.shown = None self.leave() return None self.shown.image = img else: # if playing, then stopped from outside if self._player.playing: # we need to leave self._player.pause() self.leave() return None # make the new shown and return it # start the player self._player.play() # get the image img = self._player.get_texture() if img is None: self._player.pause() if self.shown: self.shown.delete() self.shown = None self.leave() return None # process the anchors anchor_x = val(self.anchor_x) if anchor_x is None: # set to center anchor_x = img.width//2 img.anchor_x = anchor_x anchor_y = val(self.anchor_y) if anchor_y is None: # set to center anchor_y = img.height//2 img.anchor_y = anchor_y self.shown = pyglet.sprite.Sprite(img, x=val(self.x), y=val(self.y), group=val(self.group), batch=self.exp.window.batch) self.shown.scale = val(self.scale) self.shown.rotation = val(self.rotation) self.shown.opacity = val(self.opacity) # update the time self.current_time = self._player.time return self.shown
def _update_callback(self, dt): # children must implement drawing the showable to make it shown if False: #not self.shown is None: # update with the values pass else: # make the new image self.img = pyglet.resource.image(val(self.imgstr), flip_x=val(self.flip_x), flip_y=val(self.flip_y)) # process the anchors anchor_x = val(self.anchor_x) if anchor_x is None: # set to center anchor_x = self.img.width//2 self.img.anchor_x = anchor_x anchor_y = val(self.anchor_y) if anchor_y is None: # set to center anchor_y = self.img.height//2 self.img.anchor_y = anchor_y # make the sprite from the image self.shown = pyglet.sprite.Sprite(self.img, x=val(self.x), y=val(self.y), group=val(self.group), batch=self.exp.window.batch) self.shown.scale = val(self.scale) self.shown.rotation = val(self.rotation) self.shown.opacity = val(self.opacity) return self.shown
def _callback(self, dt): # process the refs args = [val(a) for a in self.args] kwargs = {key: val(value) for (key, value) in self.kwargs} self.res = self.func(self, *args, **kwargs)
def _enter(self): # reset outcome so we re-evaluate if called in loop self.outcome = val(self.cond) super(If, self)._enter()
def _update_callback(self, dt): self.exp.window.set_clear_color(val(self.color))
def _enter(self): # get the parent enter super(Loop, self)._enter() # reset outcome so we re-evaluate if called in loop self.outcome = val(self.cond)
def _update_position(self): pos = val(self.__pos_ref) if None not in pos: self.__instruction.pos = [ mp - os for (mp, os) in zip(pos, self._offset) ]