def trial_prep(self): # Clear the screen of stimuli before the trial start clear() # Determine image and image name for trial self.image_name = self.trial_factors[P.trial_number-1][0] self.arrangement = self.images[self.image_name] # infer which mask to use and retrieve it self.mask_type = self.trial_factors[P.trial_number-1][1] try: self.mask = self.masks[self.mask_type] except KeyError: self.mask = None # Reset warning signal flag self.first_warning_played = False self.second_warning_played = False #Reset gaze offscreen flag self.gaze_offscreen = time.time() # Display trial start message and perform drift correct after keypress blit(self.trial_start_msg, 5, P.screen_c) flip() any_key() self.el.drift_correct()
def alert(text): '''A convenience function for clearing the screen and displaying an alert message. Will probably be depricated soon. ''' clear() message(text, "alert", blit_txt=True, flip_screen=True)
def __execute_experiment__(self, *args, **kwargs): """For internal use, actually runs the blocks/trials of the experiment in sequence. """ from klibs.KLGraphics import clear if self.blocks == None: self.blocks = self.trial_factory.export_trials() for block in self.blocks: P.recycle_count = 0 P.block_number = self.blocks.i P.practicing = block.practice self.block() P.trial_number = 1 for trial in block: # ie. list of trials try: try: P.trial_id = self.database.last_id_from('trials') + 1 except TypeError: P.trial_id = 1 self.__trial__(trial, block.practice) P.trial_number += 1 except TrialException: block.recycle() P.recycle_count += 1 clear() # NOTE: is this actually wanted? self.rc.reset() self.clean_up() self.incomplete = False if 'session_info' in self.database.table_schemas.keys(): where = {'session_number': P.session_number} self.database.update('session_info', {'complete': True}, where)
def present_temporal_stream(self, temporal_stream): duration_cd = CountDown(ITEM_DURATION, start=False) mask_cd = CountDown(MASK_DURATION, start=False) response_window = CountDown(2, start=False) last_item = True if len(temporal_stream) == 1 else False item = temporal_stream.pop() if item[1]: self.target_onset = self.target_sw.elapsed() duration_cd.start() while duration_cd.counting(): self.blit_img(item[0], reg=5, loc=P.screen_c) mask_cd.start() while mask_cd.counting(): self.blit_img(self.mask, reg=5, loc=P.screen_c) if last_item: clear() response_window.start() while response_window.counting(): fill() flip()
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 screen_refresh(self): position = self.el.gaze() fill() blit(self.figure, 5, P.screen_c) if not position: clear() else: if self.mask is not None: blit(self.mask, 5, position) flip()
def trial(self): # Wait 1s before presenting array while self.evm.before("present_fixation", True): ui_request() self.present_fixation() while self.evm.before("search_onset", True): ui_request() if self.search_type == SPACE: self.present_array() self.spatial_rc.collect() if len(self.spatial_rc.cursor_listener.responses): spatial_located, spatial_rt = self.spatial_rc.cursor_listener.response() else: spatial_located = 'miss' spatial_rt = 'NA' else: try: # the display callback "present_stream()" pops an element each pass; when all targets have been shown this bad boy throws an error self.temporal_rc.collect() except IndexError: self.temporal_responses = self.temporal_rc.mousebutton_listener.responses trial_data = { "block_num": P.block_number, "trial_num": P.trial_number, "search_type": "Spatial", "cell_count": self.cell_count, "target_distractor": self.target_distractor, "distractor_distractor": self.distractor_distractor, } if self.search_type == TIME: for tpt in self.temporal_presentation_times: onset_key = 't{0}_onset'.format(self.temporal_presentation_times.index(tpt)+1) onset_val = tpt[0] dist_count_key = 't{0}_distractor_count'.format(self.temporal_presentation_times.index(tpt)+1) dist_count_val = tpt[1] trial_data[onset_key] = onset_val trial_data[dist_count_key] = dist_count_val else: for i in range(0,15): onset_key = 't{0}_onset'.format(i+1) onset_val = 'NA' dist_count_key = 't{0}_distractor_count'.format(i+1) dist_count_val = 'NA' trial_data[onset_key] = onset_val trial_data[dist_count_key] = dist_count_val return trial_data clear()
def trial(self): while self.evm.before('T1_on', True): ui_request() # Variable delay following trial initiation self.blit_it(self.tmtm_stream['t1_target']) # Blit T1 to screen while self.evm.before('T1_off', True): ui_request() # Wait (conditional duration) self.flip_it() # Remove T1 while self.evm.before('T1_mask_on', True): ui_request() # Wait (ISI; fixed at ~17ms) self.blit_it(self.tmtm_stream['t1_mask']) # Blit M1 to screen while self.evm.before('T1_mask_off', True): ui_request() # Wait (conditional duration) self.flip_it() # Remove M1 while self.evm.before('T2_on', True): ui_request() # Wait (TTOA) self.blit_it(self.tmtm_stream['t2_target']) # Blit T2 to screen while self.evm.before('T2_off', True): ui_request() # Wait (fixed at ~50ms) self.flip_it() # Remove T2 while self.evm.before('T2_mask_on', True): ui_request() # Wait (ISI; fixed at ~17ms) self.blit_it(self.tmtm_stream['t2_mask']) # Blit M2 to screen while self.evm.before('T2_mask_off', True): ui_request() # Wait (fixed at ~50ms) self.flip_it() # Remove M2 self.t1_rc.collect() # Request T1 identity self.t2_rc.collect() # Request T2 identity # Save responses t1_response = self.t1_rc.keypress_listener.response(rt=False) t2_response = self.t2_rc.keypress_listener.response(rt=False) # Clear remaining stimuli from screen clear() # Log trial factors & responses return { "block_num": P.block_number, "trial_num": P.trial_number, "practicing": str(P.practicing), "isoa": self.isoa, "isi": self.isi, "ttoa": self.ttoa, "t1_difficulty": self.t1_difficulty, "t1_duration": self.t1_duration, "m1_duration": self.m1_duration, "t2_duration": self.t2_duration, "m2_duration": self.m2_duration, "t1_identity": self.t1_identity, "t2_identity": self.t2_identity, "t1_response": t1_response, "t2_response": t2_response }
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 trial(self): while self.evm.before("present_fixation", True): ui_request() self.blit_img(self.fixation, 5, P.screen_c) while self.evm.before("search_onset", True): ui_request() if self.search_type == SPACE: self.rc.collect() else: try: self.target_onset = 'NA' self.target_sw = Stopwatch() self.rc.collect() except IndexError: pass if len(self.rc.keypress_listener.responses): response, rt = self.rc.keypress_listener.response() if response != self.present_absent: self.present_feedback() else: response, rt = 'None', 'NA' clear() return { "practicing": str(P.practicing), "block_num": P.block_number, "trial_num": P.trial_number, "search_type": self.search_type, "stimulus_type": "LINE" if P.condition == 'line' else "COLOUR", "present_absent": self.present_absent, "set_size": self.set_size if self.search_type == SPACE else 'NA', "target_distractor": self.target_distractor, "distractor_distractor": self.distractor_distractor, "target_onset": self.target_onset if self.search_type == TIME else 'NA', "response": response, "rt": rt, "error": str(response != self.present_absent) }
def trial(self): """ trial_factors: 1 = mask_type, 2 = target_level, 3 = mask_size, 4 = target_shape] """ if P.development_mode: print(self.mask_type, self.target_level, self.mask_size, self.target_shape) self.rc.collect() resp = self.rc.keypress_listener.response() if P.development_mode: print(resp) # handle timeouts if resp.rt == TIMEOUT: feedback = CountDown(1) msg = message("Too slow!", "alert", blit_txt=False) while feedback.counting(): ui_request() fill() blit(msg, 5, P.screen_c) flip() clear() # create readable data as fixation is currrently in (x,y) coordinates if self.fixation == self.fixation_top: initial_fixation = "TOP" elif self.fixation == self.fixation_central: initial_fixation = "CENTRAL" else: initial_fixation = "BOTTOM" return {"practicing": P.practicing, "response": resp.value, "rt": float(resp.rt), "mask_type": self.mask_type, "mask_size": self.mask_size, "local": self.target_shape if self.target_level == LOCAL else "D", "global": self.target_shape if self.target_level == GLOBAL else "D", "d_orientation": self.orientation, "trial_num": P.trial_number, "block_num": P.block_number, "initial_fixation": initial_fixation}
def trial(self): hide_mouse_cursor() while self.evm.before('cue_on'): ui_request() self.display_refresh(cue=self.cue_type, tone=self.tone_trial) while self.evm.before('cue_off'): ui_request() self.display_refresh() while self.evm.before('target_on'): ui_request() self.rc.collect() if self.rc.keypress_listener.response_count != 0: response, rt = self.rc.keypress_listener.response() else: response, rt = NA, NA self.present_feedback(rt=rt, response=response) clear() return { "block_num": P.block_number, "trial_num": P.trial_number, "practicing": str(P.practicing), 'cue_type': self.cue_type, 'ctoa': self.ctoa, 'target_loc': self.target_loc, 'target_side': self.target_side, 'tone_trial': str(self.tone_trial), 'response': response, 'rt': rt }
def __generate_stimuli(self): clear() msg = message("Generating stimuli...", "q_and_a", blit_txt=False) blit(msg, 5, P.screen_c) flip() stimuli_labels = [[(False, 0), (CIRCLE, 0)], [(False, 90), (CIRCLE, 0)], [(False, 180), (CIRCLE, 0)], [(False, 270), (CIRCLE, 0)], [(False, 0), (SQUARE, 0)], [(False, 90), (SQUARE, 0)], [(False, 180), (SQUARE, 0)], [(False, 270), (SQUARE, 0)], [(CIRCLE, 0), (False, 0)], [(CIRCLE, 0), (False, 90)], [(CIRCLE, 0), (False, 180)], [(CIRCLE, 0), (False, 270)], [(SQUARE, 0), (False, 0)], [(SQUARE, 0), (False, 90)], [(SQUARE, 0), (False, 180)], [(SQUARE, 0), (False, 270)]] for sl in stimuli_labels: stim = self.render_texture(sl[1][0], sl[1][1]) figure = self.render_figure(sl[0][0], sl[0][1]) stim.putalpha(figure) stim = aggdraw_to_numpy_surface(stim) fig_text = sl[0][0] if sl[0][0] in (CIRCLE, SQUARE) else "D_%s" % sl[0][1] texture_text = sl[1][0] if sl[1][0] in (CIRCLE, SQUARE) else "D_%s" % sl[1][1] self.stimuli["{0}_{1}".format(fig_text, texture_text)] = stim.render()
def trial_prep(self): clear() # choose randomly varying parts of trial self.orientation = random.choice(self.orientations) self.fixation = tuple(random.choice(self.exp_meta_factors['fixation'])) # infer which mask & stim to use and retrieve them self.figure = self.target_shape if self.target_level == LOCAL else False if self.figure: stim_label = "{0}_D_{1}".format(self.target_shape, self.orientation) else: stim_label = "D_{0}_{1}".format(self.orientation, self.target_shape) self.figure = self.stimuli[stim_label] self.mask_label = "{0}_{1}".format(self.mask_type, self.mask_size) try: self.mask = self.masks[self.mask_label] except KeyError: self.mask = None # for the no mask condition, easier than creating empty keys in self.masks blit(self.trial_start_msg, 5, P.screen_c) flip() any_key() self.el.drift_correct(self.fixation)
def __generate_masks(self): smaller_than_screen = True while smaller_than_screen: self.maximum_mask_size += 1 new_max_mask_px = deg_to_px(self.maximum_mask_size) + self.mask_blur_width * 4 + 2 if new_max_mask_px > P.screen_y: smaller_than_screen = False self.maximum_mask_size -= 1 for size in self.trial_factory.exp_factors['mask_size']: if size > self.maximum_mask_size: e_str = "The maximum mask size this monitor can support is {0} degrees.".format(self.maximum_mask_size) raise ValueError(e_str) clear() msg = message("Rendering masks...", "q_and_a", blit_txt=False) blit(msg, 5, P.screen_c) flip() self.masks = {} for size in self.trial_factory.exp_factors['mask_size']: ui_request() self.masks["{0}_{1}".format(CENTRAL, size)] = self.render_mask(size, CENTRAL).render() self.masks["{0}_{1}".format(PERIPHERAL, size)] = self.render_mask(size, PERIPHERAL).render()
def trial(self): # Wait 1s before presenting array while self.evm.before("present_fixation", True): ui_request() self.present_fixation() while self.evm.before("search_onset", True): ui_request() if self.search_type == SPACE: self.present_array() self.spatial_rc.collect() if len(self.spatial_rc.keypress_listener.responses): spatial_response, spatial_rt = self.spatial_rc.keypress_listener.response( ) if spatial_response != self.present_absent: self.present_feedback() else: spatial_response = "None" spatial_rt = 'NA' else: try: self.response_sw = Stopwatch( ) # Used as RT stopwatch in cases where responses are made after stream has ended self.stream_sw = Stopwatch( ) # Records duration of stream, just in case it becomes handy to have self.target_sw = Stopwatch( ) # Records time that target is presented, again just in case. # the display callback "present_stream()" pops an element each pass; when all targets have been shown this bad boy throws an error self.temporal_pre_rc.collect() except IndexError: pass # Pause once stream has ended self.stream_sw.pause() if len(self.temporal_pre_rc.keypress_listener.responses): temporal_response, temporal_rt = self.temporal_pre_rc.keypress_listener.response( ) else: self.temporal_post_rc.collect() if len(self.temporal_post_rc.keypress_listener.responses): temporal_rt = self.response_sw.elapsed( ) * 1000 # Rescale RT to ms and log temporal_response = self.temporal_post_rc.keypress_listener.response( rt=False) else: temporal_response = "None" temporal_rt = "NA" if temporal_response != self.present_absent: self.present_feedback() clear() return { "practicing": str(P.practicing), "block_num": P.block_number, "trial_num": P.trial_number, "search_type": self.search_type, "stimulus_type": 'LINE', "present_absent": self.present_absent, "set_size": self.set_size if self.search_type == SPACE else 'NA', "target_distractor": self.target_distractor, "distractor_distractor": self.distractor_distractor, "target_time": self.target_time if self.search_type == TIME else "NA", "stream_duration": self.stream_sw.elapsed() if self.search_type == TIME else "NA", "target_onset": self.target_onset if self.search_type == TIME else "NA", "spatial_response": spatial_response if self.search_type == SPACE else "NA", "spatial_rt": spatial_rt if self.search_type == SPACE else "NA", "temporal_response": temporal_response if self.search_type == TIME else "NA", "temporal_rt": temporal_rt if self.search_type == TIME else "NA" }
def trial(self): # Hide cursor during trial hide_mouse_cursor() # Present fixation & wait 1s before presenting RSVP stream self.present_fixation() while self.evm.before('stream_on', True): pass # Present RSVP stream self.present_stream() # For 'identity' blocks, request targets' numerical identity if self.block_type == IDENTITY: # Collect responses self.t1_identity_rc.collect() self.t2_identity_rc.collect() # Assign to return variables t1_id_response, t1_id_rt = self.t1_identity_rc.keypress_listener.response( ) t2_id_response, t2_id_rt = self.t2_identity_rc.keypress_listener.response( ) t1_response_err, t1_response_err_rt, t2_response_err, t2_response_err_rt = [ 'NA', 'NA', 'NA', 'NA' ] # For 'colour' blocks, request targets' colouring else: self.t1_colouring_rc.collect() self.t2_colouring_rc.collect() t1_response_err, t1_response_err_rt = self.t1_colouring_rc.color_listener.response( ) t2_response_err, t2_response_err_rt = self.t2_colouring_rc.color_listener.response( ) t1_id_response, t1_id_rt, t2_id_response, t2_id_rt = [ 'NA', 'NA', 'NA', 'NA' ] return { "block_num": P.block_number, "trial_num": P.trial_number, "block_type": self.block_type, "t1_time": self.t1_time, "t2_time": self.t2_time, "lag": self.lag, "t1_identity": self.t1_identity, "t2_identity": self.t2_identity, "t1_identity_response": t1_id_response, "t1_identity_rt": t1_id_rt, "t2_identity_response": t2_id_response, "t2_identity_rt": t2_id_rt, "t1_colour": self.t1_colour, "t2_colour": self.t2_colour, "t1_ang_err": t1_response_err, "t1_ang_err_rt": t1_response_err_rt, "t2_ang_err": t2_response_err, "t2_ang_err_rt": t2_response_err_rt, "t1_wheel_rotation": self.t1_wheel.rotation, "t2_wheel_rotation": self.t2_wheel.rotation } # Clear remaining stimuli from screen clear()
def trial(self): # BANDIT TRIAL if P.practicing: cotoa, probe_rt = ['NA', 'NA'] # Don't occur in bandit blocks # Present placeholders while self.evm.before('target_on', True) and not self.err: self.confirm_fixation() self.present_neutral_boxes() flip() # BANDIT RESPONSE PERIOD self.targets_shown = True # After bandits shown, don't recycle trial # Present bandits and listen for response self.bandit_rc.collect() # If wrong response made if self.err: bandit_choice, bandit_rt, reward = ['NA', 'NA', 'NA'] else: self.err = 'NA' # Retrieve responses from ResponseCollector(s) & record data bandit_choice = self.bandit_rc.keypress_listener.response( value=True, rt=False) bandit_rt = self.bandit_rc.keypress_listener.response( value=False, rt=True) if bandit_rt == TIMEOUT: self.show_error_message('bandit_timeout') reward = 'NA' else: # Determine bandit payout & display reward = self.feedback(bandit_choice) # PROBE TRIAL else: bandit_choice, bandit_rt, reward = [ 'NA', 'NA', 'NA' ] # Don't occur in probe trials # Present placeholders & confirm fixation while self.evm.before('target_on', True): self.confirm_fixation() self.present_neutral_boxes() # Present cue if self.evm.between('cue_on', 'cue_off'): if self.cue_location == LEFT: blit(self.thick_rect, 5, self.left_box_loc) else: blit(self.thick_rect, 5, self.right_box_loc) # Present cueback elif self.evm.between('cue_off', 'cueback_off'): blit(self.star_cueback, 5, P.screen_c) flip() # PROBE RESPONSE PERIOD self.targets_shown = True # After probe shown, don't recycle trial # Present probes & listen for response self.probe_rc.collect() # If 'go' trial, check for response if self.go_no_go == GO: # If wrong response made if self.err: probe_rt = 'NA' # If correct response OR timeout else: self.err = 'NA' probe_rt = self.probe_rc.keypress_listener.response( value=False, rt=True) if probe_rt == TIMEOUT: self.show_error_message('probe_timeout') probe_rt = 'NA' # Similarly, for 'nogo' trials else: probe_rt = 'NA' # If response made, penalize if len(self.probe_rc.keypress_listener.responses): self.show_error_message('response_on_nogo') self.err = 'response_on_nogo' # If no response, continue as normal else: self.err = 'NA' # Return trial data return { "block_num": P.block_number, "trial_num": P.trial_number, "block_type": "BANDIT" if P.practicing else "PROBE", "high_value_col": self.high_value_colour[:3] if P.practicing else 'NA', "high_value_loc": self.high_value_location if P.practicing else 'NA', "low_value_col": self.low_value_colour[:3] if P.practicing else 'NA', "low_value_loc": self.low_value_location if P.practicing else 'NA', "winning_trial": self.winning_trial if P.practicing else 'NA', "bandit_selected": self.bandit_selected if P.practicing else 'NA', "bandit_rt": bandit_rt, "reward": reward, "cue_loc": self.cue_location if not P.practicing else 'NA', "cotoa": self.cotoa if not P.practicing else 'NA', "probe_loc": self.probe_location if not P.practicing else 'NA', "probe_col": self.probe_colour if not P.practicing else 'NA', "go_no_go": self.go_no_go if not P.practicing else 'NA', "probe_rt": probe_rt, "err": self.err } # Clear remaining stimuli from screen clear()
def trial(self): if P.development_mode: trial_info = ( "\ntrial_type: '{0}', high_val_loc: '{1}', probe_loc: '{2}', " "cue_loc: '{3}', winning_bandit: '{4}'") print( trial_info.format(self.trial_type, self.high_value_location, self.probe_location, self.cue_location, self.winning_bandit)) while self.evm.before('target_on', True) and not self.err: self.confirm_fixation() self.present_neutral_boxes() if self.evm.between('cue_on', 'cue_off'): if self.cue_location in [LEFT, DOUBLE]: blit(self.thick_rect, 5, self.left_box_loc) if self.cue_location in [RIGHT, DOUBLE]: blit(self.thick_rect, 5, self.right_box_loc) elif self.evm.between('cue_off', 'cueback_off'): blit(self.star_cueback, 5, P.screen_c) flip() self.targets_shown = True # after bandits or probe shown, don't recycle trial on user error if self.trial_type in [BANDIT, BOTH] and not self.err: while self.evm.before('nogo_end') and not self.err: if key_pressed(): self.show_error_message('too_soon') self.err = "early_response" break self.confirm_fixation() self.bandit_callback(before_go=True) flip() # PROBE RESPONSE PERIOD if self.trial_type in [PROBE, BOTH] and not self.err: self.probe_rc.collect() if not self.err: if len(self.probe_rc.keypress_listener.responses): self.show_error_message('wrong_response') self.err = 'keypress_on_probe' elif len(self.probe_rc.audio_listener.responses) == 0: self.show_error_message('probe_timeout') if self.probe_rc.audio_listener.stream_error: self.err = 'microphone_error' else: self.err = 'probe_timeout' # BANDIT RESPONSE PERIOD if self.trial_type in [BANDIT, BOTH] and not self.err: self.bandit_rc.collect() if self.trial_type == BANDIT and P.ignore_vocal_for_bandits == False: if len(self.bandit_rc.audio_listener.responses): self.show_error_message('wrong_response') self.err = 'vocal_on_bandit' # Retrieve collected response data before logging to database if self.err: bandit_choice, bandit_rt, reward = ['NA', 'NA', 'NA'] probe_rt = 'NA' else: self.err = 'NA' # Retreive responses from RepsponseCollector(s) and record data if self.trial_type in [BANDIT, BOTH]: bandit_choice = self.bandit_rc.keypress_listener.response( value=True, rt=False) bandit_rt = self.bandit_rc.keypress_listener.response( value=False, rt=True) if bandit_rt == TIMEOUT: self.show_error_message('bandit_timeout') reward = 'NA' else: # determine bandit payout (reward) and display feedback to participant reward = self.feedback(bandit_choice) else: bandit_choice, bandit_rt, reward = ['NA', 'NA', 'NA'] if self.trial_type in [PROBE, BOTH]: probe_rt = self.probe_rc.audio_listener.response(value=False, rt=True) else: probe_rt = 'NA' # Clear any remaining stimuli from screen before trial end clear() return { "block_num": P.block_number, "trial_num": P.trial_number, "trial_type": self.trial_type, "cue_loc": self.cue_location, "cotoa": self.cotoa, "high_value_col": self.high_value_color[:3] if self.trial_type != PROBE else "NA", "low_value_col": self.low_value_color[:3] if self.trial_type != PROBE else "NA", "high_value_loc": self.high_value_location if self.trial_type != PROBE else "NA", "winning_bandit": self.winning_bandit if self.trial_type != PROBE else "NA", "bandit_choice": bandit_choice, "bandit_rt": bandit_rt, "reward": reward, "probe_loc": self.probe_location if self.trial_type != BANDIT else "NA", "probe_rt": probe_rt, "err": self.err }
def trial(self): # Wait 1s before presenting array while self.evm.before("present_fixation", True): ui_request() self.present_fixation() while self.evm.before("search_onset", True): ui_request() if self.search_type == SPACE: self.present_array() self.spatial_rc.collect() if len(self.spatial_rc.keypress_listener.responses): spatial_response, spatial_rt = self.spatial_rc.keypress_listener.response( ) if spatial_response != self.present_absent: self.present_feedback() else: spatial_response = "None" spatial_rt = 'NA' else: try: self.response_sw = Stopwatch() self.stream_sw = Stopwatch() self.target_sw = Stopwatch() # the display callback "present_stream()" pops an element each pass; when all targets have been shown this bad boy throws an error self.temporal_pre_rc.collect() except IndexError: pass self.stream_sw.pause() if len(self.temporal_pre_rc.keypress_listener.responses): temporal_response, temporal_rt = self.temporal_pre_rc.keypress_listener.response( ) else: self.temporal_post_rc.collect() if len(self.temporal_post_rc.keypress_listener.responses): temporal_response = self.temporal_post_rc.keypress_listener.response( rt=False) temporal_rt = self.response_sw.elapsed() * 1000 else: temporal_response = "None" temporal_rt = "NA" if temporal_response != self.present_absent: self.present_feedback() clear() return { "practicing": str(P.practicing), "block_num": P.block_number, "trial_num": P.trial_number, "search_type": self.search_type, "stimulus_type": 'COLOR', "present_absent": self.present_absent, "set_size": self.set_size if self.search_type == SPACE else "NA", "target_distractor": self.target_distractor, "distractor_distractor": self.distractor_distractor, "target_time": self.target_time if self.search_type == TIME else "NA", "stream_duration": self.stream_sw.elapsed() if self.search_type == TIME else "NA", "target_onset": self.target_onset if self.search_type == TIME else "NA", "spatial_response": spatial_response if self.search_type == SPACE else "NA", "spatial_rt": spatial_rt if self.search_type == SPACE else "NA", "temporal_response": temporal_response if self.search_type == TIME else "NA", "temporal_rt": temporal_rt if self.search_type == TIME else "NA" }
def trial(self): while self.evm.before("cross fix end"): self.jc_wait_time() self.display_refresh(self.start_axis, self.cross_w) while self.evm.before("circle fix end"): self.jc_wait_time() self.display_refresh(self.start_axis, self.circle) while self.evm.before("cue end"): self.jc_wait_time() self.display_refresh(self.start_axis, self.circle, cue=self.cue_location) while self.evm.before("circle box end"): self.jc_wait_time() self.display_refresh(self.start_axis, self.circle) current_frame = 0 while self.evm.before("animation end"): self.jc_wait_time() if self.animation_trial: if current_frame < self.animation_frames: if self.evm.trial_time_ms > ( current_frame * self.frame_duration + 1600): box_locs = self.frames[self.start_axis][ self.rotation_dir][current_frame] self.display_refresh(box_locs, self.asterisk) current_frame += 1 else: self.display_refresh(self.start_axis, self.asterisk) while self.evm.before("asterisk end"): self.display_refresh(self.box_axis_during_target(), self.circle) self.jc_wait_time() flush() self.display_refresh(self.box_axis_during_target(), self.circle, target=self.target_location) if P.saccade_response_cond: self.jc_saccade_data() 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 == "none" 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', "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": str(self.animation_trial).upper(), "target_acquired": str(self.target_acquired).upper() if P.saccade_response_cond else NA, "keypress_rt": keypress_rt, "moved_eyes": str(self.moved_eyes_during_rc).upper() if P.keypress_response_cond else NA }
def trial(self): # Hide cursor during trial hide_mouse_cursor() # Wait some foreperiod before presenting T1 while self.evm.before('T1_on', True): ui_request() # Present T1 fill() blit(self.tmtm_stream['t1_target'], registration=5, location=P.screen_c) flip() self.t1_sw = Stopwatch() # Don't do anything during T1 presentation while self.evm.before('T1_off', True): ui_request() self.t1_isi_sw = Stopwatch() # Remove T1 fill() flip() self.t1_sw.pause() print("T1 duration actual: " + str(self.t1_sw.elapsed())) fill() flip() while self.evm.before('T1_mask_on', True): ui_request() self.t1_isi_sw.pause() print("ISI actual: " + str(self.t1_isi_sw.elapsed())) # After one refresh rate (how long it takes to remove T1) present mask fill() blit(self.tmtm_stream['t1_mask'], registration=5, location=P.screen_c) flip() self.t1_mask_sw = Stopwatch() # Don't do anything during presentation while self.evm.before('T1_mask_off', True): ui_request() # Remove mask fill() flip() self.t1_mask_sw.pause() print("T1 mask duration actual: " + str(self.t1_mask_sw.elapsed())) # If not practicing, present T2 if not P.practicing: # After TTOA is up, present T2 while self.evm.before('T2_on', True): ui_request() fill() blit(self.tmtm_stream['t2_target'], registration=5, location=P.screen_c) flip() self.t2_sw = Stopwatch() # Don't do anything during presentation while self.evm.before('T2_off', True): ui_request() self.t2_isi_sw = Stopwatch() # Remove T2 fill() flip() self.t2_sw.pause() fill() flip() while self.evm.before('T2_mask_on', True): ui_request() self.t2_isi_sw.pause() # After one refresh rate, present mask fill() blit(self.tmtm_stream['t2_mask'], registration=5, location=P.screen_c) flip() self.t2_mask_sw = Stopwatch() # Don't do anything during presentation while self.evm.before('T2_mask_off', True): ui_request() # Remove mask fill() flip() self.t2_mask_sw.pause() # Wait 1/3 second before asking for responses while self.evm.before('response_foreperiod', True): ui_request() # Request & record responses if self.block_type == IDENTITY: # Not relevant to identity trials t1_response_err, t1_response_err_rt, t2_response_err, t2_response_err_rt = [ 'NA', 'NA', 'NA', 'NA' ] # Collect identity responses self.t1_identity_rc.collect() if not P.practicing: self.t2_identity_rc.collect() # Assign to variables returned t1_id_response, t1_id_rt = self.t1_identity_rc.keypress_listener.response( ) # No T2 present during practice if not P.practicing: t2_id_response, t2_id_rt = self.t2_identity_rc.keypress_listener.response( ) else: t2_id_response, t2_id_rt = ['NA', 'NA'] # During practice, keep a tally of T1 performance if P.practicing: if t1_id_response == self.t1_identity: self.t1_performance += 1 else: # Colour block # Not relevant to colour trials t1_id_response, t1_id_rt, t2_id_response, t2_id_rt = [ 'NA', 'NA', 'NA', 'NA' ] # Collect colour responses self.t1_colouring_rc.collect() if not P.practicing: self.t2_colouring_rc.collect() # Assign to variables returned t1_response_err, t1_response_err_rt = self.t1_colouring_rc.color_listener.response( ) # T2 only presented during test blocks if not P.practicing: t2_response_err, t2_response_err_rt = self.t2_colouring_rc.color_listener.response( ) else: t2_response_err, t2_response_err_rt = ['NA', 'NA'] if P.practicing: # As numeric identities have 9 possible values, similarly the colour wheel can # be thought of as having 9 'bins' (each 40º wide). Colour responses are labelled # as 'correct' if their angular error does not exceed 20º in either direction. if (abs(t1_response_err) <= 20): self.t1_performance += 1 clear() print(self.target_duration) print(self.mask_duration) return { "practicing": str(P.practicing), "block_num": P.block_number, "trial_num": P.trial_number, "block_type": self.block_type, "itoa": self.itoa, "ttoa": self.ttoa, "target_duration": self.target_duration, "mask_duration": self.mask_duration, "t1_identity": self.t1_identity, "t2_identity": self.t2_identity if not P.practicing else 'NA', "t1_identity_response": t1_id_response, "t1_identity_rt": t1_id_rt, "t2_identity_response": t2_id_response, "t2_identity_rt": t2_id_rt, "t1_colour": self.t1_colour, "t1_angle": self.t1_angle, "t1_wheel_rotation": self.t1_wheel.rotation, "t2_colour": self.t2_colour if not P.practicing else 'NA', "t2_angle": self.t2_angle if not P.practicing else 'NA', "t2_wheel_rotation": self.t2_wheel.rotation if not P.practicing else 'NA', "t1_ang_err": t1_response_err, "t1_colour_rt": t1_response_err_rt, "t2_ang_err": t2_response_err, "t2_colour_rt": t2_response_err_rt, "t1_performance_practice": self.t1_performance if P.practicing else 'NA', "t1_duration_actual": self.t1_sw.elapsed(), "t1_isi_actual": self.t1_isi_sw.elapsed(), "t1_mask_duration_actual": self.t1_mask_sw.elapsed(), "t2_duration_actual": self.t2_sw.elapsed() if not P.practicing else 'NA', "t2_isi_actual": self.t2_isi_sw.elapsed() if not P.practicing else 'NA', "t2_mask_duration_actual": self.t2_mask_sw.elapsed() if not P.practicing else 'NA' }