def MousePos(widget=None): pos = Experiment._last_instance()._app.mouse_pos_ref if widget is None: return pos else: return Ref.cond(MouseWithin(widget), Ref(map, operator.sub, pos, widget.pos), None)
def __init__(self, textstr, x=None, y=None, anchor_x='center', anchor_y='center', font_name=None, font_size=18, color=(255, 255, 255, 255), bold=False, italic=False, halign='center', width=None, height=None, multiline=False, dpi=None, group=None, parent=None, save_log=True): super(Text, self).__init__(interval=0, parent=parent, duration=0, save_log=save_log) self.textstr = textstr self.font_name = font_name self.font_size = font_size self.color = color # set loc to center if none supplied if x is None: x = Ref(self['exp']['window'], 'width') // 2 self.x = x if y is None: y = Ref(self['exp']['window'], 'height') // 2 self.y = y self.anchor_x = anchor_x self.anchor_y = anchor_y self.bold = bold self.italic = italic self.halign = halign self.width = width self.height = height self.multiline = multiline self.dpi = dpi self.group = group self.log_attrs.extend([ 'textstr', 'font_name', 'font_size', 'color', 'x', 'y', 'anchor_x', 'anchor_y', 'bold', 'italic', 'halign', 'width', 'height', 'multiline' ]) pass
def _enter(self): self._button_names = [button._name for button in self.__buttons] if self._correct_resp is None: self._correct_resp = [] elif type(self.correct_resp) not in (list, tuple): self._correct_resp = [self._correct_resp] self.__pressed_ref = Ref( lambda lst: [name for name, down in lst if down], [(button.name, button.state == "down") for button in self.__buttons]) super(ButtonPress, self)._enter()
def __init__(self): # set up the values of interest and their refs self._width = 0.0 self._width_ref = Ref.getattr(self, "_width") self._height = 0.0 self._height_ref = Ref.getattr(self, "_height") self._last_flip = event_time(0.0, 0.0) self._last_flip_ref = Ref.getattr(self, "_last_flip") self._mouse_pos = (0, 0) self._mouse_pos_ref = Ref.getattr(self, "_mouse_pos") self._mouse_button = None self._mouse_button_ref = Ref.getattr(self, "_mouse_button") self._keys_down = set() self._issued_key_refs = weakref.WeakValueDictionary()
def MousePos(widget=None): """Returns the position of the mouse. If given a widget, this function will return the position of the mouse in reference to the position of the widget. If widget is set to None, then this function will return the mouse position in relation to the experiment window. """ pos = Experiment._last_instance().screen.mouse_pos if widget is None: return pos else: return Ref.cond(MouseWithin(widget), Ref(map, operator.sub, pos, widget.pos), None)
def __init__(self, imgstr, x=None, y=None, anchor_x=None, anchor_y=None, flip_x=False, flip_y=False, rotation=0, scale=1.0, opacity=255, group=None, parent=None, save_log=True): super(Image, self).__init__(interval=0, parent=parent, duration=0, save_log=save_log) self.imgstr = imgstr self.rotation = rotation self.scale = scale self.opacity = opacity self.group = group # set loc to center if none supplied if x is None: x = Ref(self['exp']['window'], 'width') // 2 self.x = x if y is None: y = Ref(self['exp']['window'], 'height') // 2 self.y = y # eventually process for strings indicating where to anchor, # such as LEFT, BOTTOM_RIGHT, etc... self.anchor_x = anchor_x self.anchor_y = anchor_y self.flip_x = flip_x self.flip_y = flip_y # append log attrs self.log_attrs.extend([ 'imgstr', 'rotation', 'scale', 'opacity', 'x', 'y', 'flip_x', 'flip_y' ]) pass
def get_var_ref(self, name): try: return self.__issued_refs[name] except KeyError: ref = Ref.getitem(self._vars, name) self.__issued_refs[name] = ref return ref
def __getitem__(self, index): if hasattr(self, index): return Ref(self, index) else: class_name = get_class_name(self)[0] raise ValueError('%s state does not have attribute "%s".' % (class_name, index))
def _get_key_ref(self, name): try: return self._issued_key_refs[name] except KeyError: ref = Ref(self._is_key_down, name) self._issued_key_refs[name] = ref return ref
def get_var_ref(self, name): try: return self.__issued_refs[name] except KeyError: # ref = Ref.getitem(self._vars, name) ref = Ref(self.get_var, name, _parent_state=self) self.__issued_refs[name] = ref return ref
def __init__(self, movstr, x=None, y=None, anchor_x=None, anchor_y=None, rotation=0, scale=1.0, opacity=255, framerate=1 / 30., group=None, parent=None, save_log=True): super(Movie, self).__init__(interval=framerate, parent=parent, duration=-1, save_log=save_log) self.movstr = movstr self.rotation = rotation self.scale = scale self.opacity = opacity self.group = group # set loc to center if none supplied if x is None: x = Ref(self['exp']['window'], 'width') // 2 self.x = x if y is None: y = Ref(self['exp']['window'], 'height') // 2 self.y = y # eventually process for strings indicating where to anchor, # such as LEFT, BOTTOM_RIGHT, etc... self.anchor_x = anchor_x self.anchor_y = anchor_y self._player = pyglet.media.Player() self._player.eos_action = self._player.EOS_PAUSE # append log attrs self.log_attrs.extend( ['movstr', 'rotation', 'scale', 'opacity', 'x', 'y']) pass
def __init__(self, new_time=None, parent=None, save_log=True): # init the parent class super(ResetClock, self).__init__(interval=0, parent=parent, duration=0, save_log=save_log) if new_time is None: # eval to now if nothing specified new_time = Ref(gfunc=lambda:now()) self.new_time = new_time
def __init__(self, exp, fullscreen=None, size=None): super(ExpApp, self).__init__() #if size is not None: # Window.size=size #if fullscreen is not None: # Window.fullscreen = fullscreen self.exp = exp self.callbacks = {} self.pending_flip_time = None self.video_queue = [] self.keys_down = set() self.issued_key_refs = weakref.WeakValueDictionary() self.mouse_pos = (None, None) self.mouse_pos_ref = Ref.getattr(self, "mouse_pos") self.mouse_button = None self.mouse_button_ref = Ref.getattr(self, "mouse_button") self.width_ref = Ref.getattr(Window, "width") self.height_ref = Ref.getattr(Window, "height") self.__screen = Screen(self)
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 __getattr__(self, name): try: return self.__issued_refs[name] except KeyError: try: props = WidgetState.property_aliases[name] except KeyError: if name in self.__widget_param_names: props = name else: return super(WidgetState, self).__getattr__(name) if isinstance(props, str): ref = Ref(self.get_current_param, props) elif isinstance(props, tuple): ref = tuple( Ref(self.get_current_param, prop) for prop in props) else: raise RuntimeError("Bad value for 'props': %r" % props) self.__issued_refs[name] = ref return ref
def MouseButton(widget=None): """Returns a Reference to the next mouse button to be pressed. If given a widget, it will only return the mouse button pressed if it was pressed while the mouse was within the widget. If not given a widget, it will return a reference to the next button to be pressed on the mouse. """ button = Experiment._last_instance()._app.mouse_button_ref if widget is None: return button else: return Ref.cond(MouseWithin(widget), button, None)
def __init__(self, exp): super(ExpApp, self).__init__() self.exp = exp self.callbacks = {} self.pending_flip_time = None self.video_queue = [] self.keys_down = set() self.issued_key_refs = weakref.WeakValueDictionary() self.mouse_pos = (None, None) self.mouse_pos_ref = Ref.getattr(self, "mouse_pos") self.mouse_button = None self.mouse_button_ref = Ref.getattr(self, "mouse_button") self.width_ref = Ref.getattr(Window, "width") self.height_ref = Ref.getattr(Window, "height") self.last_flip = event_time(0.0, 0.0) self.last_flip_ref = Ref.getattr(self, "last_flip") self.force_blocking_flip = False self.force_nonblocking_flip = False self.__screen = Screen(self) self.flip_interval = 1/60. # default to 60 Hz
def __init__(self, vstate, duration=1.0, parent=None, save_log=True): super(Show, self).__init__(parent=parent, duration=duration, save_log=save_log) # remove vstate from parent if it exists self.claim_child(vstate) # add the wait and unshow states self._show_state = vstate self._wait_state = Wait(duration, parent=self) self._unshow_state = Unshow(vstate, parent=self) # expose the shown self.shown = vstate['shown'] # save the show and hide times self.show_time = Ref(self._show_state,'first_flip') self.unshow_time = Ref(self._unshow_state,'first_flip') # append times to log self.log_attrs.extend(['show_time','unshow_time'])
def While(condition, body=None, name="WHILE", blocking=True): if body is None: body = Serial(name="WHILE_BODY") body.override_instantiation_context() with Serial(name=name, blocking=blocking) as s: Wait(until=condition, name="WAIT_TO_START") with Parallel(name=name) as p: Wait(until=Ref.not_(condition), name="WAIT_TO_STOP") p.claim_child(body) body._blocking = False p.override_instantiation_context() s.override_instantiation_context() return body
def MousePos(widget=None): """Returns the position of the mouse. If given a widget, this function will return the position of the mouse in reference to the position of the widget. If widget is set to None, then this function will return the mouse position in relation to the experiment window. """ pos = Experiment._last_instance()._app.mouse_pos_ref if widget is None: return pos else: return Ref.cond(MouseWithin(widget), Ref(map, operator.sub, pos, widget.pos), None)
def MouseButton(widget=None): """Returns a Reference to the next mouse button to be pressed. If given a widget, it will only return the mouse button pressed if it was pressed while the mouse was within the widget. If not given a widget, it will return a reference to the next button to be pressed on the mouse. """ button = Experiment._last_instance().screen.mouse_button if widget is None: return button else: return Ref.cond(MouseWithin(widget), button, None)
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 __init__(self): self._scale_factor = 1.0 self._scale_factor_ref = Ref.getattr(self, "_scale_factor") self.scale_down = False self.scale_up = False self._scale_box = None
def MouseButton(widget=None): button = Experiment._last_instance()._app.mouse_button_ref if widget is None: return button else: return Ref.cond(MouseWithin(widget), button, None)
class ButtonPress(CallbackState): def __init__(self, buttons=None, correct_resp=None, base_time=None, duration=None, parent=None, save_log=True, name=None, blocking=True): super(ButtonPress, self).__init__(parent=parent, duration=duration, save_log=save_log, name=name, blocking=blocking) if buttons is None: self.__buttons = [] elif type(buttons) not in (list, tuple): self.__buttons = [buttons] else: self.__buttons = buttons self._button_names = None self._init_correct_resp = correct_resp self._init_base_time = None self._pressed = '' self._press_time = {"time": None, "error": None} self._correct = False self._rt = None self.__pressed_ref = None # append log vars self._log_attrs.extend([ 'button_names', 'correct_resp', 'base_time', 'pressed', 'press_time', 'correct', 'rt' ]) self.__parallel = None def _enter(self): self._button_names = [button._name for button in self.__buttons] if self._correct_resp is None: self._correct_resp = [] elif type(self.correct_resp) not in (list, tuple): self._correct_resp = [self._correct_resp] self.__pressed_ref = Ref( lambda lst: [name for name, down in lst if down], [(button.name, button.state == "down") for button in self.__buttons]) super(ButtonPress, self)._enter() def _callback(self): if self._base_time is None: self._base_time = self._start_time self._pressed = '' self._press_time = None self._correct = False self._rt = None self.__pressed_ref.add_change_callback(self.button_callback) def button_callback(self): self.claim_exceptions() pressed_list = self.__pressed_ref.eval() if not len(pressed_list): return button = pressed_list[0] self._pressed = button self._press_time = self._exp._app.event_time # calc RT if something pressed self._rt = self._press_time['time'] - self._base_time if self._pressed in self._correct_resp: self._correct = True # let's leave b/c we're all done self.cancel(self._press_time['time']) def _leave(self): self.__pressed_ref.remove_change_callback(self.button_callback) super(ButtonPress, self)._leave() def __enter__(self): if self.__parallel is not None: raise RuntimeError("ButtonPress context is not reentrant!") #!!! #TODO: make sure we're the previous state? self.__parallel = Parallel(name="BUTTONPRESS") self.__parallel.override_instantiation_context() self.__parallel.claim_child(self) self.__parallel.__enter__() return self def __exit__(self, type, value, tb): ret = self.__parallel.__exit__(type, value, tb) for child in self.__parallel._children[1:]: child._blocking = False self.__buttons.extend(iter_nested_buttons(self.__parallel)) self.__parallel = None return ret
def FreeKey(self, lbl, max_duration=10.0, max_resp=100, base_time=None): """ Perform free recall typed responses. Parameters ---------- lbl : Label state The text that will appear on the screen to indicate to the participant that they are to type a response. This text will disappear from the screen when a response is begun and return when ready for the next response. It's a good idea to use something like a label with '???????'. max_duration : {10.0, float} The amount of time in seconds that the participant is given to respond. max_resp : {100, int} Maximum number of responses that the participant is allowed to enter. base_time : float Manually set a time reference for the start of the state. This will be used to calculate reaction times. Example -------- FreeKey(Label('???????'), max_duration=15.0) The message '??????' will appear on the screen, and participants will be given 15 seconds to enter a response, replacing that text. They can enter as many responses as possible in the 15 second time period. Log Parameters --------------- All parameters above and below 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 additional logged parameters. responses : list List of typed responses, each with the following information: first_key_time, first_key_rt, enter_key_time, enter_key_rt, response, response_num. The time is the actual time, the rt is the time since the base_time. """ # I'd like the lbl to be up until the below is done. How? # is it just that I would cancel it at the end here? #lbl = Label(text=txt, font_size=40) self.claim_child(lbl) with UntilDone(): # container for responses self.responses = [] # info for each response self.fk_num_resp = 0 self.fk_first_key_time = 0 self.fk_first_key_rt = 0 self.fk_cur_resp = '' # save the starting text and base time self.fk_start_text = lbl.text # handle starting values self.max_duration = max_duration self.max_resp = max_resp # handle the base time with If(base_time): # use the passed value self.base_time = base_time with Else(): # make sure it's available #Debug(fk_on_screen=lbl.on_screen) Wait(until=lbl.on_screen) #Debug(fk_on_screen=lbl.on_screen) # use the label's appear time self.base_time = lbl.appear_time['time'] # reset timing to the desired base_time ResetClock(self.base_time) # collect responses for the desired max_duration or max_resp with Loop(): # accept a key response, time is based on label's ontime kp = KeyPress(keys=asciiplus, base_time=self.base_time) # process the key with If(kp.pressed == 'BACKSPACE'): # if there is text, remove a char with If(self.fk_cur_resp != ''): self.fk_cur_resp = self.fk_cur_resp[:-1] lbl.text = self.fk_cur_resp with Elif(kp.pressed == 'ENTER'): # if there is text, log as a response # increment the response counter self.fk_num_resp += 1 # append the response to the list self.responses += [ Ref(dict, response=self.fk_cur_resp, response_num=self.fk_num_resp, first_key_time=self.fk_first_key_time, first_key_rt=self.fk_first_key_rt, enter_key_time=kp.press_time, enter_key_rt=kp.rt) ] # set starting text back and reset text self.fk_cur_resp = '' with If(self.fk_num_resp < self.max_resp): # gonna keep going lbl.text = self.fk_start_text with Else(): # new key, so append it # if it's first key, save the time with If(self.fk_cur_resp == ''): self.fk_first_key_rt = kp.rt self.fk_first_key_time = kp.press_time # append the text with If(kp.pressed == 'SPACEBAR'): # handle the space self.fk_cur_resp += ' ' with Else(): # just append the letter self.fk_cur_resp += kp.pressed # update the label lbl.text = self.fk_cur_resp with UntilDone(): Wait(max_duration, until=(self.fk_num_resp >= max_resp)) # ran out of time, see if there is an unfinished response with If(self.fk_cur_resp != ''): # there is something, so log it, too # increment the response counter self.fk_num_resp += 1 # append the response to the list, but with no Enter key time self.responses += [ Ref(dict, response=self.fk_cur_resp, response_num=self.fk_num_resp, first_key_time=self.fk_first_key_time, first_key_rt=self.fk_first_key_rt, enter_key_time=None, enter_key_rt=None) ]
def __init__(self, tag, class_name, id, content, href, rel, referrerpolicy, target): """Initialize instance of A class with tag, class_name, id, href, rel, referrerpolicy, and target properties""" Component.__init__(self, tag, class_name, id, content) Ref.__init__(self, href, rel, referrerpolicy) self.target = target
class ButtonPress(CallbackState): def __init__(self, buttons=None, correct_resp=None, base_time=None, duration=None, parent=None, save_log=True, name=None, blocking=True): super(ButtonPress, self).__init__(parent=parent, duration=duration, save_log=save_log, name=name, blocking=blocking) if buttons is None: self.__buttons = [] elif type(buttons) not in (list, tuple): self.__buttons = [buttons] else: self.__buttons = buttons self._button_names = None self._init_correct_resp = correct_resp self._init_base_time = None self._pressed = '' self._press_time = {"time": None, "error": None} self._correct = False self._rt = None self.__pressed_ref = None # append log vars self._log_attrs.extend(['button_names', 'correct_resp', 'base_time', 'pressed', 'press_time', 'correct', 'rt']) self.__parallel = None def _enter(self): self._button_names = [button._name for button in self.__buttons] if self._correct_resp is None: self._correct_resp = [] elif type(self.correct_resp) not in (list, tuple): self._correct_resp = [self._correct_resp] self.__pressed_ref = Ref( lambda lst: [name for name, down in lst if down], [(button.name, button.state == "down") for button in self.__buttons]) super(ButtonPress, self)._enter() def _callback(self): if self._base_time is None: self._base_time = self._start_time self._pressed = '' self._press_time = None self._correct = False self._rt = None self.__pressed_ref.add_change_callback(self.button_callback) def button_callback(self): self.claim_exceptions() pressed_list = self.__pressed_ref.eval() if not len(pressed_list): return button = pressed_list[0] self._pressed = button self._press_time = self._exp._app.event_time # calc RT if something pressed self._rt = self._press_time['time'] - self._base_time if self._pressed in self._correct_resp: self._correct = True # let's leave b/c we're all done self.cancel(self._press_time['time']) def _leave(self): self.__pressed_ref.remove_change_callback(self.button_callback) super(ButtonPress, self)._leave() def __enter__(self): if self.__parallel is not None: raise RuntimeError("ButtonPress context is not reentrant!") #!!! #TODO: make sure we're the previous state? self.__parallel = Parallel(name="BUTTONPRESS") self.__parallel.override_instantiation_context() self.__parallel.claim_child(self) self.__parallel.__enter__() return self def __exit__(self, type, value, tb): ret = self.__parallel.__exit__(type, value, tb) for child in self.__parallel._children[1:]: child._blocking = False self.__buttons.extend(iter_nested_buttons(self.__parallel)) self.__parallel = None return ret
if len(pmids) <> 1: continue pmid = pmids[0].text back_refs = doc.xpath("/article/back/ref-list/ref") if len(back_refs) == 0: continue int_ext_ids = {} for ref in back_refs: int_id_tuple = ref.items()[0] ref_int_id = int_id_tuple[1] try: ref_ext_id = ref.xpath("mixed-citation/pub-id[@pub-id-type='pmid']")[0].text except IndexError: continue int_ext_ids[ref_int_id] = ref_ext_id body_refs = [Ref(ref) for ref in doc.xpath("/article/body//xref[@ref-type='bibr']")] for ref in body_refs: section_title = ref.get_section_title() section_title = section_title.replace('\t', ' ') section_title = section_title.replace('\n', ' ') if section_title.strip() == "": print(ref.get_sentence(), ref.element.getparent(), ref.element.getparent().getparent(), ref.element.getparent().getparent().getparent()) ref_id = ref.element.values()[1] try: ref_pmc_id = int_ext_ids[ref_id] except KeyError: continue par = ''.join((ref.get_text_before(),'*', ref_pmc_id, '*', ref.get_text_after())) par = par.replace('\t', ' ') par = par.replace('\n', ' ')
def __call__(self, val): # Wrap the value in a ref. scale_factor is 1.0 by default, but we are # always trying to scale a dp value, not a raw pixel value. return Ref(dp, val) * self._scale_factor_ref