Example #1
0
    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
Example #2
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
    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
            (stimuli_elements, timing_sti,
             color_sti) = random_rsvp_calibration_seq_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)

            import pdb
            pdb.set_trace()

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

            # Execute the RSVP sequences
            for sequence_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, sequence_idx,
                                      self.parameters)

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

                # 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 = stimuli_elements[sequence_idx]

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

                self.rsvp.stimuli_timing = timing_sti[sequence_idx]

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

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

                position = self._get_feedback_decision(last_sequence_timing)
                self.logger.info(
                    f'[Feedback] Administering feedback position {position}')
                timing = 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_sequence_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