class Rating(): def __init__(self, win, description, labels, rating_file): self.win = win self.rating_file = rating_file self.description = TextStim(win, text=description, height=0.05, pos=(0, 0.5), units='norm', color=(0, 0, 0), colorSpace='rgb255') if len(labels) == 7: self.rating_scale = RatingScale(win, scale=None, labels=labels, tickMarks=[1, 2, 3, 4, 5, 6, 7], pos=(0, 0), stretch=3, textSize=0.8, textColor='Black', lineColor='Black', showValue=False, showAccept=False) else: self.rating_scale = RatingScale(win, scale=None, labels=labels, pos=(0, 0), stretch=3, textSize=0.8, textColor='Black', lineColor='Black', showValue=False, showAccept=False) self.button = Button(win, (0, -0.5), width=0.1, height=0.05, name='button_rating', text='确认') def run(self): while self.button.state != self.button.END: self.description.draw() self.rating_scale.draw() self.button.process() self.button.draw() self.win.flip() def save(self): self.rating_file.write('Rating: ' + str(self.rating_scale.getRating()) + '\n') self.rating_file.write('Decision Time: ' + str(self.rating_scale.getRT()) + '\n') choice_history = self.rating_scale.getHistory() self.rating_file.write('Choice History:\n(choice\ttime)\n') for i in choice_history: self.rating_file.write(str(i[0]) + '\t' + str(i[1]) + '\n') self.rating_file.write('\n')
class ProbabilityPieChart(object): def __init__(self, window, prob, size, prefix='', pos=(0.0, 0.0), color_pos=(.65, .65, .65), color_neg=(-.65, -.65, -.65)): deg = prob * 360. self.piechart_pos = Pie(window, end=deg, fillColor=color_pos, pos=pos, size=size) self.piechart_neg = Pie(window, start=deg, end=360, fillColor=color_neg, pos=pos, size=size) txt = f'{prefix}{int(prob*100):d}%' self.text = TextStim(window, pos=(pos[0], pos[1] + size * 1.), text=txt, wrapWidth=size * 3, height=size * .75) def draw(self): self.piechart_pos.draw() self.piechart_neg.draw() self.text.draw()
def display_text(self, text, keys=None, duration=None, **kwargs): """ Displays text on the window and waits for a key response. The 'keys' and 'duration' arguments are mutually exclusive. parameters ---------- text : str Text to display keys : str or list[str] String (or list of strings) of keyname(s) to wait for kwargs : key-word args Any (set of) parameter(s) passed to TextStim """ if keys is None and duration is None: raise ValueError("Please set either 'keys' or 'duration'!") if keys is not None and duration is not None: raise ValueError("Cannot set both 'keys' and 'duration'!") stim = TextStim(self.win, text=text, **kwargs) stim.draw() self.win.flip() if keys is not None: waitKeys(keyList=keys) if duration is not None: core.wait(duration)
def EndExp(): exitPrompt = ("This concludes the session. Thank you for " "participating!\n\nPress Escape to quit") exitText = TextStim(self.window, exitPrompt, color='Black') exitText.draw(self.window) self.window.flip() waitKeys(keyList=['escape']) self.window.close()
class ImageScreen(Screen): def __init__(self, disp, text, text_width, image, image_size, text_pos=None, image_pos=None, wait_time=1, extra_image_stims=[] ): super(ImageScreen, self).__init__(disp, wait_time=wait_time) self.extra_image_stims = extra_image_stims self.wait_time = wait_time if self.wait_time == 0: self.continue_button.clickable = True if text_pos is None: _text_pos = self.coords(self.width/4, self.height/2) else: _text_pos = text_pos if image_pos is None: _image_pos = self.coords(3*self.width/4, self.height/2) else: _image_pos = image_pos self.text_stim = TextStim( win=self.window, text=text, pos=_text_pos, height=Screen.default_font_size, wrapWidth=text_width ) self.img_stim = ImageStim( win=self.window, image=image, pos=_image_pos, size=(image_size[0], image_size[1]) ) def draw(self, debug_mode=False): for img_stim in self.extra_image_stims: img_stim.draw() self.continue_button.draw() self.text_stim.draw() self.img_stim.draw() if not self.continue_button.clickable: if getAbsTime() - self.t0 > self.wait_time: self.continue_button.clickable = True def cleanup(self): for extra in self.extra_image_stims: del extra self.window.flip() self.window.flip() self.window.flip()
def whoAmI(response, done, qpos, image): """ Function that will be called to enter the user identification data - **Input**: :response: the user resonse (empty string at beginning) :done: boolean (True / False) -> False at beginning :qpos: text position for user response :image: the stimulus image - **outpu**: :response: the user response """ # --------------------------------------- # # WHILE THE WELCOME MESSAGE IS NOT PASSED # # --------------------------------------- # while len(response) == 0: # while the user has not taped anything yet response = '' # the response written by the user - On commence avec une chaîne vide respstim = TextStim(disp, text='', pos=qpos, height=size, color=color) # stimulus texte qstim = ImageStim(disp, image=image) qstim.draw() # dessiner la question disp.flip( ) # passer au screen au suivant -> on met la question par-dessus core.wait(loadTime ) # delay of 10 seconds before passing to the learning phase done = False # ----------------------------------- # # WHILE THE USER'S ANSWER IS NOT DONE # # Check for keypresses # # ----------------------------------- # while not done: # loop until done == True resplist = waitKeys(maxWait=float('inf'), keyList=None, timeStamped=True) key, presstime = resplist[ 0] # use only the first in the returned list of keypresses -> resplist[0] is the first element in the resplist list if len(key) == 1: # Check si la longeur de la réponse (len) = 1 response += key #Ajouter la lettre tapée à la réponse => on ne tient pas compte des touches pour les majuscules ni de la touche escape elif key == 'space': # Check if key is the space bar response += ' ' # ajoute un espace elif key == 'backspace' and len( response ) > 0: # Check if the key's name was backspace AND si la réponse a au moins une lettre response = response[0: -1] #remove last character of the response if key == 'return': # if the key was non of the above, check si c'est enter done = True # set done to True respstim.setText(response.capitalize( )) # actualiser la user response => 1ère lettre en majuscule qstim.draw() # réafficher la question stimulus (image) respstim.draw() # réafficher la réponse au stimulus disp.flip() # update the monitor core.wait( loadTime) # add a little lag to avoid little freez and/or bug return response.capitalize() # 1ère lettre en majuscule
def draw(self): """ Draws stimuli """ if self.phase == 0: stim = TextStim(self.session.win, 'Trial %i' % (self.trial_nr)) stim.draw() else: self.session.default_fix.draw() super().draw()
class TestTrial(Trial): """ Simple trial with text (trial x) and fixation. """ def __init__(self, session, trial_nr, phase_durations, txt=None, **kwargs): super().__init__(session, trial_nr, phase_durations, **kwargs) self.txt = TextStim(self.session.win, txt) def draw(self): """ Draws stimuli """ if self.phase == 0: self.txt.draw() else: self.session.default_fix.draw()
class CueTrial(Trial): def __init__(self, session, trial_nr, phase_durations, txt, **kwargs): super().__init__(session, trial_nr, phase_durations, **kwargs) self.txt = TextStim(self.session.win, txt, height=1, wrapWidth=300) def draw(self): if self.phase == 0: self.txt.draw() else: pass
def setup_cal_display(self): txt = TextStim( self.win, text= "Please follow the dot. Try not to anticipate its movements.", pos=(0, 100), color='black', units='pix') txt.draw() self.targetout.draw() self.win.flip()
def draw(self): """ Draws stimuli """ if self.phase == 0: if 'response' in self.log['event_type']: self.stop_phase() stim = TextStim(self.session.win, 'Trial %i' % (self.trial_nr)) stim.draw() else: self.session.default_fix.draw() super().draw()
def Pause(self): """Pauses the task, and displays a message waiting for a spacebar input from the user before continuing to proceed. """ pauseMsg = "Experiment Paused\n\nPress '{}' to continue".format( self.pauseButton) pauseText = TextStim(self.window, text=pauseMsg, color='Black', height=40) pauseText.draw(self.window) self.window.flip() waitKeys(keyList=[self.pauseButton]) clearEvents()
class GambleInstructTrial(GambleTrial): def __init__(self, session, trial_nr, txt, bottom_txt=None, show_phase=0, keys=None, **kwargs): phase_durations = np.ones(12) * 1e-6 phase_durations[show_phase] = np.inf self.keys = keys super().__init__(session, trial_nr, phase_durations=phase_durations, **kwargs) txt_height = self.session.settings['various'].get('text_height') txt_width = self.session.settings['various'].get('text_width') self.text = TextStim(session.win, txt, pos=(0.0, 6.0), height=txt_height, wrapWidth=txt_width, color=(0, 1, 0)) if bottom_txt is None: bottom_txt = "Press any button to continue" self.text2 = TextStim(session.win, bottom_txt, pos=( 0.0, -6.0), height=txt_height, wrapWidth=txt_width, color=(0, 1, 0)) def get_events(self): events = Trial.get_events(self) if self.keys is None: if events: self.stop_phase() else: for key, t in events: if key in self.keys: self.stop_phase() def draw(self): if self.phase != 0: self.session.fixation_lines.setColor((1, -1, -1)) if self.phase < 9: super().draw() else: self.session.fixation_lines.draw() if self.phase == 10: self.choice_stim.draw() elif self.phase == 11: self.certainty_stim.draw() self.text.draw() self.text2.draw()
class CertaintyStimulus(object): def __init__(self, window, response_size=(1, .5), fillColor=(1, 1, -1), *args, **kwargs): n_responses = 4 total_width = n_responses * \ response_size[0] + (n_responses - 1) * .1 * response_size[0] positions = -total_width / 2. + \ response_size[0]/2. + \ np.arange(n_responses) * 1.1 * response_size[0] positions = [(pos, 0) for pos in positions] self.rectangles = [ Rect(window, size=response_size, pos=positions[n], opacity=.5, fillColor=fillColor) for n in range(n_responses) ] self.stim_texts = [ TextStim(window, height=.45 * response_size[1], wrapWidth=.9 * response_size[0], pos=positions[n], color=(-1, -1, -1), text=n + 1) for n in range(n_responses) ] self.description_text = TextStim( window, pos=(0, 1.5 * response_size[1]), wrapWidth=response_size[0] * 8.8, text= 'How certain are you about your choice (1=very certain, 4= very uncertain)' ) def draw(self): for rect in self.rectangles: rect.draw() for txt in self.stim_texts: txt.draw() self.description_text.draw()
def ShowPromptAndWaitForSpace(self, prompt, keylist=['space', 'escape']): ''' Show the prompt on the screen and wait for space, or the keylist specified returns the key pressed ''' keylist = [self.pauseButton, 'escape'] text = TextStim(self.window, prompt, color='Black') text.draw(self.window) self.window.flip() continueKey = waitKeys(keyList=keylist) if len(continueKey) != 0 and continueKey[0] == 'escape': self.logfile.write("Terminated early.") self.logfile.close() sys.exit() return continueKey
def day2(self): day2_text = "The task for this session is similar to yesterday. " day2_text += "You will respond six additional sets of trials. " pressToContinue = TextStim(self.win, text="<press any key to continue>", pos=(0, -0.9), height=0.06, units="norm", alignHoriz="center") ready = self.makeTextStim(day2_text) ready.draw() pressToContinue.draw() win.flip() event.waitKeys()
class InstructionsScreen(Screen): def __init__(self, disp, text, font_size=40, wait_time=0): super(InstructionsScreen, self).__init__(disp, wait_time=wait_time) self.instructions_text = TextStim( disp, pos=(0,0), text=text, height=font_size, wrapWidth=self.w_cfg_2_pix(0.666) ) def draw(self, debug_mode=False): self.instructions_text.draw() def cleanup(self): self.window.flip() self.window.flip() self.window.flip()
def userResponse(response, done, qpos, image, multi): """ Function that will be called every time the user needs to press a key to pass to the next display - **Input**: :response: the user resonse (empty string at beginning) :done: boolean (True / False) -> False at beginning :qpos: text position for user response :image: the stimulus image :multi: multiple display ? integer (1, 2 or 3) """ # --------------------------------------- # # WHILE THE WELCOME MESSAGE IS NOT PASSED # # --------------------------------------- # while len(response) == 0: # while the user has not taped anything yet response = '' # the response written by the user - On commence avec une chaîne vide respstim = TextStim(disp, text='', pos=qpos, height=size) # stimulus texte qstim = ImageStim(disp, image=image) qstim.draw() # dessiner la question if multi >= 2: # at least 2 diferent stimuli qstim2.draw() if multi == 3: # 3 diferent stimuli qstim3.draw() disp.flip( ) # passer au screen au suivant -> on met la question par-dessus core.wait(loadTime ) # delay of 10 seconds before passing to the learning phase done = False # ----------------------------------- # # WHILE THE USER'S ANSWER IS NOT DONE # # Check for keypresses # # ----------------------------------- # while not done: # loop until done == True resplist = waitKeys(maxWait=float('inf'), keyList=None, timeStamped=True) key, presstime = resplist[ 0] # use only the first in the returned list of keypresses -> resplist[0] is the first element in the resplist list response += key #Ajouter la lettre tapée à la réponse done = True # set done to True qstim.draw() # réafficher la question stimulus respstim.draw() # réafficher la réponse au stimulus disp.flip() # update the monitor core.wait( loadTime) # add a little lag to avoid little freez and/or bug
def wait_for_scanner(win, keys:List[str] =["equal", "asciicircum"], msg:Optional[str]=None) -> TaskTime: """put up a message and wait for the scanner to send a trigger, return fliptime @param win - window to draw on @param keys - list of accpetaible keys, default ^ and = @param msg - message to show while waiting """ from psychopy.visual import TextStim from psychopy.event import waitKeys if not msg: msg=f'Get Ready!\nWaiting for the scanner' # previously aslo mentioned the keys we are wating for # \n{", ".join(keys)}' tx = TextStim(win, text=msg) tx.draw() win.flip() waitKeys(keyList=keys) return getTime()
class InstructionTrial(Trial): """pseudo trial to display text""" def __init__(self, mouse: Mouse, window: Window, text: str, duration: float): super().__init__(mouse, window) self.duration = duration self.instruction_text = TextStim( window, text=text, color="black", height=30, pos=(0, 0) ) def run(self): self.draw() self.window.flip() core.wait(self.duration) self.window.flip() def draw(self): self.instruction_text.draw(self.window)
class FixationPoint(object): def __init__(self, win, pos, size, color=(1,0,0)): self.screen = win self.fixation_stim1 = TextStim(win, '+', height=size) self.fixation_stim1.blendmode = 'avg' def draw(self): self.fixation_stim1.draw()
def RunStudy(self, imageBlock, session): """Runs the study, i.e. the first half of each experimental block. Writes all relevant information about the study to a logfile. imageBlock: List of images to display during the study session: the number of the session (block number) that is running """ studyPrompt = ( "Test Session {}/{}: Are the following objects indoor or outdoor?\n\n('{}' to continue)" .format(session, 10, self.pauseButton)) studyText = TextStim(self.window, studyPrompt, color='Black') studyText.draw(self.window) self.window.flip() continueKey = waitKeys(keyList=[self.pauseButton, 'escape']) if (continueKey[0] == 'escape'): self.logfile.write("\n\n\nStudy Not Run Early\n\n\n") return self.logfile.write("\nBegin Study %d\n" % (session)) self.logfile.write("{h1:<6}{h2:<23}{h3:<10}{h4}\n".format( h1="Trial", h2="Image", h3="Response", h4="RT")) #Run trial for each image in the image block for i in range(0, len(imageBlock)): keyPresses = self.RunTrialSingle(imageBlock[i]) if (keyPresses == []): respKey = '' respRT = 0 else: respKey = keyPresses[0][0] respRT = keyPresses[0][1] if (respKey == "escape"): self.logfile.write("\n\n\nStudy block terminated early\n\n\n") break elif (respKey == self.pauseButton): self.Pause() self.logfile.write("{:^5}{:<23}{:^11}{:<1.3f}\n".format( i + 1, imageBlock[i], respKey, respRT)) return
class InstructionTrial(Trial): """ Simple trial with instruction text. """ def __init__(self, session, trial_nr, phase_durations=[np.inf], txt=None, keys=None, **kwargs): super().__init__(session, trial_nr, phase_durations, **kwargs) txt_height = self.session.settings['various'].get('text_height') txt_width = self.session.settings['various'].get('text_width') if txt is None: txt = '''Press any button to continue.''' self.text = TextStim(self.session.win, txt, height=txt_height, wrapWidth=txt_width, **kwargs) self.keys = keys def draw(self): self.session.fixation.draw() self.session.report_fixation.draw() self.text.draw() def get_events(self): events = super().get_events() if self.keys is None: if events: self.stop_phase() else: for key, t in events: if key in self.keys: self.stop_phase()
class IntroBlockTrial(Trial): def __init__(self, session, trial_nr, phase_durations=[5.], prob1=0.55, prob2=1.0, n_trials=16, **kwargs): super().__init__(session, trial_nr, phase_durations, **kwargs) txt = f""" In this block of {n_trials} trials, the first option will have a winning chance of {int(prob1*100):d}%.\n\n The second option will have a winning chance of {int(prob2*100):d}%. """ text_width = self.session.settings['various'].get('text_width') text_height = self.session.settings['various'].get('text_height') piechart_width = self.session.settings['various'].get('piechart_width') piechart_pos1 = .5 * -text_width - .25 * piechart_width, 1.5 * piechart_width piechart_pos2 = .5 * -text_width - .25 * piechart_width, -1.5 * piechart_width self.piechart1 = ProbabilityPieChart(self.session.win, prob1, pos=piechart_pos1, size=piechart_width) self.piechart2 = ProbabilityPieChart(self.session.win, prob2, pos=piechart_pos2, size=piechart_width) self.text = TextStim(self.session.win, txt, wrapWidth=text_width, height=text_height) def draw(self): self.text.draw() self.piechart1.draw() self.piechart2.draw()
class KeypressTrial(Trial): def __init__(self, mouse: Mouse, window: Window, text: str, keys: List[str]): super().__init__(mouse, window) self.keys = keys self.instruction_text = TextStim(window, text=text, color="black", height=30, pos=(0, 0)) def run(self): self.draw() self.window.flip() keys = event.waitKeys(keyList=self.keys) self.window.flip() return keys def draw(self): self.instruction_text.draw(self.window)
class StimulusSetToPosition(StimulusSet): def __init__(self, win, pos, size, session, ori=0, hide=False, text=''): super(StimulusSetToPosition, self).__init__(win, pos=pos, size=size, session=session, ori=ori, hide=hide) lw = self.session.deg2pix(self.config.get('cross', 'linewidth')) self.cross = Cross( self.screen, self.size, pos=self.pos, lineColor=self.config.get('cross', 'color'), lineWidth=lw, ori=ori, ) self.text_stimulus = TextStim( self.screen, 'size left', pos=[self.pos[0], self.pos[1] + 0.1 * self.size], height=self.size * 0.05, ori=self.ori, color='green') self.checkerboard.contrast = 0 def draw(self): super(StimulusSetToPosition, self).draw() if not self.hide: self.cross.draw() self.text_stimulus.draw() def set_text(self, text): self.text_stimulus.text = text
def draw_overview_target(win, level, target_pos, text_pos, mouse_clicks_all_levels): target = ImageStim(win, 'target.png', size=420, pos=target_pos) level_text = TextStim(win, text=f'Level {level}', height=35, color=(0.2, 0.2, 0.8), pos=text_pos) target.draw() level_text.draw() target_x, target_y = target_pos curr_level_mouse_clicks = mouse_clicks_all_levels[level - 1] for target_hit_pos in curr_level_mouse_clicks: if target_hit_pos['mouse_in_target']: circle = Circle(win, radius=5, fillColor='yellow', lineColor='yellow') circle.setPos((target_hit_pos['mouse_x'] + target_x, target_hit_pos['mouse_y'] + target_y)) circle.draw()
class Button(): START, END = range(2) def __init__(self, win, pos, width, height, name, text='选择'): self.name = name self.rect = Rect(win, height=height, width=width, units='norm', pos=pos) self.mouse = event.Mouse(win=win) self.caption = TextStim(win, text=text, height=height - 0.01 , pos=pos, units='norm', color=(0, 0, 0), colorSpace='rgb255') self.state = self.START def draw(self): x, y = self.mouse.getPos() if self.rect.contains(x, y, units='norm'): self.rect.setLineColor(color=(0, 0, 204), colorSpace='rgb255') self.caption.setColor(color=(0, 0, 204), colorSpace='rgb255') else: self.rect.setLineColor(color=(0, 0, 0), colorSpace='rgb255') self.caption.setColor(color=(0, 0, 0), colorSpace='rgb255') self.rect.draw() self.caption.draw() def process(self): x, y = self.mouse.getPos() if self.rect.contains(x, y, units='norm') and self.mouse.getPressed()[0] == 1: self.state = self.END
def show_intro(win): start = TextStim( win, text="Hi there, player! This is you! Let's play!", height=35, color=(0.2, 0.2, 0.8), pos=(250, 230), ) player = ImageStim( win, 'creature.jpg', pos=(0, -100), size=(420, 420), ) intro_text = ( 'In this game you should shoot at the target with your mouse. ' + 'The target moves rapidly to a new position each time you shoot at it.' + 'There are 3 levels each faster than the previous one. Good luck!') instructions = TextStim( win, text=intro_text, height=35, color=(1, 0.2, 0.6), pos=(250, 0), ) start.draw() player.draw() win.flip() wait(3) instructions.draw() win.flip() wait(8)
def feedback_text(self, state): if state == "incorrect": fb_inc = TextStim(disp, text='Incorrect!', height=self.size, color=convertRGB(RED)) fb_inc.draw() if state == "correct": fb_C = TextStim(disp, text='Correct!', height=self.size, color=convertRGB(GREEN)) fb_C.draw() if state == "no response": fb_nr = TextStim(disp, text='Please make a choice!', height=self.size, color=convertRGB(BLACK)) fb_nr.draw()
def instructions(self, state): if state == "welcome": textscreen = TextStim(disp, text=welcome_text, color=convertRGB(BLACK), height=self.size) textscreen.draw() disp.flip() if state == "experiment finished": endscreen = TextStim(disp, text=experiment_finished_Text, color=convertRGB(BLACK), height=self.size) endscreen.draw() disp.flip() if state == "practice finished": pracscreen = TextStim(disp, text=practice_finished_text, color=convertRGB(BLACK), height=self.size) pracscreen.draw() disp.flip()
class ProjectionsLinesAndCircles(object): """ Test jig for projection warping. Switch between warpings by pressing a key 'S'pherical, 'C'ylindrical, 'N'one, warp'F'ile. Click the mouse to set the eyepoint X, Y. Up / Down arrow or mousewheel to move eyepoint in and out. """ def __init__(self, win, warper): self.win = win self.warper = warper self.stimT = TextStim(self.win, text='Null warper', units = 'pix', pos=(0, -140), alignHoriz='center', height=20) self.bl = -win.size / 2.0 self.tl = (self.bl[0], -self.bl[1]) self.tr = win.size / 2.0 self.stims = [] self.degrees = 120 nLines = 12 for x in range(-nLines, nLines+1): t = GratingStim(win,tex=None,units='deg',size=[2,win.size[1]],texRes=128,color=foregroundColor, pos=[float(x) / nLines * self.degrees,0]) self.stims.append (t) for y in range (-nLines, nLines+1): t = GratingStim(win,tex=None,units='deg',size=[win.size[0],2],texRes=128,color=foregroundColor,pos=[0,float(y)/nLines * self.degrees]) self.stims.append (t) for c in range (1, nLines+1): t = Circle (win, radius=c * 10, edges=128, units='deg', lineWidth=4) self.stims.append (t) self.updateInfo() self.keys = key.KeyStateHandler() win.winHandle.push_handlers(self.keys) self.mouse = event.Mouse(win=self.win) def updateFrame(self): """ Updates frame with any item that is to be modulated per frame. """ for s in self.stims: s.draw() self.stimT.draw() def update_sweep(self): """ Update function for sweeps. Input is in domain units. """ self.updateFrame() self.check_keys() self._handleMouse() self.win.flip() def updateInfo(self): try: self.stimT.setText ("%s \n eyePoint: %.3f, %.3f \n eyeDistance: %.2f\n\nProjection: [s]pherical, [c]ylindrical, [n]one, warp[f]ile\nFlip: [h]orizontal, [v]ertical\nMouse: wheel = eye distance, click to set eyepoint\n[q]uit" % ( self.warper.warp, self.warper.eyepoint[0], self.warper.eyepoint[1], self.warper.dist_cm)) except: pass def check_keys(self): """Checks key input""" for keys in event.getKeys(timeStamped=True): k = keys[0] if k in ['escape', 'q']: self.win.close() sys.exit() elif k in ['space']: for c in range (1,2): t = Circle(self.win, radius=c) self.stims.append (t) #for c in range (1,2): # t = RadialStim(self.win) # self.stims.append(t) # handle projections elif k in ['s']: self.warper.changeProjection ('spherical', None, (0.5,0.5)) elif k in ['c']: self.warper.changeProjection ('cylindrical', None, (0.5,0.5)) elif k in ['n']: self.warper.changeProjection (None, None, (0.5,0.5)) elif k in ['f']: self.warper.changeProjection ('warpfile', r'..\data\sample.meshwarp.data', (0.5,0.5)) # flip horizontal and vertical elif k in ['h']: self.warper.changeProjection(self.warper.warp, self.warper.warpfile, flipHorizontal = not self.warper.flipHorizontal) elif k in ['v']: self.warper.changeProjection(self.warper.warp, self.warper.warpfile, flipVertical = not self.warper.flipVertical) # move eyepoint elif k in ['down']: if (self.warper.dist_cm > 1): self.warper.dist_cm -= 1 self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) elif k in ['up']: if (self.warper.dist_cm < 200): self.warper.dist_cm += 1 self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) elif k in ['right']: if (self.warper.eyepoint[0] < 0.9): self.warper.eyepoint = (self.warper.eyepoint[0] + 0.1, self.warper.eyepoint[1]) self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) elif k in ['left']: if (self.warper.eyepoint[0] > 0.1): self.warper.eyepoint = (self.warper.eyepoint[0] - 0.1, self.warper.eyepoint[1]) self.warper.changeProjection (self.warper.warp, None, self.warper.eyepoint) self.updateInfo() def _handleMouse(self): x,y = self.mouse.getWheelRel() if y != 0: self.warper.dist_cm += y self.warper.dist_cm = max (1, min (200, self.warper.dist_cm)) self.warper.changeProjection (self.warper.warp, self.warper.warpfile, self.warper.eyepoint) self.updateInfo() pos = (self.mouse.getPos() + 1) / 2 leftDown = self.mouse.getPressed()[0] if leftDown: self.warper.changeProjection (self.warper.warp, self.warper.warpfile, pos) self.updateInfo()
class DetectPupilsScreen(Screen): def __init__(self, disp, text, config_dict, pupil_coords_getter, seconds_to_ok): super(DetectPupilsScreen, self).__init__(disp) self.continue_button.setPos((0.0,0.0)) self.pupil_coords_getter = pupil_coords_getter cfg = config_dict[u'detect_pupils_screen'] self.in_range_ctr = 0 fps = self.window.getActualFrameRate() self.ctr_max = fps*seconds_to_ok self.detect_pupils_instructions = TextStim( self.window, text=text, pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.x_cfg_2_pix(cfg[u'text'][u'width']), height=cfg[u'text'][u'font_size'] ) self.lefteye = [] self.lefteye.append(Circle(self.window, radius=50)) self.lefteye[-1].fillColor='white' self.lefteye.append(Circle(self.window, radius=25)) self.lefteye[-1].fillColor='black' self.riteeye = [] self.riteeye.append(Circle(self.window, radius=50)) self.riteeye[-1].fillColor='white' self.riteeye.append(Circle(self.window, radius=25)) self.riteeye[-1].fillColor='black' # self.ok_indicator = RadialStim( # self.window, tex='none', mask='gauss', pos=(0,0), # size=(1000,1000), color=[0,0,0.5], opacity=0.5 # ) self.ok_indicator = Circle( self.window, radius=(350,200), fillColor='palegreen', opacity=0.05, lineColor=None ) self.grid = [] for x, y in self.window.calib_points_coords: self.grid.append(Circle(self.window, radius=5, pos=self.coords((x, y)), lineColor=None, fillColor='green' )) def draw(self, debug_mode=False): ((leftx,lefty),(ritex,ritey)) = self.pupil_coords_getter() leftx *= self.window.hres lefty *= self.window.vres ritex *= self.window.hres ritey *= self.window.vres if leftx == 0.0 or lefty == 0.0: leftx, lefty = (-5000,-5000) if ritex == 0.0 or ritey == 0.0: ritex, ritey = (-5000,-5000) for circle in self.lefteye: circle.pos = self.coords((leftx,lefty)) for circle in self.riteeye: circle.pos = self.coords((ritex,ritey)) # ldist = xydist([leftx,lefty], (self.window.hres/2,self.window.vres/2)) # rdist = xydist([ritex,ritey], (self.window.hres/2,self.window.vres/2)) # if ldist+rdist < self.window.vres/2: # self.in_range_ctr += 1 if (self.ok_indicator.contains(self.lefteye[0].pos) and self.ok_indicator.contains(self.riteeye[0].pos) ): self.in_range_ctr += 1 op = self.ok_indicator.opacity + 0.03 self.ok_indicator.opacity = min(op, 0.65) else: op = self.ok_indicator.opacity - 0.03 self.ok_indicator.opacity = max(op, 0.05) # # # if missed_flag: # temp = self.ok_indicator.color * 0.95 # temp[2] = 0.5 # temp[0] = 0 # else: # ratio = self.window.vres/(3*(ldist+rdist)) # if ratio > 1: # ratio = 1 # temp = [0, ratio, 0.5] # # self.ok_indicator.color = temp if ((self.in_range_ctr >= self.ctr_max) or debug_mode ): self.continue_button.clickable = True # draw commands for thing in self.grid: thing.draw() self.ok_indicator.draw() self.detect_pupils_instructions.draw() self.continue_button.draw() for circle in self.lefteye: circle.draw() for circle in self.riteeye: circle.draw()
class Display: def __init__(self, pars): self.win = initializers.setup_window() self.pars = pars self.geom = initializers.setup_geometry(self.win, self.pars) self.rotation_clocks = [None] * self.geom['numtargs'] self.type = ['default'] * self.geom['numtargs'] self.setup_sounds() self.setup_images() self.setup_text() def setup_sounds(self): self.cashsnd = Sound('resources/cash.wav') self.firesnd = Sound('resources/bbhit.wav') self.buzzsnd = Sound('resources/buzz.wav') def setup_images(self): self.notargs = [] self.gotargs = [] self.deftargs = [] self.bkimg = ImageStim(self.win, image='resources/pond.jpg', units='norm', size=(2.0, 2.0)) for targ in range(self.geom['numtargs']): self.notargs.append( ImageStim(self.win, image='resources/rfrog2.jpg', size=self.geom['target_size'], pos=self.geom['target_centers'][targ])) self.gotargs.append( ImageStim(self.win, image='resources/gfrog2.jpg', size=self.geom['target_size'], pos=self.geom['target_centers'][targ])) self.deftargs.append( ImageStim(self.win, image='resources/lilypad.jpg', size=self.geom['target_size'], pos=self.geom['target_centers'][targ])) # set initial target stims to be the defaults self.targets = [] for targ in self.deftargs: self.targets.append(targ) def setup_text(self): self.scoretxt = TextStim(self.win, text="Total Points: ", font='Helvetica', alignHoriz='left', alignVert='top', units='norm', pos=(-1, 1), height=0.2, color=[178, 34, 34], colorSpace='rgb255', wrapWidth=2) self.targtxt = [] for targ in range(self.geom['numtargs']): self.targtxt.append( TextStim(self.win, pos=self.geom['target_centers'][targ], color='White', units='height', height=0.05, text='')) def set_target_image(self, index, value='default'): if value == 'go': self.targets[index] = self.gotargs[index] elif value == 'no': self.targets[index] = self.notargs[index] elif value == 'default': self.targets[index] = self.deftargs[index] def set_target_text(self, index, value): self.targtxt[index].setText(value) def set_score(self, pts): self.scoretxt.setText('Total Points: ' + str(pts)) def onset(self, index, value): self.rotation_clocks[index] = Clock() self.type[index] = value def offset(self, index): self.rotation_clocks[index] = Clock() self.type[index] = 'default' def update(self): # for each target with clock running (i.e., rotating) ... for idx, clk in enumerate(self.rotation_clocks): if clk: rot_time = clk.getTime() rot_dur = self.pars['rot_dur'] if rot_time > rot_dur: rotfrac = -1 # rotation completed else: rotfrac = cos(pi * rot_time / self.pars['rot_dur']) # adjust target size to give illusion of rotation base_size = self.geom['target_size'] self.targets[idx].size = (abs(rotfrac) * base_size[0], base_size[1]) # set correct image on target based on rotation angle if rotfrac < 0: self.set_target_image(idx, self.type[idx]) def draw(self): self.update() self.bkimg.draw() self.scoretxt.draw() for stim in self.targets: stim.draw() for stim in self.targtxt: stim.draw() self.win.flip() def close(self): self.win.close()
# test for two monitors: import time from psychopy.visual import Window from psychopy.visual import TextStim from psychopy import event # create a Window create_win = lambda s: Window(size=(1280,1024), fullscr=True, monitor="testMonitor", winType='pyglet', screen=s) win1 = create_win(0) win2 = create_win(1) # draw some text on the Window txt = list() txt.append(TextStim(win1, text="This is screen 1")) txt.append(TextStim(win2, text="This is screen 2")) txt2 = TextStim(win2, pos=(0, -0.5), text="another text") [t.draw() for t in txt] win1.flip() event.waitKeys() win2.flip(clearBuffer=False) event.waitKeys() txt2.draw() win2.flip(clearBuffer=False) event.waitKeys()
class Display: def __init__(self, pars): self.win = initializers.setup_window() self.pars = pars self.geom = initializers.setup_geometry(self.win, self.pars) self.rotation_clocks = [None] * self.geom['numtargs'] self.type = ['default'] * self.geom['numtargs'] self.setup_sounds() self.setup_images() self.setup_text() def setup_sounds(self): self.cashsnd = Sound('resources/cash.wav') self.firesnd = Sound('resources/bbhit.wav') self.buzzsnd = Sound('resources/buzz.wav') def setup_images(self): self.notargs = [] self.gotargs = [] self.deftargs = [] self.bkimg = ImageStim(self.win, image='resources/pond.jpg', units='norm', size=(2.0, 2.0)) for targ in range(self.geom['numtargs']): self.notargs.append(ImageStim(self.win, image='resources/rfrog2.jpg', size=self.geom['target_size'], pos=self.geom['target_centers'][targ])) self.gotargs.append(ImageStim(self.win, image='resources/gfrog2.jpg', size=self.geom['target_size'], pos=self.geom['target_centers'][targ])) self.deftargs.append(ImageStim(self.win, image='resources/lilypad.jpg', size=self.geom['target_size'], pos=self.geom['target_centers'][targ])) # set initial target stims to be the defaults self.targets = [] for targ in self.deftargs: self.targets.append(targ) def setup_text(self): self.scoretxt = TextStim(self.win, text="Total Points: ", font='Helvetica', alignHoriz='left', alignVert='top', units='norm', pos=(-1, 1), height=0.2, color=[178, 34, 34], colorSpace='rgb255', wrapWidth=2) self.targtxt = [] for targ in range(self.geom['numtargs']): self.targtxt.append(TextStim(self.win, pos=self.geom['target_centers'][targ], color='White', units='height', height=0.05, text='')) def set_target_image(self, index, value='default'): if value == 'go': self.targets[index] = self.gotargs[index] elif value == 'no': self.targets[index] = self.notargs[index] elif value == 'default': self.targets[index] = self.deftargs[index] def set_target_text(self, index, value): self.targtxt[index].setText(value) def set_score(self, pts): self.scoretxt.setText('Total Points: ' + str(pts)) def onset(self, index, value): self.rotation_clocks[index] = Clock() self.type[index] = value def offset(self, index): self.rotation_clocks[index] = Clock() self.type[index] = 'default' def update(self): # for each target with clock running (i.e., rotating) ... for idx, clk in enumerate(self.rotation_clocks): if clk: rot_time = clk.getTime() rot_dur = self.pars['rot_dur'] if rot_time > rot_dur: rotfrac = -1 # rotation completed else: rotfrac = cos(pi * rot_time / self.pars['rot_dur']) # adjust target size to give illusion of rotation base_size = self.geom['target_size'] self.targets[idx].size = (abs(rotfrac) * base_size[0], base_size[1]) # set correct image on target based on rotation angle if rotfrac < 0: self.set_target_image(idx, self.type[idx]) def draw(self): self.update() self.bkimg.draw() self.scoretxt.draw() for stim in self.targets: stim.draw() for stim in self.targtxt: stim.draw() self.win.flip() def close(self): self.win.close()
class ContribScreen(Screen): """ This screen lets users select their contribution. """ def __init__(self, disp, text, config_dict, gaze_pos_getter=None, width=None, height=None, margin=None, font_size=None, choice_font_size=100, origin=None ): super(ContribScreen, self).__init__(disp) cfg = config_dict[u'contrib_screen'] self.gaze_pos_getter = gaze_pos_getter self.instr_text_preformat = text self.contrib_choice = '__' self.mouseover_threshold = 0 self.choice_coords = [] if width is not None: self.width = width else: self.width = self.window.hres if height is not None: self.height = height else: self.height = self.window.vres if margin is not None: self.margin = margin else: self.margin = self.window.margin if origin is not None: self.origin = origin if font_size is None: font_size = config_dict[u'contrib_screen'][u'text'][u'font_size'] self.contrib_choices = self.gen_contrib_choices( cfg[u'nrows'], cfg[u'ncols'], font_size=choice_font_size ) self.contrib_instructions = TextStim( self.window, height=font_size, text=self.instr_text_preformat.format(self.contrib_choice), pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.w_cfg_2_pix(cfg[u'text'][u'width']) ) self.gaze = Circle(self.window, radius=5) self.gaze.fillColor = 'red' def draw(self, debug_mode=False): mouse_x, mouse_y = self.mouse.getPos() for text_stim in self.contrib_choices: if xydist((mouse_x, mouse_y), text_stim.pos) < self.mouseover_threshold: text_stim.color = 'darkorange' if self.mouse.getPressed()[0]: self.contrib_choice = text_stim.text self.contrib_instructions.setText(self.instr_text_preformat.format(self.contrib_choice)) self.continue_button.clickable = True else: text_stim.color = 'white' text_stim.draw() self.continue_button.draw() self.contrib_instructions.draw() if self.gaze_pos_getter is not None: self.gaze.pos = self.coords(self.gaze_pos_getter()) self.gaze.draw() def cleanup(self): self.continue_button.clickable = False self.contrib_instructions.setText(self.instr_text_preformat.format('__')) self.move_on_flag.clear() def gen_contrib_choices(self, nrows, ncols, font_size): h_spacing = (self.width - 2*self.margin)/(ncols-1) v_spacing = h_spacing '''OR: v_spacing = (self.height - 2*self.margin)/(nrows-1)''' self.mouseover_threshold = min(h_spacing, v_spacing)/4 contrib_choices = [] for i in range(0, nrows*ncols): xpos = self.margin + (i % ncols)*h_spacing ''' To move the array to the bottom of the page: ypos = self.height - self.margin - (nrows-floor(1.0*i/ncols)-1)*v_spacing ''' ypos = floor(1.0*i/ncols)*v_spacing + self.margin ''' 1.0*i/ncols gives us a floating-point number. Without the 1.0, python interprets this as int-division and truncates. I could have exploited this for slightly simpler code but it is really stupid that it works that way and who knows what bugs could pop up by relying on something that is in my opinion a bug? We take the floor of that number to give us a "row index." We multiply this number by the vertical spacing. ''' if i < 10: temp = ' {} '.format(i) else: temp = '{}'.format(i) contrib_choices.append(TextStim(win=self.window, text=temp, pos=self.coords((xpos, ypos)), height=font_size)) self.choice_coords.append((xpos, ypos)) return contrib_choices
class DetectPupilsScreen(Screen): """ Screen which lets subjects see where they should move their head to get the best calibration. """ def __init__(self, disp, text, config_dict, pupil_coords_getter, seconds_to_ok): super(DetectPupilsScreen, self).__init__(disp) self.continue_button.pos = (0.0, 0.0) self.pupil_coords_getter = pupil_coords_getter cfg = config_dict[u'detect_pupils_screen'] self.in_range_ctr = 0 fps = self.window.getActualFrameRate() if fps is None: fps = 60 self.ctr_max = fps*seconds_to_ok self.detect_pupils_instructions = TextStim( self.window, text=text, pos=self.coords((self.x_cfg_2_pix(cfg[u'text'][u'x']), self.y_cfg_2_pix(cfg[u'text'][u'y']) )), wrapWidth=self.x_cfg_2_pix(cfg[u'text'][u'width']), height=cfg[u'text'][u'font_size'] ) self.lefteye = [] self.lefteye.append(Circle(self.window, radius=50)) self.lefteye[-1].fillColor = 'white' self.lefteye.append(Circle(self.window, radius=25)) self.lefteye[-1].fillColor = 'black' self.riteeye = [] self.riteeye.append(Circle(self.window, radius=50)) self.riteeye[-1].fillColor = 'white' self.riteeye.append(Circle(self.window, radius=25)) self.riteeye[-1].fillColor = 'black' # self.ok_indicator = RadialStim( # self.window, tex='none', mask='gauss', pos=(0,0), # size=(1000,1000), color=[0,0,0.5], opacity=0.5 # ) self.ok_indicator = Circle( self.window, radius=(350, 200), fillColor='palegreen', opacity=0.05, lineColor=None ) self.grid = [] for x, y in self.window.calib_points_coords: self.grid.append(Circle(self.window, radius=5, pos=self.coords((x, y)), lineColor=None, fillColor='green' )) def draw(self, debug_mode=False): ((leftx, lefty), (ritex, ritey)) = self.pupil_coords_getter() leftx *= self.window.hres lefty *= self.window.vres ritex *= self.window.hres ritey *= self.window.vres if leftx == 0.0 or lefty == 0.0: leftx, lefty = (-5000, -5000) if ritex == 0.0 or ritey == 0.0: ritex, ritey = (-5000, -5000) for circle in self.lefteye: circle.pos = self.coords((leftx, lefty)) for circle in self.riteeye: circle.pos = self.coords((ritex, ritey)) if self.ok_indicator.contains(self.lefteye[0].pos) and self.ok_indicator.contains(self.riteeye[0].pos): self.in_range_ctr += 1 op = self.ok_indicator.opacity + 0.03 self.ok_indicator.opacity = min(op, 0.65) else: op = self.ok_indicator.opacity - 0.03 self.ok_indicator.opacity = max(op, 0.05) if (self.in_range_ctr >= self.ctr_max) or debug_mode: self.continue_button.clickable = True # draw commands for thing in self.grid: thing.draw() self.ok_indicator.draw() self.detect_pupils_instructions.draw() self.continue_button.draw() for circle in self.lefteye: circle.draw() for circle in self.riteeye: circle.draw()
print('Max. flow rate: .3%f %s' % (pump.maxFlowRate, pump.flowRateUnit)) win = Window() msg = ('Press one of the following keys: \n\n' ' F – Fill Syringe at 1 mL/s\n' ' E – Empty Syringe at 1 mL/s\n' ' A – Aspirate 1 mL at 1 mL/s\n' ' D – Dispense 1 mL at 1 mL/s\n' '\n' ' Q – Quit') t = TextStim(win, msg) event.clearEvents() while True: t.draw() win.flip() # Retrieve keypresses. The user can completely fill or empty the syringe, # or aspirate or dispense a small volume (1 mL) by pressing the # corresponding keys. # # When aspirating or dispensing, the code halts further script execution # until the pump operation has finished, and then immediately switches the # valve position (i.e., from inlet to outlet after aspiration, and from # outlet to inlet after dispense). During an experiment, this can ensure # a sharp(er) stimulus offset. keys = event.getKeys(keyList=['f', 'e', 'a', 'd', 'q']) if 'f' in keys: pump.fill(flowRate=1, waitUntilDone=False)
class KeyboardInputScreen(Screen): """ A screen to allow users to enter data via the keyboard. """ def __init__(self, disp, text, input_prompt_list, correct_ans_list=None, extra_draw_list=None, wait_time=1): super(KeyboardInputScreen, self).__init__(disp, wait_time=wait_time) self.instructions_text = TextStim( disp, pos=(0, disp.vres*0.2), text=text, height=40, wrapWidth=1400 ) self.input_prompt_list = [] self.input_field_list = [] self.extra_draw_list = extra_draw_list if self.extra_draw_list is None: self.extra_draw_list = [] height_list = [] for i in range(len(input_prompt_list)): height_list.append( disp.vres*-0.2*i/(len(input_prompt_list)-1) ) for index, text in enumerate(input_prompt_list): self.input_prompt_list.append(TextStim( disp, pos=(disp.hres*-0.2, height_list[index]), text=text, height=40, wrapWidth=disp.hres*0.5 )) self.input_field_list.append(button.Button( disp, pos=(disp.hres*0.2, height_list[index]), font_size=30, width=disp.hres*0.15, height=40, text_color='black', text='' )) self.active_input_field = None self.answer_list = [] self.correct_ans_list = correct_ans_list def draw(self, debug_mode=False): key_list = getKeys() if self.active_input_field is not None: for key in key_list: temp = self.active_input_field.text if key == 'backspace': if len(temp) > 0: self.active_input_field.text = temp[:-1] elif key == 'tab': new_index = self.input_field_list.index(self.active_input_field) + 1 try: self.active_input_field = self.input_field_list[new_index] except IndexError: self.active_input_field = self.input_field_list[0] elif key in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']: self.active_input_field.text = temp + key elif key in ['num_0', 'num_1', 'num_4', 'num_7', 'num_2', 'num_5', 'num_8', 'num_3', 'num_6', 'num_9']: self.active_input_field.text = temp + key[-1] elif key in ['comma', 'period', 'num_decimal']: self.active_input_field.text = temp + ',' for index, input_field in enumerate(self.input_field_list): if self.mouse.isPressedIn(input_field.frame, [0]): self.active_input_field = input_field if input_field is self.active_input_field: input_field.color = 'white' elif input_field.color == 'white': input_field.color = 'lightgrey' for input_field in self.input_field_list: if input_field.text == '': self.continue_button.clickable = False self.instructions_text.draw() self.continue_button.draw() for index, input_ in enumerate(self.input_field_list): input_.draw() self.input_prompt_list[index].draw() for item in self.extra_draw_list: item.draw() def cleanup(self): self.move_on_flag.clear() self.active_input_field = None self.window.flip() for item in self.input_field_list: self.answer_list.append(item.text) self.window.flip() key_list = getKeys() if self.active_input_field is not None: for key in key_list: temp = self.active_input_field.text if key == 'backspace': if len(temp) > 0: self.active_input_field.text = temp[:-1] elif key == 'tab': new_index = self.input_field_list.index(self.active_input_field) + 1 try: self.active_input_field = self.input_field_list[new_index] except IndexError: self.active_input_field = self.input_field_list[0] elif key in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']: self.active_input_field.text = temp + key elif key in ['num_0', 'num_1', 'num_4', 'num_7', 'num_2', 'num_5', 'num_8', 'num_3', 'num_6', 'num_9']: self.active_input_field.text = temp + key[-1] elif key in ['comma', 'period', 'num_decimal']: self.active_input_field.text = temp + ',' for index, input_field in enumerate(self.input_field_list): if self.mouse.isPressedIn(input_field.frame, [0]): self.active_input_field = input_field if input_field is self.active_input_field: input_field.color = 'white' elif input_field.color == 'white': input_field.color = 'lightgrey' for input_field in self.input_field_list: if input_field.text == '': self.continue_button.clickable = False self.instructions_text.draw() self.continue_button.draw() for index, input_ in enumerate(self.input_field_list): input_.draw() self.input_prompt_list[index].draw() for item in self.extra_draw_list: item.draw()
class KeyboardInputScreen(Screen): def __init__(self, disp, text, input_prompt_list, correct_ans_list=None, extra_draw_list=[]): super(KeyboardInputScreen, self).__init__(disp) self.instructions_text = TextStim( disp, pos=(0, disp.vres*0.2), text=text, height=40, wrapWidth=self.w_cfg_2_pix(0.666) ) self.input_prompt_list = [] self.input_field_list = [] self.extra_draw_list = extra_draw_list height_list = [] for i in range(len(input_prompt_list)): height_list.append( disp.vres*-0.2*i/(len(input_prompt_list)-1) ) for index, text in enumerate(input_prompt_list): self.input_prompt_list.append(TextStim( disp, pos=(disp.hres*-0.2, height_list[index]), text=text, height=40, wrapWidth=disp.hres*0.5 )) self.input_field_list.append(button.Button( disp, pos=(disp.hres*0.2, height_list[index]), font_size=30, width=disp.hres*0.15, height=40, text_color='black', text='' )) self.active_input_field = None self.answer_list = [] self.correct_ans_list = correct_ans_list def draw(self, debug_mode=False): self.continue_button.clickable = True key_list = getKeys() if self.active_input_field is not None: for key in key_list: temp = self.active_input_field.text if key == 'backspace': if len(temp) > 0: self.active_input_field.text = temp[:-1] elif key == 'tab': new_index = self.input_field_list.index(self.active_input_field) + 1 try: self.active_input_field = self.input_field_list[new_index] except IndexError: self.active_input_field = self.input_field_list[0] elif key in ['1','2','3','4','5','6','7','8','9','0']: self.active_input_field.text = temp + key elif key in ['num_0', 'num_1', 'num_4', 'num_7', 'num_2', 'num_5', 'num_8', 'num_3', 'num_6', 'num_9']: self.active_input_field.text = temp + key[-1] elif key in ['comma', 'period', 'num_decimal']: self.active_input_field.text = temp + ',' for index, input_field in enumerate(self.input_field_list): if self.mouse.isPressedIn(input_field._frame, [0]): self.active_input_field = input_field if input_field is self.active_input_field: input_field._frame.fillColor = 'white' elif input_field._frame.fillColor == 'white': input_field._frame.fillColor = 'lightgrey' for input_field in self.input_field_list: if input_field.text == '': self.continue_button.clickable = False self.instructions_text.draw() self.continue_button.draw() for index, input_ in enumerate(self.input_field_list): input_.draw() self.input_prompt_list[index].draw() for item in self.extra_draw_list: item.draw() def cleanup(self): self.move_on_flag.clear() self.active_input_field = None self.window.flip() for item in self.input_field_list: self.answer_list.append(item.text) self.window.flip() self.window.flip() # # class PainfullyClearInstructions(Screen): # # # def __init__(self, disp): # super(PainfullyClearInstructions, self).__init__(disp) # # self.mypoints = [] # self.yourpoints = [] # for x, y in self.gen_points_coords(20, 4, 300, 300): # self.mypoints.append(Circle( # win=self.window, radius=10, # fillColor='white', lineColor=None, pos=(x,y) # )) # for x, y in self.gen_points_coords(20, 4, self.width-300-3*30, 300): # self.mypoints.append(Circle( # win=self.window, radius=10, # fillColor='black', lineColor=None, pos=(x,y) # )) # # def gen_points_coords(self, n, n_cols, col_1_x, row_1_y): # ys = [] # xs = [] # for i in range(n): # ys.append(floor((row_1_y + 30*i)/n_cols)) # xs.append(col_1_x + 30*(i % n_cols)) # return zip(xs, ys) # # def step1(self):
class FlexibleResourcePresentationScreen(Screen): def __init__(self, disp, text, extra_commands, wait_time=1, txt_dict=None, cfg_dict=None): super(FlexibleResourcePresentationScreen, self).__init__(disp, wait_time) self.txt_dict = txt_dict self.cfg_dict = cfg_dict self.wait_time = wait_time if self.wait_time == 0: self.continue_button.clickable = True self.text_stim = TextStim( win=self.window, text=text, pos=self.coords((self.x_cfg_2_pix(0.25), self.y_cfg_2_pix(0.5))), height=Screen.default_font_size, wrapWidth=self.w_cfg_2_pix(0.4) ) self.extra_draw_stims = [] for command in extra_commands: if type(command) == str or type(command) == unicode: items = eval(command) for item in items: self.extra_draw_stims.append(item) def draw(self, debug_mode=False): if not self.continue_button.clickable: if getAbsTime() - self.t0 > self.wait_time: self.continue_button.clickable = True self.continue_button.draw() self.text_stim.draw() for stim in self.extra_draw_stims: stim.draw() def painfully_clear_example(self, n): img = ImageStim( win=self.window, image='resources/worked_example/Slide{}.PNG'.format(n), pos=(0,200), size=(960,720) ) background = Rect( win=self.window, width=img.size[0]+10, height=img.size[1]+10, fillColor='white', lineColor=None, pos=img.pos ) return [background, img] def mini_contrib_screen(self): img = ImageStim( win=self.window, image='resources/contrib_screen.PNG', pos=self.coords((self.x_cfg_2_pix(0.75), self.y_cfg_2_pix(0.33))), size=(960, 540) ) background = Rect( win=self.window, width=img.size[0]+10, height=img.size[1]+10, fillColor='white', lineColor=None, pos=img.pos ) return [background, img] def mini_feedback_screen(self, n): if FeedbackScreen.reversed: img = 'resources/feedback/reversed/Slide{}.PNG'.format(n) else: img = 'resources/feedback/default/Slide{}.PNG'.format(n) image = ImageStim( win=self.window, image=img, pos=self.coords((self.x_cfg_2_pix(0.75), self.y_cfg_2_pix(0.33))), size=(960, 540) ) background = Rect( win=self.window, width=image.size[0]+10, height=image.size[1]+10, fillColor='white', lineColor=None, pos=image.pos ) return [background, image] def cleanup(self): self.window.flip() self.window.flip() self.window.flip()