def trial(self): if P.development_mode: print(self.image_name, self.mask_type) trial_countdown = CountDown(900) # 15 minutes while trial_countdown.remaining() > 0: q = pump(True) if key_pressed(sdl2.SDLK_DELETE, queue=q): # press 'Del' to skip trial break elif key_pressed(sdl2.SDLK_ESCAPE, queue=q): # Press 'escape' to pause and calibrate trial_countdown.pause() self.el.calibrate() self.el.drift_correct() self.el.start(P.trial_number) trial_countdown.resume() continue if trial_countdown.elapsed() >= self.first_warning_onset and not self.first_warning_played: self.warning_signal.play() self.first_warning_played = True if trial_countdown.elapsed() >= self.second_warning_onset and not self.second_warning_played: self.warning_signal.play() self.second_warning_played = True pos = self.el.gaze() fill() if int(pos[0]) != -32768: # if gaze not lost self.gaze_offscreen = time.time() if (pos[0] < 0) or (pos[0] > P.screen_x) or (pos[1] < 0) or (pos[1] > P.screen_y): pass elif (time.time() - self.gaze_offscreen) < self.gaze_timeout: blit(self.arrangement, 5, P.screen_c) if self.mask is not None and trial_countdown.elapsed() < self.mask_off_time: blit(self.mask, 5, pos) flip() return { "trial_num": P.trial_number, "block_num": P.block_number, "arrangement": self.image_name, "mask_type": self.mask_type }
def get_peak_during(self, period, msg=None): """Determines the peak loudness value recorded over a given period. Displays a visual callback that shows the current input volume and the loudest peak encounteredduring the interval so far. Args: period (numeric): the number of seconds to record input for. msg (:obj:`~klibs.KLGraphics.KLNumpySurface.NumpySurface`, optional): a rendered message to display in the top-right corner of the screen during the sampling loop. Returns: int: the loudest peak of all samples recorded during the period. """ local_peak = 0 last_sample = 0 if msg: msg = message(msg, blit_txt=False) flush() self.stream.start() sample_period = CountDown(period + 0.05) while sample_period.counting(): ui_request() sample = self.stream.sample().peak if sample_period.elapsed() < 0.05: # Sometimes 1st or 2nd peaks are extremely high for no reason, so ignore first 50ms continue if sample > local_peak: local_peak = sample sample_avg = (sample + last_sample) / 2 peak_circle = peak(5, int( (local_peak / 32767.0) * P.screen_y * 0.8)) sample_circle = peak( 5, int((sample_avg / 32767.0) * P.screen_y * 0.8)) last_sample = sample fill() blit(Ellipse(peak_circle, fill=[255, 145, 0]), location=P.screen_c, registration=5) blit(Ellipse(sample_circle, fill=[84, 60, 182]), location=P.screen_c, registration=5) if msg: blit(msg, location=[25, 25], registration=7) flip() self.stream.stop() return local_peak
def warm_up(self): warmup_timer = CountDown(600, start=True) self.first_signal_played = False self.second_signal_played = False self.third_signal_played = False self.fourth_signal_played = False while warmup_timer.counting(): if key_pressed(sdl2.SDLK_DELETE): break t = warmup_timer.elapsed() if t < 60: tool = 'pencil' elif 60 <= t < 120: if not self.first_signal_played: self.warning_signal.play() self.first_signal_played = True tool = 'charcoal' elif 120 <= t < 180: if not self.second_signal_played: self.warning_signal.play() self.second_signal_played = True tool = 'smudger' elif 180 <= t < 240: if not self.third_signal_played: self.warning_signal.play() self.third_signal_played = True tool = 'eraser' else: if not self.fourth_signal_played: self.warning_signal.play() self.fourth_signal_played = True tool = 'any' fill() blit(self.images['warmup.png'], 5, P.screen_c) blit(self.warmup_txt[tool], 1, (30, P.screen_y-30)) flip()
def block(self): halfway_block = (P.blocks_per_experiment / 2) + 1 if P.run_practice_blocks and P.session_number == 1: halfway_block += 3 if P.run_practice_blocks and P.session_number == 1 and P.block_number <= 3: txt = "This is a practice block ({0} of 3)\n\n".format( P.block_number) if P.block_number == 1: txt += ( "During this task, arrows will appear either above or below the '+' symbol.\n" "Your job will be to indicate the direction of the middle arrow as quickly\n" "and accurately as possible using the keyboard.\n\n" "( c = left, m = right )") elif P.block_number == 2: txt += ( "On some trials, the central arrow will be displaced upwards or downwards " "by a large amount.\n" "When this occurs, please press the space bar instead of the 'c' or 'm' keys." ) self.trial_type = 'EV' self.ev_offset = 'below' demo_arrows = self.generate_arrows() else: txt += ( "On some trials, a large red countdown timer will appear instead of the arrows." "\nWhen this occurs, please press the space bar as quickly as you can." ) instructions = message(txt, align='center', blit_txt=False) continue_msg = message('Press any key to begin.', align='center', blit_txt=False) instruction_time = CountDown(3) while True: keydown = key_pressed() fill() blit(instructions, 8, (P.screen_c[0], int(P.screen_y * 0.1))) if P.block_number == 2: blit(self.fixation, 5, P.screen_c) for shape, loc in demo_arrows: blit(shape, 5, loc) elif P.block_number == 3: elapsed = min( [int(instruction_time.elapsed() * 1000), 367]) demo_counter = message(str(elapsed).zfill(4), "PVT", blit_txt=False) blit(demo_counter, 5, P.screen_c) if P.development_mode or instruction_time.counting() == False: blit(continue_msg, 2, (P.screen_c[0], int(P.screen_y * 0.9))) if keydown == True: break flip() elif P.run_practice_blocks and P.session_number == 1 and P.block_number == 4: self.block_msg( "Practice complete! Press any key to begin the task.") elif P.block_number == 1: self.block_msg("Press any key to begin the task.") elif P.block_number == halfway_block: self.block_msg( "Phew, you're halfway done! Press any key to continue.")
def instructions(self): p1 = ( "During this task, you will presented with a sequence of letters in the middle of " "the screen.\n\nPress any key to see an example.") p2a = ( "For some blocks, your task will be to indicate whether each letter matches " "the letter just before it:") p2b = ( "For others, your task will be to indicate whether each letter matches " "the letter two before it:") p2c = "(matches for each block type are highlighted)" p3 = ( "Occasionally, the task will be interrupted by screens asking you about your " "focus just prior.\nWhen this happens, please select the most accurate " "response using the mouse cursor.\n\nPress any key to see an example." ) msg1 = message(p1, 'normal', blit_txt=False, align='center') msg2a = message(p2a, 'normal', blit_txt=False, wrap_width=int(P.screen_x * 0.8)) msg2b = message(p2b, 'normal', blit_txt=False, wrap_width=int(P.screen_x * 0.8)) msg2c = message(p2c, 'normal', blit_txt=False) msg3 = message(p3, 'normal', blit_txt=False, align='center', wrap_width=int(P.screen_x * 0.8)) # First page of instructions flush() fill() blit(msg1, 5, P.screen_c) flip() any_key(allow_mouse_click=False) # Example stimuli for letter in (1, 2, 1): trialtime = CountDown(2.5) while trialtime.counting(): mask_on = trialtime.elapsed() > 0.5 stim = self.mask if mask_on else self.letters[ self.letter_set[letter]] ui_request() fill() blit(self.accuracy_rect, 5, P.screen_c) blit(self.accuracy_mask, 5, P.screen_c) blit(stim, 5, P.screen_c) flip() # Task explanation/illustration fill() blit(msg2a, 8, (P.screen_c[0], int(P.screen_y * 0.15))) blit(msg2b, 8, (P.screen_c[0], int(P.screen_y * 0.45))) blit(msg2c, 2, (P.screen_c[0], int(P.screen_y * 0.8))) self.draw_nback_illustration(int(P.screen_y * 0.3), target=5) self.draw_nback_illustration(int(P.screen_y * 0.6), target=4) flip() any_key(allow_mouse_click=False) # Probe explanation + example probe fill() blit(msg3, 5, P.screen_c) flip() any_key() self.probe.collect()
def instructions(self): p1 = ( "During this task, you will presented with a sequence of numbers in the middle of " "the screen.\n\nPress any key to see an example.") p2 = ( "Your task will be to press the [space] key as quickly as possible whenever a " "number other than {0} appears, and to withhold your response whenever the number " "is {0}.\n\nPress any key to continue.".format(P.target)) p3 = ( "Occasionally, the task will be interrupted by screens asking you about your " "focus just prior.\nWhen this happens, please select the most accurate " "response using the mouse cursor.\n\nPress any key to see an example." ) p4 = ( "After responding, you will be asked how much effort you " "were putting into staying focused on the task before the interruption.\n\n" "When this happens, please answer using the scale from 0% to 100% that will appear " "on screen. Your responses will be anonymous so please answer honestly.\n\n" "Press any key to see an example.") msg1 = message(p1, 'normal', blit_txt=False, align='center') msg2 = message(p2, 'normal', blit_txt=False, align='center', wrap_width=int(P.screen_x * 0.8)) msg3 = message(p3, 'normal', blit_txt=False, align='center', wrap_width=int(P.screen_x * 0.8)) msg4 = message(p4, 'normal', blit_txt=False, align='center', wrap_width=int(P.screen_x * 0.8)) # First page of instructions flush() fill() blit(msg1, 5, P.screen_c) flip() any_key(allow_mouse_click=False) # Example stimuli numlist = [1, 2, 3, 4, 5, 6, 7, 8, 9] random.shuffle(numlist) for n in numlist[1:5]: trialtime = CountDown(1.125) numsize = random.choice(self.sizes) while trialtime.counting(): ui_request() fill() mask_on = trialtime.elapsed() > 0.25 if mask_on: blit(self.mask_x, 5, P.screen_c) blit(self.mask_ring, 5, P.screen_c) else: blit(self.digits[n][numsize], 5, P.screen_c) flip() # Task explanation/illustration flush() fill() blit(msg2, 5, P.screen_c) flip() any_key(allow_mouse_click=False) # Probe explanation + example probe fill() blit(msg3, 5, P.screen_c) flip() any_key(allow_mouse_click=False) self.probe.collect() # Slider explanation + example slider fill() blit(msg4, 5, P.screen_c) flip() any_key(allow_mouse_click=False) self.get_effort()