def log_and_recycle_trial(self, err_type): """ Renders an error message to the screen and wait for a response. When a response is made, the incomplete trial data is logged to the trial_err table and the trial is recycled. """ flush() fill() message(self.err_msgs[err_type], registration=5, location=P.screen_c) flip() any_key() err_data = { "participant_id": P.participant_id, "block_num": P.block_number, "trial_num": P.trial_number, "session_type": 'saccade' if P.saccade_response_cond else 'keypress', "cue_location": self.cue_location, "target_location": self.target_location, "start_axis": self.start_axis, "box_rotation": self.rotation_dir if self.animation_trial else NA, "animation_trial": boolean_to_logical(self.animation_trial), "err_type": err_type } self.database.insert(data=err_data, table="trials_err") raise TrialException(self.err_msgs[err_type])
def identity_callback(self, target): # Request appropriate identity identity_request_msg = self.t1_id_request if target == "T1" else self.t2_id_request fill() message(identity_request_msg, location=P.screen_c, registration=5, blit_txt=True) flip()
def update_range(self, seg_count): # this originally did some randomization around a given number and was later changed to hard values self.lower_bound = 1 self.upper_bound = 5 self.lb_msg = message(str(self.lower_bound), "small", blit_txt=False) self.ub_msg = message(str(self.upper_bound), "small", blit_txt=False) self.__build_increments()
def block(self): if not P.practicing: if self.search_type == SPACE: self.condition = self.spatial_conditions_exp.pop() else: self.condition = self.temporal_conditions_exp.pop() else: self.condition = self.practice_conditions.pop() self.target_distractor, self.distractor_distractor = self.condition # Generate wheel to select colors from self.color_selector = ColorWheel(deg_to_px(1), rotation=random.randrange(0, 360)) # Select target colouring self.target_color = self.color_selector.color_from_angle(0) self.target_item = Rectangle(width=self.item_size, fill=self.target_color) self.create_stimuli() if not self.general_instruct_shown: self.general_instruct_shown = True general_text = self.anykey_text.format(self.general_instructions) general_msg = message(general_text, align='left', blit_txt=False) fill() blit(general_msg, 5, P.screen_c) flip() any_key() block_txt = "Block {0} of {1}".format(P.block_number, P.blocks_per_experiment) progress_txt = self.anykey_text.format(block_txt) if P.practicing: progress_txt += "\n(This is a practice block)" progress_msg = message(progress_txt, align='center', blit_txt=False) fill() blit(progress_msg, 5, P.screen_c) flip() any_key() if self.search_type == SPACE: block_type_txt = self.anykey_text.format(self.spatial_instructions) else: block_type_txt = self.anykey_text.format( self.temporal_instructions) block_type_msg = message(block_type_txt, align='left', blit_txt=False) fill() blit(block_type_msg, 5, P.screen_c) flip() any_key()
def prep_stream(self): # Dynamically assign target colouring self.txtm.styles['T1'].color = self.t1_colour self.txtm.styles['T2'].color = self.t2_colour # Generate unique masks for each target self.t1_mask = self.generate_mask() self.t2_mask = self.generate_mask() stream_items = { 't1_target': message(self.t1_identity, align='center', style='T1', blit_txt=False), 't1_mask': self.t1_mask, 't2_target': message(self.t2_identity, align='center', style='T2', blit_txt=False), 't2_mask': self.t2_mask } return stream_items
def block(self): # Present block progress block_txt = "Block {0} of {1}".format(P.block_number, P.blocks_per_experiment) progress_txt = self.anykey_txt.format(block_txt) if P.practicing: progress_txt += "\n(This is a practice block)" progress_msg = message(progress_txt, align='center', blit_txt=False) fill() blit(progress_msg, 5, P.screen_c) flip() any_key() # Inform as to block type if self.block_type == COLOUR: block_type_txt = self.anykey_txt.format(self.colour_instruct) else: block_type_txt = self.anykey_txt.format(self.identity_instruct) block_type_msg = message(block_type_txt, align='center', blit_txt=False) fill() blit(block_type_msg, 5, P.screen_c) flip() any_key()
def block(self): # Show total score following completion of training task if self.total_score: fill() score_txt = "Total block score: {0} points!".format( self.total_score) msg = message(score_txt, 'myText', blit_txt=False) blit(msg, 5, P.screen_c) flip() any_key() self.total_score = 0 # Reset score once presented # Training task if P.practicing: self.block_type = TRAINING # Initialize selection counters self.high_value_trial_count = 0 self.low_value_trial_count = 0 # End of block messaging if not P.practicing: self.block_type = PROBE fill() msg = message(self.end_of_block_txt, 'myText', blit_txt=False) blit(msg, 5, P.screen_c) flip() any_key()
def __init__(self, choices, question, width, origin, order=None): BoundaryInspector.__init__(self) self.q = question self.width = width self.origin = origin if order == None: order = list(choices.keys()) random.shuffle(order) self.order = order self.q_pad = 0.8 * message("ABCDEFG", "normal", blit_txt=False).height x1 = origin[0] - width//2 x2 = origin[0] + width//2 y1 = origin[1] + self.q.height + self.q_pad * 2 self.answers = {} for a in order: txt = message(choices[a], "normal", blit_txt=False, wrap_width=(width-self.q_pad//2), align='center') y2 = y1 + txt.height + self.q_pad bounds = RectangleBoundary(a, (x1, y1), (x2, y2)) self.add_boundary(bounds) self.answers[a] = {'text': txt, 'location': (origin[0], y1), 'height': y2-y1} y1 = y2
def __init__(self, bar, button_text, button_size, location, callback=None): super(Button, self).__init__() super(EnvAgent, self).__init__() self.bar = bar self.size = button_size self.button_text = button_text self.button_rtext_a = message(button_text, "button_active", blit_txt=False) self.button_rtext_i = message(button_text, "button_inactive", blit_txt=False) self.frame_i = Rectangle(button_size[0], button_size[1], fill=None, stroke=(5, (255, 255, 255))) self.frame_a = Rectangle(button_size[0], button_size[1], fill=None, stroke=(5, (150, 255, 150))) self.active = False self.location = location self.text_location = (self.location[0] + self.size[0] // 2, self.location[1] + self.size[1] // 2) self.create_boundary() self.callback = callback
def feedback(self, response): if self.winning_bandit == HIGH: winning_bandit_loc = self.high_value_location else: winning_bandit_loc = self.low_value_location if response == winning_bandit_loc: points = self.bandit_payout(value=self.winning_bandit) msg = message("You won {0} points!".format(points), "score up", blit_txt=False) else: points = self.penalty # -5 msg = message("You lost 5 points!", "score down", blit_txt=False) self.total_score += points feedback = [points, msg] feedback_exposure = CountDown(self.feedback_exposure_period) while feedback_exposure.counting(): ui_request() fill() blit(feedback[1], location=P.screen_c, registration=5) flip() return feedback[0]
def block(self): # Block type defaults to probe trials, overidden in practice block(s) self.block_type = PROBE # Show total score following completion of bandit task if self.total_score: fill() score_txt = "Total block score: {0} points!".format( self.total_score) msg = message(score_txt, 'timeout', blit_txt=False) blit(msg, 5, P.screen_c) flip() any_key() self.total_score = 0 # Reset score once presented # Bandit task if P.practicing: self.block_type == BANDIT # Initialize selection counters self.times_selected_high = 0 self.time_selected_low = 0 # End of block messaging if not P.practicing: self.block_type == PROBE fill() msg = message(self.end_of_block_txt, blit_txt=False) blit(msg, 5, P.screen_c) flip() any_key()
def feedback(self, response): correct_response = True if response == self.tilt_line_location else False # Every 5 trials of a particular payoff, ask anticipated earnings if self.potential_payoff == HIGH: self.high_value_trial_count += 1 if self.high_value_trial_count in [5, 10, 15]: self.query_learning(HIGH) else: self.low_value_trial_count += 1 if self.low_value_trial_count in [5, 10, 15]: self.query_learning(LOW) # Determine payout for trial if correct_response & (self.winning_trial == YES): points = self.payout() msg = message("You won {0} points!".format(points), 'myText', blit_txt=False) else: points = self.penalty msg = message("You lost 5 points!", 'myText', blit_txt=False) # Keep tally of score self.total_score += points feedback = [points, msg] # Present score feedback_exposure = CountDown(self.feedback_exposure_period) fill() blit(feedback[1], location=P.screen_c, registration=5) flip() while feedback_exposure.counting(): ui_request() return feedback[0]
def block(self): # Show block message at start of every block header = "Block {0} of {1}".format(P.block_number, P.blocks_per_experiment) if P.practicing: header = "This is a practice block. ({0})".format(header) practice_msg = "During this block you will be given feedback for your responses." msg = message(header + "\n" + practice_msg, align="center", blit_txt=False) else: msg = message(header, blit_txt=False) message_interval = CountDown(1) while message_interval.counting(): ui_request() # Allow quitting during loop fill() blit(msg, 8, (P.screen_c[0], P.screen_y * 0.4)) flip() flush() start_msg = message("Press any key to start.", blit_txt=False) fill() blit(msg, 8, (P.screen_c[0], P.screen_y * 0.4)) blit(start_msg, 5, [P.screen_c[0], P.screen_y * 0.6]) flip() any_key()
def wheel_callback(self, wheel): # Hide cursor during selection phase hide_mouse_cursor() # Response request msg colour_request_msg = self.t1_col_request if wheel == self.t1_wheel else self.t2_col_request message_offset = deg_to_px(1.5) message_loc = (P.screen_c[0], (P.screen_c[1] - message_offset)) fill() # Present appropriate wheel if wheel == self.t1_wheel: blit(self.t1_wheel, registration=5, location=P.screen_c) else: blit(self.t2_wheel, registration=5, location=P.screen_c) # Present response request message(colour_request_msg, location=message_loc, registration=5, blit_txt=True) # Present annulus drawbject as cursor blit(self.cursor, registration=5, location=mouse_pos()) flip()
def calibrate(self): """Determines the loudness threshold for vocal responses based on sample input from the participant. During calibration, input levels are monitored during three 3-second intervals in which participants are asked to make a single vocal response. After all three samples are collected, the threshold is set to the smallest peak value of the three samples, and the participant is prompted to make one more response to see if it passes the threshold. If it does, calibration is complete and will end after any key is pressed. If it doesn't, the participant will be notified that calibration wasn't sucessful and will be prompted to press 'c' to calibrate again, or 'v' to try validation again. As a convenience for programmers writing and testing experiments using audio input, if KLibs is in development mode and the Params option 'dm_auto_threshold' is set to True, this calibration process will be skipped for a quicker one requiring no user input. In this mode, the ambient room noise is recorded for one second after a countdown, and the threshold is then set to be five times the average peak volume from that interval. This will not work if your microphone does not pick up any ambient room noise. Returns: int: an integer from 1 to 32767 representing the threshold value to use for vocal responses. Raises: RuntimeError: If using auto thresholding and the recorded ambient noise level is 0. """ if not self.stream: self.stream = self.exp.audio.stream if P.development_mode and P.dm_auto_threshold: ambient = self.get_ambient_level() if ambient == 0: e = ( "Ambient level appears to be zero, increase the gain on your microphone or " "disable auto-thresholding.") raise RuntimeError(e) elif ambient * 5 > 32767: e = ( "Ambient noise level too high to use auto-thresholding. Reduce the gain on " "your microphone or try and reduce the noise level in the room." ) raise RuntimeError(e) self.threshold = ambient * 5 else: peaks = [] for i in range(0, 3): msg = "Provide a normal sample of your intended response." peaks.append(self.get_peak_during(3, msg)) if i < 2: s = "" if i == 1 else "s" # to avoid "1 more samples" next_message = ("Got it! {0} more sample{1} to collect. " "Press any key to continue".format( 2 - i, s)) fill() message(next_message, location=P.screen_c, registration=5) flip() any_key() self.threshold = min(peaks) self.__validate() return self.threshold
def present_target(self): msg = "This is your target!" msg_loc = [P.screen_c[0], (P.screen_c[1] - deg_to_px(2))] fill() message(msg, location=msg_loc, registration=5) blit(self.target_item, location=P.screen_c, registration=5) flip()
def anykey_msg(self, msg): msg += "\n\n{press any key to continue}" fill() message(msg, location=P.screen_c, registration=5, align='center', blit_txt=True) flip() any_key()
def _init_probe(self, probetype): p_origin = (P.screen_c[0], P.screen_x // 10) if probetype == 'christoff2009': q = ("What was your attention focused on just before the probe?\n" "1 (on-task) - 7 (off-task)") title = message(q, "title", align='center', blit_txt=False) return LikertProbe(1, 7, title, int(P.screen_x * 0.6), p_origin) elif probetype == 'killingsworth2010': q = "Are you thinking about something other than\nwhat you're currently doing?" responses = { 'on_task': "No", 'mw_pleasant': "Yes, something pleasant", 'mw_neutral': "Yes, something neutral", 'mw_unpleasant': "Yes, something unpleasant" } order = ['on_task', 'mw_pleasant', 'mw_neutral', 'mw_unpleasant'] title = message(q, "title", align='center', blit_txt=False) return ThoughtProbe(responses, title, int(P.screen_x * 0.6), p_origin, order) elif probetype == 'mason2007': q = "Were you just having an irrelevant thought?\n\n" responses = { 'irrelevant': "Yes", 'relevant': "No", } order = ['irrelevant', 'relevant'] title = message(q, "title", align='center', blit_txt=False) return ThoughtProbe(responses, title, int(P.screen_x * 0.6), p_origin, order) elif probetype == 'mcvay2009': q = "What were you just thinking about?" responses = { 'task': "The task", 'performance': "Task experience/performance", 'everyday': "Everyday stuff", 'currentstate': "Current state of being", 'worries': "Personal worries", 'daydreams': "Daydreams", 'other': "Other" } order = [ 'task', 'performance', 'everyday', 'currentstate', 'worries', 'daydreams', 'other' ] title = message(q, "title", align='center', blit_txt=False) return ThoughtProbe(responses, title, int(P.screen_x * 0.6), p_origin, order) elif probetype == 'mrazek2013': q = ("To what extent was your attention focused on the task\n" "or to task-unrelated concerns?") title = message(q, "title", align='center', blit_txt=False) return LikertProbe(1, 5, title, int(P.screen_x * 0.45), p_origin)
def __init__(self, y_pos, bar_length, bar_height, handle_radius, bar_fill, handle_fill): BoundaryInspector.__init__(self) EnvAgent.__init__(self) self.boundaries = {} self.pos = (P.screen_c[0] - bar_length // 2, y_pos) # upper-left self.message_pos = (P.screen_c[0], y_pos - 50) self.__handle_pos = (self.pos[0], self.pos[1] + bar_height // 2) self.handle_color = handle_fill self.handle_radius = handle_radius self.handle_stroke = None self.handle_boundary = None self.bar = None self.bar_size = (bar_length, bar_height) self.bar_color = bar_fill self.bar_stroke = None self.show_increment_ticks = True self.show_increment_text = False self.increment_count = None self.increments = [] self.increment_by = 1 self.increment_surfs = {} self.lower_bound = None self.upper_bound = None self.handle = Ellipse(self.handle_radius * 2, fill=self.handle_color, stroke=self.handle_stroke) self.bar = Rectangle(self.bar_size[0], self.bar_size[1], fill=self.bar_color, stroke=self.bar_stroke) self.add_boundary("handle", [ (self.pos[0] + self.handle_radius, self.pos[1]), self.handle_radius ], CIRCLE_BOUNDARY) self.msg = message("How many corners did the dot traverse?", "default", blit_txt=False) self.lb_msg = None self.ub_msg = None self.ok_text = message("OK", blit_txt=False) self.ok_inactive_button = Rectangle(100, 50, stroke=(1, (255, 255, 255)), fill=(125, 125, 125)).render() self.ok_active_button = Rectangle(100, 50, stroke=(1, (255, 255, 255)), fill=(5, 175, 45)).render() self.button_active = False self.button_pos = (P.screen_c[0], y_pos + bar_height + 50) button_upper_left = (self.button_pos[0] - 50, self.button_pos[1] - 25) button_botton_right = (self.button_pos[0] + 50, self.button_pos[1] + 25) self.add_boundary("button", (button_upper_left, button_botton_right), RECT_BOUNDARY) self.response = None
def block(self): if not P.practicing: if self.search_type == SPACE: self.condition = self.spatial_conditions_exp.pop() else: self.condition = self.temporal_conditions_exp.pop() else: self.condition = self.practice_conditions.pop() self.target_distractor, self.distractor_distractor = self.condition self.target_tilt = random.randint(0, 179) self.target_item = Rectangle(self.item_size, self.item_thickness, fill=WHITE, rotation=self.target_tilt) self.create_stimuli() if not self.general_instruct_shown: self.general_instruct_shown = True general_text = self.anykey_text.format(self.general_instructions) general_msg = message(general_text, align='left', blit_txt=False) fill() blit(general_msg, 5, P.screen_c) flip() any_key() block_txt = "Block {0} of {1}".format(P.block_number, P.blocks_per_experiment) progress_txt = self.anykey_text.format(block_txt) if P.practicing: progress_txt += "\n(This is a practice block)" progress_msg = message(progress_txt, align='center', blit_txt=False) fill() blit(progress_msg, 5, P.screen_c) flip() any_key() if self.search_type == SPACE: block_type_txt = self.anykey_text.format(self.spatial_instructions) else: block_type_txt = self.anykey_text.format( self.temporal_instructions) block_type_msg = message(block_type_txt, align='left', blit_txt=False) fill() blit(block_type_msg, 5, P.screen_c) flip() any_key()
def trial(self): while self.evm.before('cue_on'): self.wait_time() self.display_refresh(cue=True) while self.evm.before('cue_off'): self.wait_time() self.display_refresh() while self.evm.before('target_on'): self.wait_time() flush() self.display_refresh(target=True) if P.saccade_response_cond: self.record_saccades() keypress_rt = 'NA' if P.keypress_response_cond: self.rc.collect() keypress_rt = self.rc.keypress_listener.response(rt=True, value=False) clear() smart_sleep(1000) if P.keypress_response_cond: if self.target_location == "catch" and keypress_rt != TIMEOUT: fill() message(self.err_msgs['early'], registration=5, location=P.screen_c) flip() any_key() elif self.moved_eyes_during_rc: fill() message("Moved eyes during response interval!", registration=5, location=P.screen_c) flip() any_key() return { "block_num": P.block_number, "trial_num": P.trial_number, 'session_type': 'saccade' if P.saccade_response_cond else 'keypress', 'box_alignment': self.box_alignment, 'cue_location': self.cue_location, 'target_location': self.target_location, 'target_acquired': str(self.target_acquired).upper() if P.saccade_response_cond else NA, 'keypress_rt': keypress_rt if P.keypress_response_cond else NA, 'moved_eyes': str(self.moved_eyes_during_rc).upper() if P.keypress_response_cond else NA }
def prep_stream(self, block): # To be populated & returned stream_items = [] # Set font colouring for targets (only used w/n COLOUR blocks) self.txtm.styles['T1Col'].color = self.t1_colour self.txtm.styles['T2Col'].color = self.t2_colour # For IDENTITY streams, targets=digits & distractors=letters. # All are uniformly coloured (gray) if block == IDENTITY: # Stream length is such that 6 items are always presented subsequent to T2 for i in range(0, self.t2_time + 6): # Insert targets @ their respective positions if i == self.t1_time: stream_items.append( message(self.t1_identity, align='center', style='stream', blit_txt=False)) elif i == self.t2_time: stream_items.append( message(self.t2_identity, align='center', style='stream', blit_txt=False)) # Populate remaining positions w/ distractors (randomly sampled) else: stream_items.append( random.choice(self.letters_rendered.values())) # For COLOUR streams, targets & distractors are digits. # Targets are randomly coloured, distractors are gray else: for i in range(0, self.t2_time + 6): if i == self.t1_time: stream_items.append( message(self.t1_identity, align='center', style='T1Col', blit_txt=False)) elif i == self.t2_time: stream_items.append( message(self.t2_identity, align='center', style='T2Col', blit_txt=False)) else: stream_items.append( random.choice(self.numbers_rendered.values())) # Return stream return stream_items
def present_feedback(self): fill() message("Incorrect!", location=P.screen_c, registration=5, blit_txt=True) flip() feedback_period_cd = CountDown(0.5) # seconds while feedback_period_cd.counting(): ui_request()
def prep_stream(self): # Prepare unique masks for each target self.t1_mask = self.generate_mask() self.t2_mask = self.generate_mask() stream_items = { 't1_target': message(self.t1_identity, align='center', blit_txt=False), 't1_mask': self.t1_mask, 't2_target': message(self.t2_identity, align='center', blit_txt=False), 't2_mask': self.t2_mask } return stream_items
def trial_prep(self): if P.development_mode: print "\ntrial factors" print "======================" fill() msg = "Box Alignment: {0}\nCue Location: {1}\nTarget Location: {2}".format( self.box_alignment, self.cue_location, self.target_location) print msg print "======================" message(msg, registration=5, location=P.screen_c, blit_txt=True) flip() any_key() clear() any_key() self.placeholder = self.construct_placeholder() self.cue = self.construct_cue() self.cue_loc = self.locations[self.cue_location] self.set_box_positions() self.target_trial = False if self.target_location != 'catch': self.target_trial = True self.target_loc = self.get_target_location() self.evm.register_tickets([ ('cue_on', 1000), # Cue appears 1000ms after drift check ('cue_off', 1100), # Cue removed after 100ms ('target_on', 1960), # Target appears 860ms after cue removal ('task_end', 4460) # 2500ms to respond to target before trial aborts ]) # Reset trial flags self.before_target = True self.target_acquired = False self.moved_eyes_during_rc = False self.display_refresh() self.el.drift_correct(fill_color=BLACK, draw_target=EL_FALSE) self.fix.fill = WHITE self.display_refresh() flush()
def block(self): block_num = P.block_number block_count = P.blocks_per_experiment # Display progress messages at start of blocks if block_num > 1: flush() fill() block_msg = "Completed block {0} of {1}. Press any key to continue." block_msg = block_msg.format(block_num - 1, block_count) message(block_msg, registration=5, location=P.screen_c) flip() any_key()
def __verify_session_structures(self): error_strings = { "bad_format": "Response type and feedback type must be separated by a single hyphen.", "bad_condition": ("Response type must be either 'PP' (physical), 'MI' (imagery), " "or 'CC' (control)."), "bad_feedback": ("Feedback type must be one or two characters long, and be " "a combination of the letters 'V', 'R' and / or 'X'."), "bad_trialcount": ("Custom trial counts must be specified in (blocktype, trials) " "format, where 'trials' is a positive integer."), } # Validate specified session structure to use, return informative error if formatted wrong session_num, block_num = (0, 0) e = "Error encountered parsing Block {0} of Session {1} in session structure '{2}' ({3}):" for structure_key, session_structure in P.session_structures.items(): for session in session_structure: session_num += 1 for block in session: block_num += 1 if type(block) in [tuple, list]: if isinstance(block[1], int) and block[1] > 0: err = self.validate_block_condition(block[0]) else: err = "bad_trialcount" else: err = self.validate_block_condition(block) if err: if isinstance(block, tuple): block = list(block) err_txt1 = e.format(block_num, session_num, structure_key, str(block)) err_txt1 += "\n" + error_strings[err] msg1 = message(err_txt1, "error", align="center", blit_txt=False) msg2 = message("Press any key to exit TraceLab.", blit_txt=False) fill() blit(msg1, 2, (P.screen_c[0], P.screen_c[1] - 30)) blit(msg2, 8, P.screen_c) flip() any_key() self.exp.quit()
def block(self): # Determine probe bias for block and generate list of probe locs accordingly if P.block_number > 3: self.probe_bias = "left" nonbiased_loc = "right" else: self.probe_bias = "right" nonbiased_loc = "left" loc_list = [self.probe_bias]*4 + [nonbiased_loc] self.probe_locs = loc_list * int(P.trials_per_block/float(len(loc_list))+1) random.shuffle(self.probe_locs) # At the start of each block, display a start message (block progress if experimental block, # practice message if practice block). After 3000ms, keypress will start first trial. probe_msg = ( "During this block, the colour target will appear more often on the " "{0} and less often on the {1}.".format(self.probe_bias, nonbiased_loc) ) header = "Block {0} of {1}".format(P.block_number, P.blocks_per_experiment) if P.practicing: header = "This is a practice block. ({0})".format(header) if P.block_number > 1: msg = message(header+"\n"+probe_msg, align="center", blit_txt=False) else: msg = message(header, blit_txt=False) message_interval = CountDown(1) while message_interval.counting(): ui_request() # Allow quitting during loop fill() blit(msg, 8, (P.screen_c[0], P.screen_y*0.4)) flip() flush() fill() blit(msg, 8, (P.screen_c[0], P.screen_y*0.4)) message("Press any key to start.", registration=5, location=[P.screen_c[0], P.screen_y*0.6]) flip() any_key() # When running participants, send halfway point and last-block notifications to researcher via Slack if not P.development_mode: if P.block_number == 3: # If participant is halfway done slack_message("Halfway done ({0}/{1})".format(P.block_number, P.blocks_per_experiment))
def trial(self): # Clear screen and wait for target onset fill() flip() while self.evm.before('target_on'): ui_request() # Start timer and collect response self.rc.collect() response = self.rc.keypress_listener.response() # Stop timer and show for 1sec after response is made elapsed_msg = message(str(int(response.rt)).zfill(4), style='PVT', blit_txt=False) feedback_timer = CountDown(1) while feedback_timer.counting(): fill() blit(elapsed_msg, 5, P.screen_c) flip() # Log trial data to database return { "block_num": P.block_number, "trial_num": P.trial_number, "isi": self.interstim_interval, "rt": response.rt }
def trial_clean_up(self): # Reset ResponseCollectors self.t1_colouring_rc.color_listener.reset() self.t2_colouring_rc.color_listener.reset() self.t1_identity_rc.keypress_listener.reset() self.t2_identity_rc.keypress_listener.reset() # Switch block type if not P.practicing: if P.trial_number == P.trials_per_block: if P.block_number < P.blocks_per_experiment: if self.block_type == IDENTITY: self.block_type = COLOUR else: self.block_type = IDENTITY else: if P.trial_number == P.trials_per_practice_block: if self.block_type == IDENTITY: self.block_type = COLOUR else: self.block_type = IDENTITY if P.trial_number == P.trials_per_block: break_txt = self.anykey_txt.format("Good work! Take a break") break_msg = message(break_txt, align='center', blit_txt=False) fill() blit(break_msg, registration=5, location=P.screen_c) flip() any_key()
def block(self): if P.block_number == int(math.ceil(P.blocks_per_experiment/2.0))+1: util.flush() msg_text = "Whew! You're halfway done.\nTake a break, then press any key to continue." msg = message(msg_text, align="center", blit_txt=False) fill() blit(msg, registration=5, location=P.screen_c) flip() any_key()