def demo_copy_phrase_wrapper():
    # We need to train a dummy model
    num_x_p = 100
    num_x_n = 900

    x_p = mean_pos + var_pos * np.random.randn(num_ch, num_x_p, dim_x)
    x_n = mean_neg + var_neg * np.random.randn(num_ch, num_x_n, dim_x)
    y_p = [1] * num_x_p
    y_n = [0] * num_x_n

    train_x = np.concatenate((x_p, x_n), 1)
    train_y = np.concatenate((y_p, y_n), 0)
    permutation = np.random.permutation(train_x.shape[1])
    train_x = train_x[:, permutation, :]
    train_y = train_y[permutation]

    train_x = train_x[list(np.where(np.asarray(channel_map) == 1)[0]), :, :]

    k_folds = 10
    model, _ = train_pca_rda_kde_model(train_x, train_y, k_folds=k_folds)

    # Define task and operate
    task_list = [('I_LOVE_COOKIES', 'I_LOVE_'),
                 ('THIS_IS_A_DEMO', 'THIS_IS_A_')]

    task = CopyPhraseWrapper(min_num_inq=1,
                             max_num_inq=25,
                             signal_model=model,
                             fs=dim_x * 2,
                             k=1,
                             alp=alphabet(),
                             task_list=task_list)

    print(task)
Exemple #2
0
    def __init__(self, window, clock, experiment_clock, task_color='white',
                 task_font='Times', task_pos=(-.75, .75), task_height=0.1,
                 grid_rows=6, grid_columns=6, time_flash=.25,
                 task_text='1/100',
                 stim_font='Times',
                 stim_pos=(0, .0),
                 stim_height=0.25,
                 is_txt_stim=True, alp=None):

        self.win = window
        self.logger = log = logging.getLogger(__name__)

        # TASK TEXT
        self.task_font_text = task_font
        self.task_height = task_height
        self.task_pos = task_pos
        self.task_text = task_text
        self.task_color = task_color

        # STIM / GRID
        self.is_txt_stim = is_txt_stim
        self.stimuli = []
        self.rows = grid_rows
        self.stimuli_font = stim_font
        self.columns = grid_columns
        self.stim_height = stim_height

        self.stim_number = grid_rows + grid_columns

        self.max_height_grid = -1 + stim_height
        self.max_width_grid = 1 - stim_height
        self.uniform_grid_values_row = sorted(
            np.linspace(
                start=self.max_height_grid,
                stop=self.max_width_grid,
                num=self.rows))

        self.uniform_grid_values_col = sorted(
            np.linspace(
                start=self.max_height_grid,
                stop=self.max_width_grid - .25,
                num=self.columns),
            reverse=True)

        if not alp:
            self.alp = alphabet()
        else:
            self.alp = alp

        self.flash = time_flash
        # Clocks
        self.trialClock = clock
        self.expClock = experiment_clock

        # Length of the stimuli (number of stimuli on screen)
        self.stim_length = len(self.stimuli)
Exemple #3
0
    def test_alphabet_text(self):
        parameters_used = 'bcipy/parameters/parameters.json'
        parameters = load_json_parameters(parameters_used, value_cast=True)

        parameters['is_txt_stim'] = True

        alp = alphabet(parameters)

        self.assertEqual(alp, [
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            '<', '_'
        ])
Exemple #4
0
    def test_alphabet_images(self):
        parameters_used = 'bcipy/parameters/parameters.json'
        parameters = load_json_parameters(parameters_used, value_cast=True)

        parameters['is_txt_stim'] = False
        parameters['path_to_presentation_images'] = ('bcipy/static/images/'
                                                     'rsvp_images/')

        alp = alphabet(parameters)

        self.assertNotEqual(alp, [
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'R', 'S', 'T', 'U', 'V', 'Y', 'Z', '<', '_'
        ])
Exemple #5
0
def session_data(data_dir: str, alp=None):
    """Returns a dict of session data transformed to map the alphabet letter
    to the likelihood when presenting the evidence. Also removes attributes
    not useful for debugging."""

    # TODO: Better error handling for missing parameters.
    # Get the alphabet based on the provided parameters (txt or icon).
    parameters = load_json_parameters(os.path.join(data_dir,
                                                   "parameters.json"),
                                      value_cast=True)
    if parameters.get('is_txt_sti', False):
        parameters['is_txt_stim'] = parameters['is_txt_sti']

    if not alp:
        alp = alphabet(parameters=parameters)

    session_path = os.path.join(data_dir, "session.json")
    with open(session_path, 'r') as json_file:
        data = json.load(json_file)
        data['copy_phrase'] = parameters['task_text']
        for epoch in data['epochs'].keys():
            for trial in data['epochs'][epoch].keys():
                likelihood = dict(
                    zip(alp, data['epochs'][epoch][trial]['likelihood']))

                # Remove unused properties
                unused = [
                    'eeg_len', 'timing_sti', 'triggers', 'target_info',
                    'copy_phrase'
                ]
                remove_props(data['epochs'][epoch][trial], unused)

                data['epochs'][epoch][trial]['stimuli'] = data['epochs'][
                    epoch][trial]['stimuli'][0]

                # Associate letters to values
                data['epochs'][epoch][trial]['lm_evidence'] = dict(
                    zip(alp, data['epochs'][epoch][trial]['lm_evidence']))
                data['epochs'][epoch][trial]['eeg_evidence'] = dict(
                    zip(alp, data['epochs'][epoch][trial]['eeg_evidence']))
                data['epochs'][epoch][trial]['likelihood'] = likelihood

                # Display the 5 most likely values.
                data['epochs'][epoch][trial]['most_likely'] = dict(
                    Counter(likelihood).most_common(5))

        return data
Exemple #6
0
    def __init__(self, win, daq, parameters, file_save):
        super(RSVPCalibrationTask, self).__init__()

        self.window = win
        self.frame_rate = self.window.getActualFrameRate()
        self.parameters = parameters
        self.daq = daq
        self.static_clock = core.StaticPeriod(screenHz=self.frame_rate)
        self.experiment_clock = core.Clock()
        self.buffer_val = parameters['task_buffer_len']
        self.alp = alphabet(parameters)
        self.rsvp = init_calibration_display_task(self.parameters, self.window,
                                                  self.daq, self.static_clock,
                                                  self.experiment_clock)
        self.file_save = file_save
        trigger_save_location = f"{self.file_save}/{parameters['trigger_file_name']}"
        self.trigger_file = open(trigger_save_location, 'w', encoding='utf-8')

        self.wait_screen_message = parameters['wait_screen_message']
        self.wait_screen_message_color = parameters[
            'wait_screen_message_color']

        self.stim_number = parameters['stim_number']
        self.stim_length = parameters['stim_length']
        self.timing = [
            parameters['time_target'], parameters['time_cross'],
            parameters['time_flash']
        ]

        self.color = [
            parameters['target_letter_color'], parameters['fixation_color'],
            parameters['stim_color']
        ]

        self.task_info_color = parameters['task_color']

        self.stimuli_height = parameters['stim_height']

        self.is_txt_stim = parameters['is_txt_stim']
        self.eeg_buffer = parameters['eeg_buffer_len']

        self.enable_breaks = parameters['enable_breaks']
Exemple #7
0
 def __init__(self, path2eeg):
     self.abc = alphabet()
     self.samples = eegs(path2eeg)
    def test_valid_letters(self):
        alp = alphabet()
        cp = CopyPhraseWrapper(min_num_seq=1,
                               max_num_seq=50,
                               signal_model=None,
                               fs=25,
                               k=2,
                               alp=alp,
                               task_list=[('HELLO_WORLD', 'HE')],
                               is_txt_sti=True,
                               device_name='LSL',
                               evidence_names=['LM', 'ERP'],
                               device_channels=[
                                   'ch1', 'ch2', 'ch3', 'ch4', 'ch5', 'ch6',
                                   'ch7', 'ch8', 'ch9', 'ch10', 'ch11', 'ch12',
                                   'ch13', 'ch14', 'ch15', 'ch16', 'TRG'
                               ],
                               stimuli_timing=[0.5, 0.25])

        triggers = [('+', 0.0), ('H', 0.5670222830376588),
                    ('D', 0.8171830819919705), ('J', 1.0843321380089037),
                    ('B', 1.3329724550130777), ('C', 1.5825864360085689),
                    ('A', 1.833380013005808), ('F', 2.083211077027954),
                    ('G', 2.333359022042714), ('I', 2.583265081048012),
                    ('E', 2.833274284028448)]
        target_info = [
            'nontarget', 'nontarget', 'nontarget', 'nontarget', 'nontarget',
            'nontarget', 'nontarget', 'nontarget', 'nontarget', 'nontarget',
            'nontarget'
        ]

        letters, timings, labels = cp.letter_info(triggers, target_info)
        expected_letters = ['H', 'D', 'J', 'B', 'C', 'A', 'F', 'G', 'I', 'E']
        expected_time = [
            0.5670222830376588, 0.8171830819919705, 1.0843321380089037,
            1.3329724550130777, 1.5825864360085689, 1.833380013005808,
            2.083211077027954, 2.333359022042714, 2.583265081048012,
            2.833274284028448
        ]
        self.assertEqual(expected_letters, letters)
        self.assertEqual(expected_time, timings)
        self.assertEqual(len(letters), len(labels))

        triggers = [('calibration_trigger', 0.0), ('+', 0.1),
                    ('H', 0.5670222830376588), ('D', 0.8171830819919705),
                    ('J', 1.0843321380089037), ('B', 1.3329724550130777),
                    ('C', 1.5825864360085689), ('A', 1.833380013005808),
                    ('F', 2.083211077027954), ('G', 2.333359022042714),
                    ('I', 2.583265081048012), ('E', 2.833274284028448)]
        target_info = [
            'calib', 'fixation', 'nontarget', 'nontarget', 'nontarget',
            'nontarget', 'nontarget', 'nontarget', 'nontarget', 'nontarget',
            'nontarget', 'nontarget'
        ]
        letters, timings, labels = cp.letter_info(triggers, target_info)
        self.assertEqual(expected_letters, letters)
        self.assertEqual(expected_time, timings)
        self.assertEqual(['nontarget'] * (len(letters)), labels)

        # Test it throws an exception when letter is outside alphabet
        with self.assertRaises(Exception):
            cp.letter_info([('A', 0.0), ('*', 1.0)],
                           ['nontarget', 'nontarget'])
Exemple #9
0
    def __init__(self, win, daq, parameters, file_save, signal_model,
                 language_model, fake, is_word, auc_filename):
        super(RSVPIconToIconTask, self).__init__()
        self.window = win
        self.frame_rate = self.window.getActualFrameRate()
        self.parameters = parameters
        self.daq = daq
        self.static_clock = core.StaticPeriod(screenHz=self.frame_rate)
        self.experiment_clock = core.Clock()
        self.buffer_val = parameters['task_buffer_len']

        self.image_path = parameters['path_to_presentation_images']
        # Alphabet is comprised of the image base names
        self.alp = alphabet(parameters, include_path=False)

        self.rsvp = _init_icon_to_icon_display_task(
            self.parameters, self.window, self.daq, self.static_clock,
            self.experiment_clock, is_word)
        self.file_save = file_save
        self.is_word = is_word

        trigger_save_location = f'{self.file_save}/{parameters["trigger_file_name"]}'
        self.trigger_file = open(trigger_save_location, 'w+')
        self.session_save_location = f'{self.file_save}/{parameters["session_file_name"]}'

        self.wait_screen_message = parameters['wait_screen_message']
        self.wait_screen_message_color = parameters[
            'wait_screen_message_color']

        self.stim_number = parameters['stim_number']
        self.stim_length = parameters['stim_length']
        self.timing = [
            parameters['time_target'], parameters['time_cross'],
            parameters['time_flash']
        ]

        self.color = [
            parameters['target_letter_color'], parameters['fixation_color'],
            parameters['stim_color']
        ]

        self.task_info_color = parameters['task_color']

        self.stimuli_height = parameters['stim_height']

        self.eeg_buffer = parameters['eeg_buffer_len']

        self.max_seconds = parameters['max_minutes'] * 60  # convert to seconds
        self.max_seq_length = parameters['max_seq_len']
        self.max_seq_per_trial = parameters['max_seq_per_trial']
        self.fake = fake
        self.language_model = language_model
        self.signal_model = signal_model
        self.auc_filename = auc_filename

        self.task_height = parameters['task_height']

        self.is_txt_stim = False

        self.min_num_seq = parameters['min_seq_len']
        self.word_matching_text_size = parameters['word_matching_text_size']
        self.collection_window_len = parameters[
            'collection_window_after_trial_length']

        self.data_save_path = parameters['data_save_loc']

        match_type = 'Word' if self.is_word else 'Icon'
        self.session_description = f'Icon to {match_type} Matching'
Exemple #10
0
import logging
import sys
from typing import List
from collections import defaultdict
from bcipy.helpers.task import alphabet, SPACE_CHAR
from bcipy.language_model import lm_server
from bcipy.language_model.errors import (EvidenceDataStructError, NBestError,
                                         NBestHighValue)
from bcipy.language_model.lm_server import LmServerConfig

log = logging.getLogger(__name__)
sys.path.append('.')
ALPHABET = alphabet()
LM_SPACE = '#'


class LangModel:

    DEFAULT_CONFIG = LmServerConfig(image="oclmimage:version2.0",
                                    port=6000,
                                    docker_port=5000)

    def __init__(self,
                 server_config: LmServerConfig = DEFAULT_CONFIG,
                 logfile: str = "log"):
        """
        Initiate the langModel class and starts the corresponding docker
        server for the given type.

        Input:
          lmtype - language model type
Exemple #11
0
def session_db(data_dir: str, db_name='session.db', alp=None):
    """Writes a relational database (sqlite3) of session data that can
    be used for exploratory analysis.

    Parameters:
    -----------
        data_dir - directory with the session.json data (and parameters.json)
        db_name - name of database to write; defaults to session.db
        alp - optional alphabet to use; may be required if using icons that do
            not exist on the current machine.

    Returns:
    --------
        Creates a sqlite3 database and returns a pandas dataframe of the
        evidence table for use within a repl.

    Schema:
    ------
    trial:
        - id: int
        - target: str

    evidence:
        - trial integer (0-based)
        - sequence integer (0-based)
        - letter text (letter or icon)
        - lm real (language model probability for the trial; same for every
            sequence and only considered in the cumulative value during the
            first sequence)
        - eeg real (likelihood for the given sequence; a value of 1.0 indicates
            that the letter was not presented)
        - cumulative real (cumulative likelihood for the trial thus far)
        - seq_position integer (sequence position; null if not presented)
        - is_target integer (boolean; true(1) if this letter is the target)
        - presented integer (boolean; true if the letter was presented in
            this sequence)
        - above_threshold (boolean; true if cumulative likelihood was above
            the configured threshold)
    """
    # TODO: Better error handling for missing parameters.

    # Get the alphabet based on the provided parameters (txt or icon).
    parameters = load_json_parameters(os.path.join(data_dir,
                                                   "parameters.json"),
                                      value_cast=True)
    if parameters.get('is_txt_sti', False):
        parameters['is_txt_stim'] = parameters['is_txt_sti']
    if not alp:
        alp = alphabet(parameters=parameters)

    session_path = os.path.join(data_dir, "session.json")
    with open(session_path, 'r') as json_file:
        data = json.load(json_file)

        # Create database
        conn = sqlite3.connect(db_name)
        cursor = conn.cursor()

        cursor.execute('CREATE TABLE trial (id integer, target text)')
        cursor.execute(
            'CREATE TABLE evidence (series integer, sequence integer, '
            'stim text, lm real, eeg real, cumulative real, seq_position '
            'integer, is_target integer, presented integer, above_threshold)')
        conn.commit()

        for series in data['epochs'].keys():
            for i, seq_index in enumerate(data['epochs'][series].keys()):
                sequence = data['epochs'][series][seq_index]
                session_type = data['session_type']

                target_letter = get_target(
                    session_type, sequence,
                    max(sequence['likelihood']) >
                    parameters['decision_threshold'])
                stimuli = get_stimuli(session_type, sequence)

                if i == 0:
                    # create record for the trial
                    conn.executemany('INSERT INTO trial VALUES (?,?)',
                                     [(int(series), target_letter)])

                lm_ev = dict(zip(alp, sequence['lm_evidence']))
                cumulative_likelihoods = dict(zip(alp, sequence['likelihood']))

                ev_rows = []
                for letter, prob in zip(alp, sequence['eeg_evidence']):
                    seq_position = None
                    if letter in stimuli:
                        seq_position = stimuli.index(letter)
                    if target_letter:
                        is_target = 1 if target_letter == letter else 0
                    else:
                        is_target = None
                    cumulative = cumulative_likelihoods[letter]
                    above_threshold = cumulative >= parameters[
                        'decision_threshold']
                    ev_row = (int(series), int(seq_index), letter,
                              lm_ev[letter], prob, cumulative, seq_position,
                              is_target, seq_position
                              is not None, above_threshold)
                    ev_rows.append(ev_row)

                conn.executemany(
                    'INSERT INTO evidence VALUES (?,?,?,?,?,?,?,?,?,?)',
                    ev_rows)
                conn.commit()
        dataframe = pd.read_sql_query("SELECT * FROM evidence", conn)
        conn.close()
        return dataframe
Exemple #12
0
    def __init__(self, win, daq, parameters, file_save, signal_model,
                 language_model, fake):
        super(RSVPCopyPhraseTask, self).__init__()

        self.window = win
        self.frame_rate = self.window.getActualFrameRate()
        self.parameters = parameters
        self.daq = daq
        self.static_clock = core.StaticPeriod(screenHz=self.frame_rate)
        self.experiment_clock = core.Clock()
        self.buffer_val = parameters['task_buffer_len']
        self.alp = alphabet(parameters)
        self.rsvp = _init_copy_phrase_display(self.parameters, self.window,
                                              self.daq, self.static_clock,
                                              self.experiment_clock)
        self.file_save = file_save

        trigger_save_location = f"{self.file_save}/{parameters['trigger_file_name']}"
        self.trigger_file = open(trigger_save_location, 'w')
        self.session_save_location = f"{self.file_save}/{parameters['session_file_name']}"

        self.wait_screen_message = parameters['wait_screen_message']
        self.wait_screen_message_color = parameters[
            'wait_screen_message_color']

        self.stim_number = parameters['stim_number']
        self.stim_length = parameters['stim_length']
        self.time_cross = parameters['time_cross']
        self.time_target = parameters['time_target']
        self.time_flash = parameters['time_flash']
        self.timing = [self.time_target, self.time_cross, self.time_flash]

        self.color = [
            parameters['target_color'], parameters['fixation_color'],
            parameters['stim_color']
        ]

        self.task_info_color = parameters['task_color']

        self.stimuli_height = parameters['stim_height']

        self.is_txt_stim = parameters['is_txt_stim']
        self.eeg_buffer = parameters['eeg_buffer_len']
        self.copy_phrase = parameters['task_text']
        self.spelled_letters_count = int(parameters['spelled_letters_count'])
        if self.spelled_letters_count > len(self.copy_phrase):
            self.logger.debug('Already spelled letters exceeds phrase length.')
            self.spelled_letters_count = 0

        self.max_inq_length = parameters['max_inq_len']
        self.max_seconds = parameters['max_minutes'] * 60  # convert to seconds
        self.max_inq_per_trial = parameters['max_inq_per_trial']
        self.fake = fake
        self.language_model = language_model
        self.signal_model = signal_model
        self.down_sample_rate = parameters['down_sampling_rate']

        self.filter_low = self.parameters['filter_low']
        self.filter_high = self.parameters['filter_high']
        self.fitler_order = self.parameters['filter_order']
        self.notch_filter_frequency = self.parameters['notch_filter_frequency']

        self.min_num_inq = parameters['min_inq_len']
        self.collection_window_len = parameters['trial_length']

        self.static_offset = parameters['static_trigger_offset']
        self.show_feedback = parameters['show_feedback']
        self.feedback_color = parameters['feedback_message_color']

        if self.show_feedback:
            self.feedback = VisualFeedback(self.window, self.parameters,
                                           self.experiment_clock)