def _get_data_for_psd(self, inquiry_timing): # get data from the DAQ raw_data, triggers, target_info = process_data_for_decision( inquiry_timing, self.daq, self.window, self.parameters, self.rsvp.first_stim_time, self.static_offset, buf_length=self.trial_length) # filter it notch_filterted_data = notch.notch_filter(raw_data, self.fs, self.notch_filter_frequency) filtered_data = bandpass.butter_bandpass_filter( notch_filterted_data, self.filter_low, self.filter_high, self.fs, order=self.filter_order) data = downsample.downsample(filtered_data, factor=self.downsample_rate) letters, times, target_info = self.letter_info(triggers, target_info) # reshape with the filtered data with our desired window length reshaped_data, _, _, _ = trial_reshaper(target_info, times, data, fs=self.fs, k=self.downsample_rate, mode='calibration', channel_map=self.channel_map, trial_length=self.trial_length) return reshaped_data
def execute(self): self.logger.debug('Starting Icon to Icon Task!') icons = [random.choice(self.alp) for _ in range(self.stim_number)] self.logger.debug(f'Icon sequence: {icons}') selections = [] copy_phrase_task = self.init_copy_phrase_task(task_list=[(icons, [])]) epoch = EpochManager(icons, copy_phrase_task, self.timing[0]) correct_trials = 0 data = self.init_session_data(save=True) run = self.await_start() epoch.next() while run and self.user_wants_to_continue(): sequence_timing = self.present_sequence( epoch.current_sequence, epoch.current_durations, show_target=epoch.first_sequence) # Write triggers to file write_triggers_from_sequence_icon_to_icon( sequence_timing, self.trigger_file, epoch.target, target_displayed=epoch.first_sequence) core.wait(self.buffer_val) # Delete calibration if epoch.first_stimulus: del sequence_timing[0] # Delete the target presentation if epoch.first_sequence: del sequence_timing[0] # Reshape the data and triggers as needed for analysis. raw_data, triggers, target_info = process_data_for_decision( sequence_timing, self.daq, self.window, self.parameters, self.rsvp.first_stim_time) # Data Record for session.json entry = { 'stimuli': epoch.stimuli, 'eeg_len': len(raw_data), 'timing_sti': epoch.timing_sti, 'triggers': triggers, 'target_info': target_info, 'target_letter': epoch.target } if self.fake: new_epoch = True correct_trials += 1 selections.append(epoch.target) self.display_feedback(selection=epoch.target, correct=True) else: # Evaluate the data and make a decision. decision_made, new_sti = copy_phrase_task.evaluate_sequence( raw_data, triggers, target_info, self.collection_window_len) new_epoch = decision_made # Add the evidence to the data record. ev_hist = copy_phrase_task.conjugator.evidence_history likelihood = copy_phrase_task.conjugator.likelihood entry['lm_evidence'] = ev_hist['LM'][0].tolist() entry['eeg_evidence'] = ev_hist['ERP'][-1].tolist() entry['likelihood'] = likelihood.tolist() if decision_made: selection = copy_phrase_task.decision_maker.last_selection selections.append(selection) correct = selection == epoch.target if correct: correct_trials += 1 self.display_feedback(selection, correct) epoch.add_stim_data(entry) self.update_session_data(data, epoch, save=True) if new_epoch: epoch.next() else: epoch.next_stimulus(new_sti) run = self.stoppage_criteria_ok(epoch.seq_counter, data['total_time_spent']) # end while loop self.write_data(correct_trials, len(selections)) self.exit_display() return self.file_save
def execute(self): self.logger.debug('Starting Copy Phrase Task!') # already correctly spelled letters 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_inq, self.max_inq_per_trial, 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_stim=self.is_txt_stim, device_name=self.daq.device_info.name, device_channels=self.daq.device_info.channels, stimuli_timing=[self.time_cross, self.time_flash], decision_threshold=self.parameters['decision_threshold'], backspace_prob=self.parameters['lm_backspace_prob'], backspace_always_shown=self.parameters['backspace_always_shown'], filter_high=self.filter_high, filter_low=self.filter_low, filter_order=self.fitler_order, notch_filter_frequency=self.notch_filter_frequency) # Set new series (whether to present a new series), # run (whether to cont. session), # inquiry counter (how many inquiries have occured). # series counter and index # (what series, and how many inquiries within it) new_series = True run = True inq_counter = 0 series_counter = 0 series_index = 0 # Init session data and save before beginning data = { 'session': self.file_save, 'session_type': 'Copy Phrase', 'paradigm': 'RSVP', 'series': {}, 'total_time_spent': self.experiment_clock.getTime(), 'total_number_series': 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: # if correctly spelled so far, get the next unspelled letter. target_letter = self.copy_phrase[len(text_task)] else: # otherwise target is the backspace char. target_letter = '<' # Get inquiry information if new_series: # Init an series, getting initial stimuli new_series, sti = copy_phrase_task.initialize_series() ele_sti = sti[0] timing_sti = sti[1] color_sti = sti[2] # Increase series number and reset series index series_counter += 1 data['series'][series_counter] = {} series_index = 0 else: series_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.stimuli_inquiry = ele_sti[0] if self.is_txt_stim: self.rsvp.stimuli_colors = color_sti[0] self.rsvp.stimuli_timing = timing_sti[0] # Pause for a time core.wait(self.buffer_val) # Do the self.RSVP inquiry! inquiry_timing = self.rsvp.do_inquiry() # Write triggers to file _write_triggers_from_inquiry_copy_phrase(inquiry_timing, self.trigger_file, self.copy_phrase, text_task) core.wait(self.buffer_val) # Delete calibration if inq_counter == 0: del inquiry_timing[0] # reshape the data and triggers as needed for later modules raw_data, triggers, target_info = \ process_data_for_decision( inquiry_timing, self.daq, self.window, self.parameters, self.rsvp.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['series'][series_counter][series_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 inquiry (target_letter, text_task, run) = \ fake_copy_phrase_decision(self.copy_phrase, target_letter, text_task) # here we assume, in fake mode, all inquiries result in a # selection. last_selection = text_task[-1] new_series, sti = copy_phrase_task.initialize_series() # Update next state for this record data['series'][ series_counter][ series_index][ 'next_display_state'] = \ text_task else: # Evaluate this inquiry, returning whether to gen a new # series (inq) or stimuli to present new_series, sti = \ copy_phrase_task.evaluate_inquiry( raw_data, triggers, target_info, self.collection_window_len) # Construct Data Record data['series'][series_counter][series_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_series is False, get the stimuli info returned if not new_series: 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_series and self.show_feedback: self.feedback.administer(last_selection, message='Selected:', line_color=self.feedback_color, fill_color=self.feedback_color) # Update time spent and save data data['total_time_spent'] = self.experiment_clock.getTime() data['total_number_series'] = series_counter _save_session_related_data(self.session_save_location, data) # Decide whether to keep the task going max_tries_exceeded = inq_counter >= self.max_inq_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: self.logger.debug( 'COPYPHRASE ERROR: Max tries exceeded. To allow for more tries ' 'adjust the max_inq_len parameter.') if max_time_exceeded: self.logger.debug( 'COPYPHRASE ERROR: Max time exceeded. To allow for more time ' 'adjust the max_minutes parameter.') run = False # Increment inquiry counter inq_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_inquiry_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