def execute(self): self.logger.debug('Starting Copy Phrase Calibration Task!') run = True # get the initial target letter target_letter = self.copy_phrase[0] text_task = '*' # check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color, first_run=True): run = False while run: # check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color): break #Take a break every number of trials defined in parameters.json if self.enable_breaks: #Get number of trials by getting the length of the currently #typed string number_of_trials = len(text_task.replace('*', '')) pause_calibration(self.window, self.rsvp, number_of_trials, self.parameters) # Generate some sequences to present based on parameters (ele_sti, timing_sti, color_sti) = target_rsvp_sequence_generator( self.alp, target_letter, self.parameters, len_sti=self.len_sti, timing=self.timing, is_txt=self.is_txt_sti, color=self.color) # Get task information, seperate from stimuli to be presented (task_text, task_color) = get_task_info(self.num_sti, self.task_info_color) self.rsvp.update_task_state(text=text_task, color_list=['white']) self.rsvp.draw_static() self.window.flip() # update task state self.rsvp.stim_sequence = ele_sti[0] # self.rsvp.text_task = text_task if self.is_txt_sti: self.rsvp.color_list_sti = color_sti[0] self.rsvp.time_list_sti = timing_sti[0] # buffer and execute the sequence core.wait(self.buffer_val) sequence_timing = self.rsvp.do_sequence() # Write triggers to file _write_triggers_from_sequence_copy_phrase(sequence_timing, self.trigger_file, self.copy_phrase, text_task) # buffer core.wait(self.buffer_val) # Fake a decision! (target_letter, text_task, run) = fake_copy_phrase_decision(self.copy_phrase, target_letter, text_task) # update the final task state and say goodbye self.rsvp.update_task_state(text=text_task, color_list=['white']) self.rsvp.text = trial_complete_message(self.window, self.parameters) self.rsvp.draw_static() self.window.flip() core.wait(self.buffer_val) if self.daq.is_calibrated: _write_triggers_from_sequence_copy_phrase( ['offset', self.daq.offset], self.trigger_file, self.copy_phrase, text_task, offset=True) # Close this sessions trigger file and return some data self.trigger_file.close() # Wait some time before exiting so there is trailing eeg data saved core.wait(self.eeg_buffer) return self.file_save
def execute(self): self.logger.debug(f'Starting {self.name()}!') run = True # Check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color, first_run=True): run = False # Begin the Experiment while run: # Get random sequence information given stimuli parameters (ele_sti, timing_sti, color_sti) = random_rsvp_calibration_seq_gen( self.alp, num_sti=self.num_sti, len_sti=self.len_sti, timing=self.timing, is_txt=self.rsvp.is_txt_sti, color=self.color) (task_text, task_color) = get_task_info(self.num_sti, self.task_info_color) # Execute the RSVP sequences for idx_o in range(len(task_text)): # check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color): break # Take a break every number of trials defined in parameters.json if self.enable_breaks: pause_calibration(self.window, self.rsvp, idx_o, self.parameters) # update task state self.rsvp.update_task_state(text=task_text[idx_o], color_list=task_color[idx_o]) # Draw and flip screen self.rsvp.draw_static() self.window.flip() # Get height self.rsvp.sti.height = self.stimuli_height # Schedule a sequence self.rsvp.stim_sequence = ele_sti[idx_o] # check if text stimuli or not for color information if self.is_txt_sti: self.rsvp.color_list_sti = color_sti[idx_o] self.rsvp.time_list_sti = timing_sti[idx_o] # Wait for a time core.wait(self.buffer_val) # Do the sequence last_sequence_timing = self.rsvp.do_sequence() # Write triggers for the sequence _write_triggers_from_sequence_calibration( last_sequence_timing, self.trigger_file) # Wait for a time core.wait(self.buffer_val) # Set run to False to stop looping run = False # Say Goodbye! self.rsvp.text = trial_complete_message(self.window, self.parameters) self.rsvp.draw_static() self.window.flip() # Give the system time to process core.wait(self.buffer_val) if self.daq.is_calibrated: _write_triggers_from_sequence_calibration( ['offset', self.daq.offset], self.trigger_file, offset=True) # Close this sessions trigger file and return some data self.trigger_file.close() # Wait some time before exiting so there is trailing eeg data saved core.wait(self.eeg_buffer) return self.file_save
def execute(self): self.logger.debug('Starting Copy Phrase Task!') text_task = str(self.copy_phrase[0:self.spelled_letters_count]) task_list = [(str(self.copy_phrase), str(self.copy_phrase[0:self.spelled_letters_count]))] # Try Initializing Copy Phrase Wrapper: copy_phrase_task = CopyPhraseWrapper(self.min_num_seq, self.max_seq_length, signal_model=self.signal_model, fs=self.daq.device_info.fs, k=2, alp=self.alp, task_list=task_list, lmodel=self.language_model, is_txt_sti=self.is_txt_sti, device_name=self.daq.device_info.name, device_channels=self.daq.device_info.channels, stimuli_timing=[self.time_cross, self.time_flash]) # Set new epoch (whether to present a new epoch), # run (whether to cont. session), # sequence counter (how many seq have occured). # epoch counter and index (what epoch, and how many sequences within it) new_epoch = True run = True seq_counter = 0 epoch_counter = 0 epoch_index = 0 # Init session data and save before beginning data = { 'session': self.file_save, 'session_type': 'Copy Phrase', 'paradigm': 'RSVP', 'epochs': {}, 'total_time_spent': self.experiment_clock.getTime(), 'total_number_epochs': 0, } # Save session data _save_session_related_data(self.session_save_location, data) # check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color, first_run=True): run = False # Start the Session! while run: # check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color): break if self.copy_phrase[0:len(text_task)] == text_task: target_letter = self.copy_phrase[len(text_task)] else: target_letter = '<' # Get sequence information if new_epoch: # Init an epoch, getting initial stimuli new_epoch, sti = copy_phrase_task.initialize_epoch() ele_sti = sti[0] timing_sti = sti[1] color_sti = sti[2] # Increase epoch number and reset epoch index epoch_counter += 1 data['epochs'][epoch_counter] = {} epoch_index = 0 else: epoch_index += 1 # Update task state and reset the static self.rsvp.update_task_state(text=text_task, color_list=['white']) self.rsvp.draw_static() self.window.flip() # Setup the new Stimuli self.rsvp.stim_sequence = ele_sti[0] if self.is_txt_sti: self.rsvp.color_list_sti = color_sti[0] self.rsvp.time_list_sti = timing_sti[0] # Pause for a time core.wait(self.buffer_val) # Do the self.RSVP sequence! sequence_timing = self.rsvp.do_sequence() self.first_stim_time = self.rsvp.first_stim_time # Write triggers to file _write_triggers_from_sequence_copy_phrase( sequence_timing, self.trigger_file, self.copy_phrase, text_task) core.wait(self.buffer_val) if seq_counter == 0: del sequence_timing[0] # reshape the data and triggers as needed for later modules raw_data, triggers, target_info = \ process_data_for_decision( sequence_timing, self.daq, self.window, self.parameters, self.first_stim_time, self.static_offset) # Uncomment this to turn off fake decisions, but use fake data. # self.fake = False if self.fake: # Construct Data Record data['epochs'][epoch_counter][epoch_index] = { 'stimuli': ele_sti, 'eeg_len': len(raw_data), 'timing_sti': timing_sti, 'triggers': triggers, 'target_info': target_info, 'target_letter': target_letter, 'current_text': text_task, 'copy_phrase': self.copy_phrase} # Evaluate this sequence (target_letter, text_task, run) = \ fake_copy_phrase_decision(self.copy_phrase, target_letter, text_task) # here we assume, in fake mode, all sequences result in a selection. last_selection = text_task[-1] new_epoch = True # Update next state for this record data['epochs'][ epoch_counter][ epoch_index][ 'next_display_state'] = \ text_task else: # Evaluate this sequence, returning whether to gen a new # epoch (seq) or stimuli to present new_epoch, sti = \ copy_phrase_task.evaluate_sequence(raw_data, triggers, target_info, self.collection_window_len) # Construct Data Record data['epochs'][epoch_counter][epoch_index] = { 'stimuli': ele_sti, 'eeg_len': len(raw_data), 'timing_sti': timing_sti, 'triggers': triggers, 'target_info': target_info, 'current_text': text_task, 'copy_phrase': self.copy_phrase, 'next_display_state': copy_phrase_task.decision_maker.displayed_state, 'lm_evidence': copy_phrase_task .conjugator .evidence_history['LM'][0] .tolist(), 'eeg_evidence': copy_phrase_task .conjugator .evidence_history['ERP'][-1] .tolist(), 'likelihood': copy_phrase_task .conjugator.likelihood.tolist() } # If new_epoch is False, get the stimuli info returned if not new_epoch: ele_sti = sti[0] timing_sti = sti[1] color_sti = sti[2] # Get the current task text from the decision maker text_task = copy_phrase_task.decision_maker.displayed_state last_selection = copy_phrase_task.decision_maker.last_selection # if a letter was selected and feedback enabled, show the chosen letter if new_epoch and self.show_feedback: self.feedback.administer(last_selection, message='Selected:') # Update time spent and save data data['total_time_spent'] = self.experiment_clock.getTime() data['total_number_epochs'] = epoch_counter _save_session_related_data(self.session_save_location, data) # Decide whether to keep the task going max_tries_exceeded = seq_counter >= self.max_seq_length max_time_exceeded = data['total_time_spent'] >= self.max_seconds if (text_task == self.copy_phrase or max_tries_exceeded or max_time_exceeded): if max_tries_exceeded: logging.debug("Max tries exceeded: to allow for more tries" " adjust the Maximum Sequence Length " "(max_seq_len) parameter.") if max_time_exceeded: logging.debug("Max time exceeded. To allow for more time " "adjust the max_minutes parameter.") run = False # Increment sequence counter seq_counter += 1 # Update task state and reset the static self.rsvp.update_task_state(text=text_task, color_list=['white']) # Say Goodbye! self.rsvp.text = trial_complete_message(self.window, self.parameters) self.rsvp.draw_static() self.window.flip() # Give the system time to process core.wait(self.buffer_val) if self.daq.is_calibrated: _write_triggers_from_sequence_copy_phrase( ['offset', self.daq.offset], self.trigger_file, self.copy_phrase, text_task, offset=True) # Close the trigger file for this session self.trigger_file.close() # Wait some time before exiting so there is trailing eeg data saved core.wait(self.eeg_buffer) return self.file_save
def execute(self): self.logger.debug('Starting Icon to Icon Task!') image_array, timing_array = generate_icon_match_images( self.len_sti, self.image_path, self.num_sti, self.timing, self.is_word) # Get all png images in image path alp_image_array = glob.glob(self.image_path + '*.png') # Remove plus image from array for image in alp_image_array: if image.endswith('PLUS.png'): alp_image_array.remove(image) if self.is_word: image_name_array = glob.glob(self.image_path + '*.png') for image in image_name_array: image_name_array[image_name_array.index( image)] = path.basename(image) alp_image_array.extend(image_name_array) for image in alp_image_array: alp_image_array[alp_image_array.index(image)] = image.split( '/')[-1].split('.')[0] self.alp = alp_image_array # Try Initializing Copy Phrase Wrapper: # (sig_pro, decision maker, signal_model) try: copy_phrase_task = CopyPhraseWrapper( self.min_num_seq, self.max_seq_length, signal_model=self.signal_model, fs=self.daq.device_info.fs, k=2, alp=self.alp, task_list=['unnecessary_string', 'unnecessary_string'], lmodel=self.language_model, is_txt_sti=self.is_txt_sti, device_name=self.daq.device_info.name, device_channels=self.daq.device_info.channels) except Exception as e: self.logger.debug(f'Error Initializing Icon to Icon Task! {e}') raise e run = True new_epoch = True epoch_index = 0 correct_trials = 0 # Init session data and save before beginning data = { 'session': self.file_save, 'session_type': 'Icon to Icon Matching', 'paradigm': 'RSVP', 'epochs': {}, 'total_time_spent': self.experiment_clock.getTime(), 'total_number_epochs': 0, } # Save session data _save_session_related_data(self.session_save_location, data) # Check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color, first_run=True): run = False current_trial = 0 while run: # check user input to make sure we should be going if not get_user_input(self.rsvp, self.wait_screen_message, self.wait_screen_message_color): break if new_epoch: # Init an epoch, getting initial stimuli new_epoch, sti = copy_phrase_task.initialize_epoch() # If correct decisions are being faked, make sure that we always # are starting a new epoch if self.fake: new_epoch = True # Increase epoch number and reset epoch index data['epochs'][current_trial] = {} epoch_index = 0 else: epoch_index += 1 data['epochs'][current_trial][epoch_index] = {} if current_trial < len(image_array) or not new_epoch: self.rsvp.sti.height = self.stimuli_height self.rsvp.stim_sequence = image_array[current_trial] self.rsvp.time_list_sti = timing_array # Change size of target word if we are in word matching mode if self.is_word: # Generate list whose length is the length of the stimuli sequence, filled with the stimuli height self.rsvp.size_list_sti = list( repeat(self.stimuli_height, len(self.rsvp.stim_sequence) + 1)) # Set the target word font size to the font size defined in parameters self.rsvp.size_list_sti[0] = self.word_matching_text_size core.wait(self.buffer_val) self.rsvp.update_task_state(self.rsvp.stim_sequence[0], self.task_height, 'yellow', self.rsvp.win.size, self.is_word) # Do the sequence sequence_timing = self.rsvp.do_sequence() self.first_stim_time = self.rsvp.first_stim_time # Write triggers to file _write_triggers_from_sequence_calibration( sequence_timing, self.trigger_file) # Wait for a time core.wait(self.buffer_val) # reshape the data and triggers as needed for later modules raw_data, triggers, target_info = \ process_data_for_decision(sequence_timing, self.daq, self.window, self.parameters, self.first_stim_time) # self.fake = False display_stimulus = self.rsvp.stim_sequence[0] display_message = False if self.fake: # Construct Data Record data['epochs'][current_trial][epoch_index] = { 'stimuli': image_array[current_trial], 'eeg_len': len(raw_data), 'timing_sti': timing_array, 'triggers': triggers, 'target_info': target_info, 'target_letter': display_stimulus } correct_decision = True display_message = True message_color = 'green' current_trial += 1 correct_trials += 1 new_epoch = True if self.is_word: display_stimulus = self.image_path + \ self.rsvp.stim_sequence[0] + '.png' else: new_epoch, sti = \ copy_phrase_task.evaluate_sequence(raw_data, triggers, target_info, self.collection_window_len) # Construct Data Record data['epochs'][current_trial][epoch_index] = { 'stimuli': image_array[current_trial], 'eeg_len': len(raw_data), 'timing_sti': timing_array, 'triggers': triggers, 'target_info': target_info, 'lm_evidence': copy_phrase_task.conjugator.evidence_history['LM'] [0].tolist(), 'eeg_evidence': copy_phrase_task.conjugator.evidence_history['ERP'] [0].tolist(), 'likelihood': copy_phrase_task.conjugator.likelihood.tolist() } # Test whether to display feedback message, and what color # the message should be if new_epoch: if self.is_word: decide_image_path = self.image_path + \ copy_phrase_task.decision_maker.last_selection + '.png' else: decide_image_path = copy_phrase_task.decision_maker.last_selection + '.png' correct_decision = decide_image_path == self.rsvp.stim_sequence[ 0] display_stimulus = decide_image_path current_trial += 1 if correct_decision: message_color = 'green' correct_trials += 1 else: message_color = 'red' display_message = True else: display_message = False if display_message: # Display feedback about whether decision was correct visual_feedback = VisualFeedback( display=self.window, parameters=self.parameters, clock=self.experiment_clock) stimulus = display_stimulus visual_feedback.message_color = message_color visual_feedback.administer(stimulus, compare_assertion=None, message='Decision:') # Update time spent and save data data['total_time_spent'] = self.experiment_clock.getTime() data['total_number_epochs'] = current_trial _save_session_related_data(self.session_save_location, data) # Decide whether to keep the task going max_tries_exceeded = current_trial >= self.max_seq_length max_time_exceeded = data['total_time_spent'] >= self.max_seconds if (max_tries_exceeded or max_time_exceeded): if max_tries_exceeded: logging.debug( "Max tries exceeded: to allow for more tries" " adjust the Maximum Sequence Length " "(max_seq_len) parameter.") if max_time_exceeded: logging.debug( "Max time exceeded. To allow for more time " "adjust the max_minutes parameter.") run = False else: run = False # Write trial data to icon_data.csv in file save location with open(f"{self.file_save}/icon_data.csv", 'w+') as icon_output_csv: icon_output_writer = csv.writer(icon_output_csv, delimiter=',') icon_output_writer.writerow([ 'Participant ID', dirname(self.file_save).replace(self.data_save_path, '') ]) icon_output_writer.writerow(['Date/Time', datetime.datetime.now()]) if self.auc_filename: icon_output_writer.writerow([ 'Calibration AUC', basename(self.auc_filename).replace('.pkl', '') ]) temp_epoch_index = 1 if epoch_index == 0 else epoch_index temp_current_trial = 1 if current_trial == 0 else current_trial icon_output_writer.writerow([ 'Percentage of correctly selected icons', (correct_trials / (temp_current_trial * temp_epoch_index)) * 100 ]) icon_output_writer.writerow([ 'Task type', ('Icon to word' if self.is_word else 'Icon to icon') ]) # Say Goodbye! self.rsvp.text = trial_complete_message(self.window, self.parameters) self.rsvp.draw_static() self.window.flip() # Give the system time to process core.wait(self.buffer_val) # Close this sessions trigger file and return some data self.trigger_file.close() # Wait some time before exiting so there is trailing eeg data saved core.wait(self.eeg_buffer) return self.file_save