Beispiel #1
0
 def await_start(self) -> bool:
     """Wait for user input to either exit or start"""
     self.logger.debug('Awaiting user start.')
     should_continue = get_user_input(self.rsvp,
                                      self.wait_screen_message,
                                      self.wait_screen_message_color,
                                      first_run=True)
     return should_continue
Beispiel #2
0
 def user_wants_to_continue(self) -> bool:
     """Check if user wants to continue or terminate.
     Returns True to continue."""
     should_continue = get_user_input(self.rsvp,
                                      self.wait_screen_message,
                                      self.wait_screen_message_color,
                                      first_run=False)
     if not should_continue:
         self.logger.debug('User wants to exit.')
     return should_continue
Beispiel #3
0
    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 sequence information given stimuli parameters
            (ele_sti, timing_sti, color_sti) = self.generate_stimuli()

            (task_text, task_color) = get_task_info(self.stim_number,
                                                    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
                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.stimuli_sequence = ele_sti[idx_o]

                # check if text stimuli or not for color information
                if self.is_txt_stim:
                    self.rsvp.stimuli_colors = color_sti[idx_o]

                self.rsvp.stimuli_timing = 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
Beispiel #4
0
    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 inquiry information given stimuli parameters
            (stimuli_elements, timing_sti,
             color_sti) = random_rsvp_calibration_inq_gen(
                 self.alp,
                 stim_number=self.stim_number,
                 stim_length=self.stim_length,
                 timing=self.timing,
                 is_txt=self.is_txt_stim,
                 color=self.color)

            (task_text, task_color) = get_task_info(self.stim_number,
                                                    self._task.task_info_color)

            # Execute the RSVP inquiries
            for inquiry_idx 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

                if self.enable_breaks:
                    pause_calibration(self.window, self.rsvp, inquiry_idx,
                                      self.parameters)

                # update task state
                self.rsvp.update_task_state(text=task_text[inquiry_idx],
                                            color_list=task_color[inquiry_idx])

                # Draw and flip screen
                self.rsvp.draw_static()
                self.window.flip()

                # Get height
                self.rsvp.sti.height = self.stimuli_height

                # Schedule a inquiry
                self.rsvp.stimuli_inquiry = stimuli_elements[inquiry_idx]

                # check if text stimuli or not for color information
                if self.is_txt_stim:
                    self.rsvp.stimuli_colors = color_sti[inquiry_idx]

                self.rsvp.stimuli_timing = timing_sti[inquiry_idx]

                # Wait for a time
                core.wait(self._task.buffer_val)

                # Do the inquiry
                last_inquiry_timing = self.rsvp.do_inquiry()

                # Write triggers for the inquiry
                _write_triggers_from_inquiry_calibration(
                    last_inquiry_timing, self._task.trigger_file)

                self.logger.info('[Feedback] Getting Decision')

                position = self._get_feedback_decision(last_inquiry_timing)
                self.logger.info(
                    f'[Feedback] Administering feedback position {position}')
                self.visual_feedback.administer(position=position)

                # Wait for a time
                core.wait(self._task.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._task.buffer_val)

        if self.daq.is_calibrated:
            _write_triggers_from_inquiry_calibration(
                ['offset', self.daq.offset],
                self._task.trigger_file,
                offset=True)

        # Close this sessions trigger file and return some data
        self._task.trigger_file.close()

        # Wait some time before exiting so there is trailing eeg data saved
        core.wait(self._task.eeg_buffer)

        return self.file_save
Beispiel #5
0
    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