def make_bipolar(data_fname, montage_filename):
    raw = mne.io.read_raw_edf(data_fname, preload=False, verbose=False)
    mne.rename_channels(raw.info, lambda name: re.sub(r'(POL|SEEG)\s+', '', name).strip())

    channel_types = dict()

    for ch in raw.ch_names:
        result = re.match(r'^[A-Z][\']?\d+', ch)
        if result:
            channel_types[ch] = 'seeg'

    raw.set_channel_types(channel_types)

    montage = pd.read_csv(montage_filename, delimiter='\t')
    montage.drop_duplicates(subset='name', inplace=True)

    anode,cathode = clean_montage(raw.ch_names, montage.anode.tolist(), montage.cathode.tolist())

    raw.load_data()

    bipo = mne.set_bipolar_reference(raw, list(anode), list(cathode), copy=True, verbose=False)
    bipo = drop_monopolar_channels(bipo)
    bipo.drop_channels(bipo.info['bads'])

    picks_seeg = mne.pick_types(bipo.info, meg=False, seeg=True)

    non_seeg_chans = [ch_name for ch_idx, ch_name in enumerate(bipo.ch_names) if not(ch_idx in picks_seeg) or len(ch_name.split('-')) == 1]
    bipo.drop_channels(non_seeg_chans)

    bipo.notch_filter(np.arange(50, bipo.info['sfreq']//2, 50))

    return bipo
예제 #2
0
def for_firas_37(crop_start=None, file_name=None):
    edf = 'C:\\Matlab\\D037_28_01_21a.edf'
    raw = mne.io.read_raw_edf(edf)
    channels_list_original = [
        'RA 01', 'RA 02', 'RH 01', 'RH 02', 'LAH 01', 'LAH 02'
    ]
    channels_list_bipolar_original = [
        x[:-1] + str(int(x[-1]) + 1) for x in channels_list_original
    ]
    channels_list = [x.replace(' 0', '') for x in channels_list_original]
    channels_list_bipolar = [
        x.replace(' 0', '') for x in channels_list_bipolar_original
    ]
    raw.pick_channels(
        list(
            set(channels_list_original) | set(channels_list_bipolar_original)))
    channels_mapping = {x: x.replace(' 0', '') for x in raw.ch_names}
    raw.rename_channels(channels_mapping)
    if crop_start is not None:
        raw.crop(tmin=crop_start * 60, tmax=crop_start * 60 + 16 * 60)
        raw.resample(250)
    raw.load_data()
    raw_bi = mne.set_bipolar_reference(raw,
                                       anode=channels_list,
                                       cathode=channels_list_bipolar,
                                       drop_refs=False)
    rotem_write_edf(raw_bi,
                    '416_bipolar.edf' if file_name is None else file_name)
예제 #3
0
파일: utils.py 프로젝트: lneisenman/seeg
def create_bipolar(raw, electrodes):
    """ create EEG data in a bipolar montage

    Parameters
    ----------
    raw : MNE Raw
        EEG data
    electrodes : list of strings
        names of electrodes

    Returns
    -------
    bipolar : MNE Raw
        EEG data in a bipolar montage
    """
    anodes = list()
    cathodes = list()
    ch_names = list()
    for name in electrodes:
        temp = setup_bipolar(name, raw.ch_names, raw.info['bads'])
        anodes.extend(temp[0])
        cathodes.extend(temp[1])
        ch_names.extend(temp[2])

    bipolar = mne.set_bipolar_reference(raw, anodes, cathodes,
                                        ch_names, verbose=False)
    bipolar = bipolar.pick_channels(ch_names)
    bipolar = bipolar.reorder_channels(ch_names)
    return bipolar
예제 #4
0
def test_bipolar_combinations():
    """Test bipolar channel generation."""
    ch_names = ['CH' + str(ni + 1) for ni in range(10)]
    info = create_info(ch_names=ch_names,
                       sfreq=1000.,
                       ch_types=['eeg'] * len(ch_names))
    raw_data = np.random.randn(len(ch_names), 1000)
    raw = RawArray(raw_data, info)

    def _check_bipolar(raw_test, ch_a, ch_b):
        picks = [raw_test.ch_names.index(ch_a + '-' + ch_b)]
        get_data_res = raw_test.get_data(picks=picks)[0, :]
        manual_a = raw_data[ch_names.index(ch_a), :]
        manual_b = raw_data[ch_names.index(ch_b), :]
        assert_array_equal(get_data_res, manual_a - manual_b)

    # test classic EOG/ECG bipolar reference (only two channels per pair).
    raw_test = set_bipolar_reference(raw, ['CH2'], ['CH1'], copy=True)
    _check_bipolar(raw_test, 'CH2', 'CH1')

    # test all combinations.
    a_channels, b_channels = zip(*itertools.combinations(ch_names, 2))
    a_channels, b_channels = list(a_channels), list(b_channels)
    raw_test = set_bipolar_reference(raw, a_channels, b_channels, copy=True)
    for ch_a, ch_b in zip(a_channels, b_channels):
        _check_bipolar(raw_test, ch_a, ch_b)
    # check if reference channels have been dropped.
    assert (len(raw_test.ch_names) == len(a_channels))

    raw_test = set_bipolar_reference(raw,
                                     a_channels,
                                     b_channels,
                                     drop_refs=False,
                                     copy=True)
    # check if reference channels have been kept correctly.
    assert (len(raw_test.ch_names) == len(a_channels) + len(ch_names))
    for idx, ch_label in enumerate(ch_names):
        manual_ch = raw_data[idx, :]
        assert_array_equal(
            raw_test._data[raw_test.ch_names.index(ch_label), :], manual_ch)

    # test bipolars with a channel in both list (anode & cathode).
    raw_test = set_bipolar_reference(raw, ['CH2', 'CH1'], ['CH1', 'CH2'],
                                     copy=True)
    _check_bipolar(raw_test, 'CH2', 'CH1')
    _check_bipolar(raw_test, 'CH1', 'CH2')
예제 #5
0
def add_bipolar_derivation(raw, ch_1, ch_2):
    """
    adds a channel to the given raw instance that is ch_1-ch_2
    :param raw: raw object to derive channel from
    :param ch_1: anode
    :param ch_2: cathode
    """
    raw = mne.set_bipolar_reference(raw, ch_1, ch_2, drop_refs=False)
    return raw
예제 #6
0
def test_bipolar_combinations():
    """Test bipolar channel generation."""
    ch_names = ['CH' + str(ni + 1) for ni in range(10)]
    info = create_info(
        ch_names=ch_names, sfreq=1000., ch_types=['eeg'] * len(ch_names))
    raw_data = np.random.randn(len(ch_names), 1000)
    raw = RawArray(raw_data, info)

    def _check_bipolar(raw_test, ch_a, ch_b):
        picks = [raw_test.ch_names.index(ch_a + '-' + ch_b)]
        get_data_res = raw_test.get_data(picks=picks)[0, :]
        manual_a = raw_data[ch_names.index(ch_a), :]
        manual_b = raw_data[ch_names.index(ch_b), :]
        assert_array_equal(get_data_res, manual_a - manual_b)

    # test classic EOG/ECG bipolar reference (only two channels per pair).
    raw_test = set_bipolar_reference(raw, ['CH2'], ['CH1'], copy=True)
    _check_bipolar(raw_test, 'CH2', 'CH1')

    # test all combinations.
    a_channels, b_channels = zip(*itertools.combinations(ch_names, 2))
    a_channels, b_channels = list(a_channels), list(b_channels)
    raw_test = set_bipolar_reference(raw, a_channels, b_channels, copy=True)
    for ch_a, ch_b in zip(a_channels, b_channels):
        _check_bipolar(raw_test, ch_a, ch_b)
    # check if reference channels have been dropped.
    assert (len(raw_test.ch_names) == len(a_channels))

    raw_test = set_bipolar_reference(
        raw, a_channels, b_channels, drop_refs=False, copy=True)
    # check if reference channels have been kept correctly.
    assert (len(raw_test.ch_names) == len(a_channels) + len(ch_names))
    for idx, ch_label in enumerate(ch_names):
        manual_ch = raw_data[idx, :]
        assert_array_equal(
            raw_test._data[raw_test.ch_names.index(ch_label), :], manual_ch)

    # test bipolars with a channel in both list (anode & cathode).
    raw_test = set_bipolar_reference(
        raw, ['CH2', 'CH1'], ['CH1', 'CH2'], copy=True)
    _check_bipolar(raw_test, 'CH2', 'CH1')
    _check_bipolar(raw_test, 'CH1', 'CH2')
예제 #7
0
def write_events_fif_bipolar():
    edf = '/Users/rotemfalach/projects/epileptic_activity/results/406/406_overnightData.edf'
    channels_list = [
        'SEEG LA1-REF', 'SEEG LA2-REF', 'SEEG LAH1-REF', 'SEEG LAH2-REF',
        'SEEG RA1-REF', 'SEEG RA2-REF', 'SEEG RAH1-REF', 'SEEG RAH2-REF'
    ]
    channels_list_bipolar = [
        x[:-5] + str(int(x[-5]) + 1) + '-REF' for x in channels_list
    ]
    # channels_list = ['LA 02', 'LH 01', 'LH 02', 'RA 02', 'RMH 01', 'RMH 02'] # 036
    # channels_list_bipolar = [x[:-1] + str(int(x[-1]) + 1) for x in channels_list]
    spikes_files = '_'.join(edf.split('_')[0:2])
    original_raw = mne.io.read_raw_edf(edf)
    original_raw.pick_channels(
        list(set(channels_list) | set(channels_list_bipolar)))
    original_raw.load_data()
    raw = original_raw
    for chan in channels_list:
        # original_raw.rename_channels({chan: chan.replace('SEEG ', '').replace('-REF', '')})
        original_raw = mne.set_bipolar_reference(
            original_raw,
            anode=[chan],
            cathode=chan[:-5] + str(int(chan[-5]) + 1) + '-REF',
            drop_refs=False,
            ch_name=chan + '_bi')
        stim_amp, stim_grad, stim_env = np.zeros((1, raw.n_times)), np.zeros(
            (1, raw.n_times)), np.zeros((1, raw.n_times))
        # chan_alias = chan.replace(' 0', '')
        chan_alias = chan.replace('SEEG ', '').replace('-REF', '')
        spikes_df = pd.read_csv(spikes_files + '_' + chan_alias +
                                '_biplor_spikes.csv')
        for evt in spikes_df.values:
            if evt[1] == 'amp':
                stim_amp[0][evt[4]] = 1
            elif evt[1] == 'grad':
                stim_grad[0][evt[4]] = 1
            else:
                stim_env[0][evt[4]] = 1

        info_amp = mne.create_info([chan_alias + '_AMP_bi'], raw.info['sfreq'],
                                   ['stim'])
        info_grad = mne.create_info([chan_alias + '_GRAD_bi'],
                                    raw.info['sfreq'], ['stim'])
        info_env = mne.create_info([chan_alias + '_ENV_bi'], raw.info['sfreq'],
                                   ['stim'])
        amp_raw = mne.io.RawArray(stim_amp, info_amp)
        grad_raw = mne.io.RawArray(stim_grad, info_grad)
        env_raw = mne.io.RawArray(stim_env, info_env)
        original_raw.add_channels([amp_raw, grad_raw, env_raw],
                                  force_update_info=True)

    original_raw.drop_channels(
        list(set(channels_list) | set(channels_list_bipolar)))
    original_raw.resample(500).save('406_bi.fif')
예제 #8
0
def bipolar_ref(raw, anode, cathode, new_ch=None, copy=False, ch_info=None):
    """ 
    Sets bipolar montage.
    """
    from mne import set_bipolar_reference

    cathode = utilsfunc.in_list(cathode)
    if len(cathode) == 1:
        cathode = cathode * len(utilsfunc.in_list(anode))
    if new_ch is None:
        new_ch = utilsfunc.in_list(anode)

    if copy is False:
        set_bipolar_reference(raw,anode=anode,\
                              cathode=cathode,ch_name=new_ch,\
                              copy=False, ch_info=ch_info)
    else:
        return set_bipolar_reference(raw,anode=anode,\
                                     cathode=cathode,ch_name=new_ch,\
                                     copy=True, ch_info=ch_info)
예제 #9
0
def for_firas_398(crop_start=None, file_name=None):
    edf = 'C:\\UCLA\\P398_overnightData.edf'
    raw = mne.io.read_raw_edf(edf)
    channels_list_original = [
        'SEEG R'
        'A1-REF', 'SEEG RA2-REF', 'SEEG REC1-REF', 'SEEG REC2-REF',
        'SEEG RAH1-REF', 'SEEG RAH2-REF', 'SEEG LA1-REF', 'SEEG LA2-REF',
        'SEEG LAH1-REF', 'SEEG LAH2-REF'
    ]
    channels_list_bipolar_original = [
        x[:-5] + str(int(x[-5]) + 1) + '-REF' for x in channels_list_original
    ]

    channels_list = [
        x.replace('SEEG ', '').replace('-REF', '')
        for x in channels_list_original
    ]
    channels_list_bipolar = [
        x.replace('SEEG ', '').replace('-REF', '')
        for x in channels_list_bipolar_original
    ]

    raw.pick_channels(
        list(
            set(channels_list_original) | set(channels_list_bipolar_original)))
    channels_mapping = {
        x: x.replace('SEEG ', '').replace('-REF', '')
        for x in raw.ch_names
    }
    raw.rename_channels(channels_mapping)
    if crop_start is not None:
        raw.crop(tmin=crop_start * 60, tmax=crop_start * 60 + 16 * 60)
        raw.resample(250)
    raw.load_data()

    raw_bi = mne.set_bipolar_reference(raw,
                                       anode=channels_list,
                                       cathode=channels_list_bipolar,
                                       drop_refs=False)
    # raw_bi.plot()

    write_edf('398_bipolar.edf' if file_name is None else file_name, raw_bi)
예제 #10
0
def test_set_bipolar_reference(inst_type):
    """Test bipolar referencing."""
    raw = read_raw_fif(fif_fname, preload=True)
    raw.apply_proj()

    if inst_type == 'raw':
        inst = raw
        del raw
    elif inst_type in ['epochs', 'evoked']:
        events = find_events(raw, stim_channel='STI 014')
        epochs = Epochs(raw, events, tmin=-0.3, tmax=0.7, preload=True)
        inst = epochs
        if inst_type == 'evoked':
            inst = epochs.average()
        del epochs

    ch_info = {'kind': FIFF.FIFFV_EOG_CH, 'extra': 'some extra value'}
    with pytest.raises(KeyError, match='key errantly present'):
        set_bipolar_reference(inst, 'EEG 001', 'EEG 002', 'bipolar', ch_info)
    ch_info.pop('extra')
    reref = set_bipolar_reference(inst, 'EEG 001', 'EEG 002', 'bipolar',
                                  ch_info)
    assert (reref.info['custom_ref_applied'])

    # Compare result to a manual calculation
    a = inst.copy().pick_channels(['EEG 001', 'EEG 002'])
    a = a._data[..., 0, :] - a._data[..., 1, :]
    b = reref.copy().pick_channels(['bipolar'])._data[..., 0, :]
    assert_allclose(a, b)

    # Original channels should be replaced by a virtual one
    assert ('EEG 001' not in reref.ch_names)
    assert ('EEG 002' not in reref.ch_names)
    assert ('bipolar' in reref.ch_names)

    # Check channel information
    bp_info = reref.info['chs'][reref.ch_names.index('bipolar')]
    an_info = reref.info['chs'][inst.ch_names.index('EEG 001')]
    for key in bp_info:
        if key == 'loc':
            assert_array_equal(bp_info[key], 0)
        elif key == 'coil_type':
            assert_equal(bp_info[key], FIFF.FIFFV_COIL_EEG_BIPOLAR)
        elif key == 'kind':
            assert_equal(bp_info[key], FIFF.FIFFV_EOG_CH)
        else:
            assert_equal(bp_info[key], an_info[key])

    # Minimalist call
    reref = set_bipolar_reference(inst, 'EEG 001', 'EEG 002')
    assert ('EEG 001-EEG 002' in reref.ch_names)

    # Minimalist call with twice the same anode
    reref = set_bipolar_reference(inst, ['EEG 001', 'EEG 001', 'EEG 002'],
                                  ['EEG 002', 'EEG 003', 'EEG 003'])
    assert ('EEG 001-EEG 002' in reref.ch_names)
    assert ('EEG 001-EEG 003' in reref.ch_names)

    # Set multiple references at once
    reref = set_bipolar_reference(
        inst,
        ['EEG 001', 'EEG 003'],
        ['EEG 002', 'EEG 004'],
        ['bipolar1', 'bipolar2'],
        [{
            'kind': FIFF.FIFFV_EOG_CH
        }, {
            'kind': FIFF.FIFFV_EOG_CH
        }],
    )
    a = inst.copy().pick_channels(['EEG 001', 'EEG 002', 'EEG 003', 'EEG 004'])
    a = np.concatenate([
        a._data[..., :1, :] - a._data[..., 1:2, :],
        a._data[..., 2:3, :] - a._data[..., 3:4, :]
    ],
                       axis=-2)
    b = reref.copy().pick_channels(['bipolar1', 'bipolar2'])._data
    assert_allclose(a, b)

    # Test creating a bipolar reference that doesn't involve EEG channels:
    # it should not set the custom_ref_applied flag
    reref = set_bipolar_reference(inst,
                                  'MEG 0111',
                                  'MEG 0112',
                                  ch_info={'kind': FIFF.FIFFV_MEG_CH},
                                  verbose='error')
    assert (not reref.info['custom_ref_applied'])
    assert ('MEG 0111-MEG 0112' in reref.ch_names)

    # Test a battery of invalid inputs
    pytest.raises(ValueError, set_bipolar_reference, inst, 'EEG 001',
                  ['EEG 002', 'EEG 003'], 'bipolar')
    pytest.raises(ValueError, set_bipolar_reference, inst,
                  ['EEG 001', 'EEG 002'], 'EEG 003', 'bipolar')
    pytest.raises(ValueError, set_bipolar_reference, inst, 'EEG 001',
                  'EEG 002', ['bipolar1', 'bipolar2'])
    pytest.raises(ValueError,
                  set_bipolar_reference,
                  inst,
                  'EEG 001',
                  'EEG 002',
                  'bipolar',
                  ch_info=[{
                      'foo': 'bar'
                  }, {
                      'foo': 'bar'
                  }])
    pytest.raises(ValueError,
                  set_bipolar_reference,
                  inst,
                  'EEG 001',
                  'EEG 002',
                  ch_name='EEG 003')
예제 #11
0
# edf = 'C:\\UCLA\\P406_staging_PSG_and_intracranial_Mref_correct.txt.edf'
# edf = 'C:\\Users\\user\\PycharmProjects\\pythonProject\\results\\402\\402_for_tag.edf'
# edf = "C:ֿֿֿֿ\\analysis\\396\\396_LAH1_100_samples.fif"
subj = '406'
edf = f'C:\\UCLA\\P{subj}_overnightData.edf'
depth_epochs = pd.read_csv(
    f'C:\\repos\\spikes_notebooks\\spike_index_{subj}.csv')
scalp_epochs = pd.read_csv(
    f'C:\\repos\\spikes_notebooks\\scalp_index_{subj}.csv')
raw = mne.io.read_raw_edf(edf).pick_channels(
    ['EOG1', 'EOG2', 'C3', 'C4', 'PZ', 'RAH1', 'RAH2', 'LAH1',
     'LAH2']).resample(1000)
raw = mne.set_bipolar_reference(raw,
                                'RAH1',
                                'RAH2',
                                ch_name='RAH1-RAH2',
                                drop_refs=False)
raw = mne.set_bipolar_reference(raw,
                                'LAH1',
                                'LAH2',
                                ch_name='LAH1-LAH2',
                                drop_refs=False)

depth = np.zeros((1, raw.n_times))
for evt in depth_epochs.values:
    depth[0][250 * evt[0]:250 * evt[0] + 250] = 1

scalp = np.zeros((1, raw.n_times))
for evt in scalp_epochs.values:
    scalp[0][250 * evt[0]:250 * evt[0] + 250] = 1
예제 #12
0
def load_data(bids_path):
    # read_raw_bids automatically
    # - populates bad channels using the BIDS channels.tsv
    # - sets channels types according to BIDS channels.tsv `type` column
    # - sets raw.annotations using the BIDS events.tsv

    subject = bids_path.subject
    session = bids_path.session

    extra_params = dict()
    if config.allow_maxshield:
        extra_params['allow_maxshield'] = config.allow_maxshield

    raw = read_raw_bids(bids_path=bids_path, extra_params=extra_params)

    if subject != 'emptyroom':
        # Crop the data.
        if config.crop is not None:
            raw.crop(*config.crop)

        # Rename events.
        if config.rename_events:
            rename_events(raw=raw, subject=subject, session=session)

    raw.load_data()
    if hasattr(raw, 'fix_mag_coil_types'):
        raw.fix_mag_coil_types()

    montage_name = config.eeg_template_montage
    if config.get_datatype() == 'eeg' and montage_name:
        msg = (f'Setting EEG channel locatiions to template montage: '
               f'{montage_name}.')
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        montage = mne.channels.make_standard_montage(montage_name)
        raw.set_montage(montage, match_case=False, on_missing='warn')

    if config.ch_types == ['eeg'] and config.eeg_bipolar_channels:
        msg = 'Creating bipolar channels …'
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        raw.load_data()
        for ch_name, (anode, cathode) in config.eeg_bipolar_channels.items():
            msg = f'    {anode} – {cathode} -> {ch_name}'
            logger.info(
                gen_log_message(message=msg,
                                step=1,
                                subject=subject,
                                session=session))
            mne.set_bipolar_reference(raw,
                                      anode=anode,
                                      cathode=cathode,
                                      ch_name=ch_name,
                                      drop_refs=False,
                                      copy=False)

        # If we created a new bipolar channel that the user wishes to
        # use as an EOG channel, it is probably a good idea to set its channel
        # type to 'eog'. Bipolar channels, by default, don't have a location,
        # so one might get unexpected results otherwise, as the channel would
        # influence e.g. in GFP calculations, but not appear on topographic
        # maps.
        if any([
                eog_ch_name in config.eeg_bipolar_channels
                for eog_ch_name in config.eog_channels
        ]):
            msg = 'Setting channel type of new bipolar EOG channel(s) …'
            logger.info(
                gen_log_message(message=msg,
                                step=1,
                                subject=subject,
                                session=session))

        for eog_ch_name in config.eog_channels:
            if eog_ch_name in config.eeg_bipolar_channels:
                msg = f'    {eog_ch_name} -> eog'
                logger.info(
                    gen_log_message(message=msg,
                                    step=1,
                                    subject=subject,
                                    session=session))
                raw.set_channel_types({eog_ch_name: 'eog'})

    if config.drop_channels:
        msg = f'Dropping channels: {", ".join(config.drop_channels)}'
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        raw.drop_channels(config.drop_channels)

    return raw
예제 #13
0
def test_set_bipolar_reference():
    """Test bipolar referencing."""
    raw = read_raw_fif(fif_fname, preload=True)
    raw.apply_proj()

    reref = set_bipolar_reference(raw, 'EEG 001', 'EEG 002', 'bipolar',
                                  {'kind': FIFF.FIFFV_EOG_CH,
                                   'extra': 'some extra value'})
    assert (reref.info['custom_ref_applied'])

    # Compare result to a manual calculation
    a = raw.copy().pick_channels(['EEG 001', 'EEG 002'])
    a = a._data[0, :] - a._data[1, :]
    b = reref.copy().pick_channels(['bipolar'])._data[0, :]
    assert_allclose(a, b)

    # Original channels should be replaced by a virtual one
    assert ('EEG 001' not in reref.ch_names)
    assert ('EEG 002' not in reref.ch_names)
    assert ('bipolar' in reref.ch_names)

    # Check channel information
    bp_info = reref.info['chs'][reref.ch_names.index('bipolar')]
    an_info = reref.info['chs'][raw.ch_names.index('EEG 001')]
    for key in bp_info:
        if key == 'loc':
            assert_array_equal(bp_info[key], 0)
        elif key == 'coil_type':
            assert_equal(bp_info[key], FIFF.FIFFV_COIL_EEG_BIPOLAR)
        elif key == 'kind':
            assert_equal(bp_info[key], FIFF.FIFFV_EOG_CH)
        else:
            assert_equal(bp_info[key], an_info[key])
    assert_equal(bp_info['extra'], 'some extra value')

    # Minimalist call
    reref = set_bipolar_reference(raw, 'EEG 001', 'EEG 002')
    assert ('EEG 001-EEG 002' in reref.ch_names)

    # Minimalist call with twice the same anode
    reref = set_bipolar_reference(raw,
                                  ['EEG 001', 'EEG 001', 'EEG 002'],
                                  ['EEG 002', 'EEG 003', 'EEG 003'])
    assert ('EEG 001-EEG 002' in reref.ch_names)
    assert ('EEG 001-EEG 003' in reref.ch_names)

    # Set multiple references at once
    reref = set_bipolar_reference(
        raw,
        ['EEG 001', 'EEG 003'],
        ['EEG 002', 'EEG 004'],
        ['bipolar1', 'bipolar2'],
        [{'kind': FIFF.FIFFV_EOG_CH, 'extra': 'some extra value'},
         {'kind': FIFF.FIFFV_EOG_CH, 'extra': 'some extra value'}],
    )
    a = raw.copy().pick_channels(['EEG 001', 'EEG 002', 'EEG 003', 'EEG 004'])
    a = np.array([a._data[0, :] - a._data[1, :],
                  a._data[2, :] - a._data[3, :]])
    b = reref.copy().pick_channels(['bipolar1', 'bipolar2'])._data
    assert_allclose(a, b)

    # Test creating a bipolar reference that doesn't involve EEG channels:
    # it should not set the custom_ref_applied flag
    reref = set_bipolar_reference(raw, 'MEG 0111', 'MEG 0112',
                                  ch_info={'kind': FIFF.FIFFV_MEG_CH},
                                  verbose='error')
    assert (not reref.info['custom_ref_applied'])
    assert ('MEG 0111-MEG 0112'[:15] in reref.ch_names)

    # Test a battery of invalid inputs
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', ['EEG 002', 'EEG 003'], 'bipolar')
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  ['EEG 001', 'EEG 002'], 'EEG 003', 'bipolar')
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', 'EEG 002', ['bipolar1', 'bipolar2'])
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', 'EEG 002', 'bipolar',
                  ch_info=[{'foo': 'bar'}, {'foo': 'bar'}])
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', 'EEG 002', ch_name='EEG 003')
예제 #14
0
def test_set_bipolar_reference():
    """Test bipolar referencing."""
    raw = read_raw_fif(fif_fname, preload=True)
    raw.apply_proj()

    reref = set_bipolar_reference(raw, 'EEG 001', 'EEG 002', 'bipolar',
                                  {'kind': FIFF.FIFFV_EOG_CH,
                                   'extra': 'some extra value'})
    assert (reref.info['custom_ref_applied'])

    # Compare result to a manual calculation
    a = raw.copy().pick_channels(['EEG 001', 'EEG 002'])
    a = a._data[0, :] - a._data[1, :]
    b = reref.copy().pick_channels(['bipolar'])._data[0, :]
    assert_allclose(a, b)

    # Original channels should be replaced by a virtual one
    assert ('EEG 001' not in reref.ch_names)
    assert ('EEG 002' not in reref.ch_names)
    assert ('bipolar' in reref.ch_names)

    # Check channel information
    bp_info = reref.info['chs'][reref.ch_names.index('bipolar')]
    an_info = reref.info['chs'][raw.ch_names.index('EEG 001')]
    for key in bp_info:
        if key == 'loc':
            assert_array_equal(bp_info[key], 0)
        elif key == 'coil_type':
            assert_equal(bp_info[key], FIFF.FIFFV_COIL_EEG_BIPOLAR)
        elif key == 'kind':
            assert_equal(bp_info[key], FIFF.FIFFV_EOG_CH)
        else:
            assert_equal(bp_info[key], an_info[key])
    assert_equal(bp_info['extra'], 'some extra value')

    # Minimalist call
    reref = set_bipolar_reference(raw, 'EEG 001', 'EEG 002')
    assert ('EEG 001-EEG 002' in reref.ch_names)

    # Minimalist call with twice the same anode
    reref = set_bipolar_reference(raw,
                                  ['EEG 001', 'EEG 001', 'EEG 002'],
                                  ['EEG 002', 'EEG 003', 'EEG 003'])
    assert ('EEG 001-EEG 002' in reref.ch_names)
    assert ('EEG 001-EEG 003' in reref.ch_names)

    # Set multiple references at once
    reref = set_bipolar_reference(
        raw,
        ['EEG 001', 'EEG 003'],
        ['EEG 002', 'EEG 004'],
        ['bipolar1', 'bipolar2'],
        [{'kind': FIFF.FIFFV_EOG_CH, 'extra': 'some extra value'},
         {'kind': FIFF.FIFFV_EOG_CH, 'extra': 'some extra value'}],
    )
    a = raw.copy().pick_channels(['EEG 001', 'EEG 002', 'EEG 003', 'EEG 004'])
    a = np.array([a._data[0, :] - a._data[1, :],
                  a._data[2, :] - a._data[3, :]])
    b = reref.copy().pick_channels(['bipolar1', 'bipolar2'])._data
    assert_allclose(a, b)

    # Test creating a bipolar reference that doesn't involve EEG channels:
    # it should not set the custom_ref_applied flag
    reref = set_bipolar_reference(raw, 'MEG 0111', 'MEG 0112',
                                  ch_info={'kind': FIFF.FIFFV_MEG_CH},
                                  verbose='error')
    assert (not reref.info['custom_ref_applied'])
    assert ('MEG 0111-MEG 0112'[:15] in reref.ch_names)

    # Test a battery of invalid inputs
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', ['EEG 002', 'EEG 003'], 'bipolar')
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  ['EEG 001', 'EEG 002'], 'EEG 003', 'bipolar')
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', 'EEG 002', ['bipolar1', 'bipolar2'])
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', 'EEG 002', 'bipolar',
                  ch_info=[{'foo': 'bar'}, {'foo': 'bar'}])
    pytest.raises(ValueError, set_bipolar_reference, raw,
                  'EEG 001', 'EEG 002', ch_name='EEG 003')
예제 #15
0
                               'C32', 'EXG1', 'EXG2', 'EXG3', 'EXG4', 'EXG5', 'EXG6', 'EXG7', 'EXG8', 'GSR1', 'GSR2', 'Erg1', 'Erg2', 'Resp', 'Plet', 'Temp'])
    
    Data_rawEEG.rename_channels(mapping={'A1':'Fp1', 'A2':'AF7', 'A3':'AF3', 'A4':'F1', 'A5':'F3', 'A6':'F5', 'A7':'F7',
                                         'A8':'FT7', 'A9':'FC5', 'A10':'FC3', 'A11':'FC1', 'A12':'C1', 'A13':'C3', 'A14':'C5',
                                         'A15':'T7', 'A16':'TP7', 'A17':'CP5', 'A18':'CP3', 'A19':'CP1', 'A20':'P1', 'A21':'P3',                                     
                                         'A22':'P5', 'A23':'P7', 'A24':'P9', 'A25':'PO7', 'A26':'PO3', 'A27':'O1', 'A28':'Iz',
                                         'A29':'Oz', 'A30':'POz', 'A31':'Pz', 'A32':'CPz', 'B1':'Fpz', 'B2':'Fp2', 'B3':'AF8',                                  
                                         'B4':'AF4', 'B5':'AFz', 'B6':'Fz', 'B7':'F2', 'B8':'F4', 'B9':'F6', 'B10':'F8', 
                                         'B11':'FT8', 'B12':'FC6', 'B13':'FC4', 'B14':'FC2', 'B15':'FCz', 'B16':'Cz', 'B17':'C2',                                 
                                         'B18':'C4', 'B19':'C6', 'B20':'T8', 'B21':'TP8', 'B22':'CP6', 'B23':'CP4', 'B24':'CP2',  
                                         'B25':'P2', 'B26':'P4', 'B27':'P6', 'B28':'P8', 'B29':'P10', 'B30':'PO8', 'B31':'PO4',
                                         'B32':'O2','C1':'mastoidleft', 'C2':'mastoidright', 'C3':'HEOGleft','C4':'HEOGright',
                                         'C5':'VEOGup', 'C6':'VEOGdown','Status':'triggers'})

#VEOG< HEOG setup
    Data_rawEEG = mne.set_bipolar_reference(Data_rawEEG,anode='VEOGup',cathode='VEOGdown',ch_name='VEOG')
    Data_rawEEG = mne.set_bipolar_reference(Data_rawEEG,anode='HEOGleft',cathode='HEOGright',ch_name='HEOG')
    
    Data_rawEEG.set_channel_types({'VEOG':'eog','HEOG':'eog'})

## Setting EEG reference
    Data_rawEEG.set_eeg_reference(['mastoidleft','mastoidright'])

    Data_rawEEG.drop_channels(['mastoidleft','mastoidright'])



## Filter on data
    low_f = 0.1 #Low edge of the high-pass filter
    high_f = 30 #High edge of the low-pass filter
    picks_eeg_eog = mne.pick_types(Data_rawEEG.info, meg=False, eeg=True, eog=True) #select the eeg and the eog channels for filtering
예제 #16
0
raw = mne.io.read_raw_bdf(data_fname, preload=True)
raw = raw.pick(picks=[
    'EXG1', 'EXG2', 'EXG3', 'EXG4', 'EXG5', 'EXG6', 'EXG7', 'EXG8', 'Erg1',
    'Erg2', 'Status'
])
mne_events = mne.find_events(raw)

if name_subj == "S3":  #removes incpmleted trail for S3
    mne_events = mne_events[:-5]

mne_events[:, 2] = mne_events[:, 2] - mne_events[:, 1]

mne_events = np.array(
    [list(x) for x in mne_events if x[2] in initial_expctd_events])

mne.set_bipolar_reference(raw,anode=['EXG1','EXG3'], cathode=['EXG2','EXG4'],ch_name=['EMG_L','EMG_R'],\
copy=False)
raw.pick_channels(['EMG_L', 'EMG_R', 'Erg1', 'Erg2'])
raw.set_channel_types({
    'EMG_L': 'emg',
    'EMG_R': 'emg',
    'Erg1': 'misc',
    'Erg2': 'misc'
})

emg_channels_idx = {0: 'EMG_L', 1: 'EMG_R'}
force_channels_idx = {2: 'Erg1', 3: 'Erg2'}
channel_names = list(emg_channels_idx.values()) + list(
    force_channels_idx.values())

#Filtering
raw = dbt.use_mne.apply_filter(raw, ch_names=['EMG_L', 'EMG_R'], low_cutoff=10)
예제 #17
0
        nameBDF = f
        Trigger = [11, 21, 31, 41]
        #65314
        fname = os.path.join(pathBDF, nameBDF)
        #    raw = mne.io.read_raw_edf(fname,preload=True, verbose=True)
        raw = mne.io.read_raw_brainvision(fname,
                                          montage=None,
                                          eog=('HEOG_m', 'HEOG_p', 'VEOG_m',
                                               'VEOG_p'),
                                          misc='auto',
                                          scale=1.0,
                                          preload=True,
                                          verbose=True)
        raw
        mne.set_bipolar_reference(raw,anode=['EMGg_m','EMGd_m'],\
        cathode=['EMGg_p','EMGd_p'],ch_name=['EMG_L','EMG_R'],\
        copy=False)
        #        events = mne.find_events(raw, stim_channel = 'STI 014', min_duration=0.002, mask=2**24-64)
        events = mne.find_events(raw)
        raw.pick_channels(['EMG_L', 'EMG_R'])

        raw.set_channel_types({
            'EMG_L': 'emg',
            'EMG_R': 'emg',
            #        'EXG5' :'eog',
            #        'EXG6' :'eog',
            #        'Erg1' :'misc',
            #        'Erg2': 'misc',
            #             'STI 014': 'stim'
        })
예제 #18
0
            'C1': 'M1',
            'C2': 'M2',
            'C3': 'HEOGleft',
            'C4': 'HEOGright',
            'C5': 'VEOGup',
            'C6': 'VEOGdown',
            'Status': 'triggers'
        })

    # Setting channel montage
    montage = mne.channels.read_montage('biosemi64')
    raw.set_montage(montage)

    # Creating EOG channels
    raw = mne.set_bipolar_reference(raw,
                                    anode='VEOGup',
                                    cathode='VEOGdown',
                                    ch_name='VEOG')
    raw = mne.set_bipolar_reference(raw,
                                    anode='HEOGleft',
                                    cathode='HEOGright',
                                    ch_name='HEOG')
    raw.set_channel_types({'VEOG': 'eog', 'HEOG': 'eog'})

    # Setting reference (mastoids, but given different name for better electrode location)
    raw.set_eeg_reference(['M1', 'M2'])
    raw.drop_channels(['M1', 'M2'])
    # raw.set_eeg_reference(ref_channels='average')

    # # Investigating raw data (Identify bad channels and add to list above)
    # raw.plot()
    # raw.plot_psd(fmax=70)
예제 #19
0
def rereference(edf: mne.io.RawArray,
                desired_ref: str,
                current_ref: str = None,
                pick_chans: list = None) -> Tuple[mne.io.RawArray, str]:
    """
    reference an edf. M1 and M2 should be included, but NOT as eeg stype in the mne.io.RawArray.
    contra_mastoid reref will be undone if needed but this requires M1 and M2 PRIOR to any referencing.
    :param edf: edf to re-ref
    :param current_ref: current reference type, can be "contra_mastoid",'linked_ear' or a channel name
    :param desired_ref: current reference type, can be "contra_mastoid",'linked_ear' or a channel name.
    If None, assumed it is a common channels
    :return:
    """
    if pick_chans is None:
        chans = edf.ch_names
    else:
        chans = pick_chans
    if current_ref == desired_ref:
        return edf, current_ref

    if desired_ref in ['linked_ear'
                       ] and 'M1' not in chans or 'M2' not in chans:
        warnings.warn(
            'Trying to reference to linked ear, but missing M1 and M2 channels. EEG file will not be re-referenced',
            EEGWarning)
        return edf, current_ref

    if current_ref == 'contra_mastoid':
        to_reref = [ch for ch in chans if ch not in ['M1', 'M2']]
        left = [
            ch for ch in to_reref
            if len([n for n in ['1', '3', '5', '7', '9'] if n in ch]) > 0
        ]
        right = [
            ch for ch in to_reref
            if len([n for n in ['2', '4', '6', '8', '10'] if n in ch]) > 0
        ]
        if len(left) > 0 and 'M2' not in chans:
            warnings.warn(
                'Trying to reference to left channels to M2 ear, but missing M2 channel. left channels cannot be unreferenced'
            )
            left_ref = []
            left = []
        else:
            left_ref = ['M2'] * len(left)
        if len(right) > 0 and 'M1' not in chans:
            warnings.warn(
                'Trying to reference to right channels to M1 ear, but missing M1 channel. right channels cannot be unreferenced'
            )
            right_ref = []
            right = []
        else:
            right_ref = ['M1'] * len(right)
        edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2'])
        edf = mne.set_bipolar_reference(edf,
                                        left + right,
                                        left_ref + right_ref,
                                        drop_refs=False,
                                        verbose=False)
        edf = edf.drop_channels(left + right)
        edf.rename_channels({ch: ch.split('-')[0] for ch in edf.ch_names})
        edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2'])

    ref_type = desired_ref
    if desired_ref == 'contra_mastoid':
        if current_ref == 'linked_ear':
            edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2'])
            edf, _ = mne.set_eeg_reference(edf,
                                           ref_channels=['M1', 'M2'],
                                           verbose=False)
            edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2'])
        to_reref = [ch for ch in chans if ch not in ['M1', 'M2']]
        left = [
            ch for ch in to_reref
            if len([n for n in ['1', '3', '5', '7', '9', 'z'] if n in ch]) > 0
        ]
        right = [
            ch for ch in to_reref
            if len([n for n in ['2', '4', '6', '8', '10'] if n in ch]) > 0
        ]
        if len(left) > 0 and 'M2' not in chans:
            warnings.warn(
                'Trying to reference to left channels to M2 ear, but missing M2 channel. left channels will not be re-referenced'
            )
            left_ref = []
            left = []
            ref_type = 'contra_right_only'
        else:
            left_ref = ['M2'] * len(left)
        if len(right) > 0 and 'M1' not in chans:
            warnings.warn(
                'Trying to reference to right channels to M1 ear, but missing M1 channel. right channels will not be re-referenced'
            )
            right_ref = []
            right = []
            ref_type = 'contra_left_only'
        else:
            right_ref = ['M1'] * len(right)
        edf = mne.set_bipolar_reference(edf,
                                        left + right,
                                        left_ref + right_ref,
                                        drop_refs=False,
                                        verbose=False)
        edf = edf.drop_channels(left + right)
        edf.rename_channels({ch: ch.split('-')[0] for ch in edf.ch_names})
    elif desired_ref == 'linked_ear':
        edf, _ = mne.set_eeg_reference(edf,
                                       ref_channels=['M1', 'M2'],
                                       verbose=False)
    else:
        edf, _ = mne.set_eeg_reference(edf,
                                       ref_channels=desired_ref,
                                       verbose=False)

    return edf, ref_type
# %%
# Using a bipolar reference
# ^^^^^^^^^^^^^^^^^^^^^^^^^
#
# To create a bipolar reference, you can use :meth:`~mne.set_bipolar_reference`
# along with the respective channel names for ``anode`` and ``cathode`` which
# creates a new virtual channel that takes the difference between two
# specified channels (anode and cathode) and drops the original channels by
# default. The new virtual channel will be annotated with the channel info of
# the anode with location set to ``(0, 0, 0)`` and coil type set to
# ``EEG_BIPOLAR`` by default. Here we use a contralateral/transverse bipolar
# reference between channels ``EEG 054`` and ``EEG 055`` as described in
# :footcite:`YaoEtAl2019` which creates a new virtual channel
# named ``EEG 054-EEG 055``.

raw_bip_ref = mne.set_bipolar_reference(raw, anode=['EEG 054'],
                                        cathode=['EEG 055'])
raw_bip_ref.plot()

# %%
# EEG reference and source modeling
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# If you plan to perform source modeling (either with EEG or combined EEG/MEG
# data), it is **strongly recommended** to use the
# average-reference-as-projection approach. It is important to use an average
# reference because using a specific
# reference sensor (or even an average of a few sensors) spreads the forward
# model error from the reference sensor(s) into all sensors, effectively
# amplifying the importance of the reference sensor(s) when computing source
# estimates. In contrast, using the average of all EEG channels as reference
# spreads the forward modeling error evenly across channels, so no one channel
예제 #21
0
anodes = [
    'T1', 'Fp1', 'F7', 'T3', 'T5', 'F3', 'T3', 'Fz', 'Cz', 'F4', 'T4', 'Fp2',
    'F8', 'T4', 'T6', 'T2'
]
cathodes = [
    'A1', 'F7', 'T3', 'T5', 'O1', 'T3', 'P3', 'Cz', 'Pz', 'T4', 'P4', 'F8',
    'T4', 'T6', 'O2', 'A2'
]

#Read and set original montage
montage = mne.channels.make_standard_montage('standard_postfixed')
epochs.set_montage(montage, raise_if_subset=False)

# Set bipolar montage
epochs_bipolar = mne.set_bipolar_reference(epochs,
                                           anodes,
                                           cathodes,
                                           drop_refs=False)

# Removing old channels (keeping only biploar)
epochs_bipolar.picks = None
epochs_bipolar.drop_channels(epochs.info['ch_names'])

#Print info for bipolar (double banana) reference raw data
print(epochs_bipolar)
print(epochs_bipolar.info['ch_names'])

# =============================================================================
# # reordering bipolar channels (given original setup of channels)
# ch_order = ['Fp1-F7', 'F7-T3', 'T3-T5', 'T5-O1',
#             'Fp1-F3', 'F3-C3', 'C3-P3', 'P3-O1',
#             'Fz-Cz', 'Cz-Pz',
예제 #22
0
def preprocess(raw):
    ## Input Variables ##############################
    trialLen = 1 # Number of seconds per trial
    #cutoff = 0.5 # Cut first/last .5 seconds from each 
    downsample_fs = 1500 # What frequency to downsample to
    ##################################################

    # Filter
    raw.filter(0.1, 200)

    # data resample
    raw.resample(downsample_fs)

    # Cut data into trials (epochs) mne.EpochsArray
    picks = mne.pick_types(raw.info, eeg=True)
    data, times = raw[:]
    events = mne.find_events(raw)

    # Make trial events
    trialSamps = downsample_fs * trialLen
    dataShape = data.shape
    overflow = dataShape[1] % trialSamps
    # MNE forces you to use events to set timing for trials
    # Create events with event_id=9 for trial start timings (after our 1-8 ttls)
    trialEvents = []
    n = int(raw.first_time) + 1
    while n <= dataShape[1] - overflow + 1:
        trialEvents.append([n, 0, 9]) # [timestamp, N/A, event_id]
        n += trialSamps
    
    raw.add_events(np.array(trialEvents), stim_channel='TTL') # adding our trial events
    events = mne.find_events(raw)

    # Split into trials based on trial events
    processedObj = mne.Epochs(raw, events, event_id=9, tmin = 0.0, tmax = trialLen, baseline = None, preload=True)

    scalings = {'eeg':2000}

    # Plot to look for bad trials/channesl
    processedObj.plot(scalings = scalings, n_epochs = 2, show=True, block=True)
    print(processedObj)
    
    # Bipolar ref
    bi1 = []
    bi2 = []
    for n in range(0,16, 2):
        if 'CH'+str(n) not in processedObj.info['bads']:
            bi1.append(processedObj.ch_names[n])
        if 'CH'+str(n+1) not in processedObj.info['bads']:
            bi2.append(processedObj.ch_names[n+1])
    print(bi1, bi2)

    if len(processedObj.info['bads']) > 0:
        print('Some bad channels')

    print(processedObj.ch_names)

    # Bipolar based upon channel names
    processedObj = mne.set_bipolar_reference(processedObj, bi1, bi2)

    return processedObj
예제 #23
0
def load_data(bids_path):
    # read_raw_bids automatically
    # - populates bad channels using the BIDS channels.tsv
    # - sets channels types according to BIDS channels.tsv `type` column
    # - sets raw.annotations using the BIDS events.tsv

    subject = bids_path.subject
    session = bids_path.session

    extra_params = dict()
    if config.allow_maxshield:
        extra_params['allow_maxshield'] = config.allow_maxshield

    raw = read_raw_bids(bids_path=bids_path, extra_params=extra_params)

    if subject != 'emptyroom':
        # Crop the data.
        if config.crop is not None:
            raw.crop(*config.crop)

        # Rename events.
        if config.rename_events:
            rename_events(raw=raw, subject=subject, session=session)

    raw.load_data()
    if hasattr(raw, 'fix_mag_coil_types'):
        raw.fix_mag_coil_types()

    montage_name = config.eeg_template_montage
    if config.get_datatype() == 'eeg' and montage_name:
        msg = (f'Setting EEG channel locatiions to template montage: '
               f'{montage_name}.')
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        montage = mne.channels.make_standard_montage(montage_name)
        raw.set_montage(montage, match_case=False, on_missing='warn')

    if config.ch_types == ['eeg'] and config.eeg_bipolar_channels:
        msg = 'Creating bipolar channels …'
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        raw.load_data()
        for ch_name, (anode, cathode) in config.eeg_bipolar_channels.items():
            msg = f'    {anode} – {cathode} -> {ch_name}'
            logger.info(
                gen_log_message(message=msg,
                                step=1,
                                subject=subject,
                                session=session))
            mne.set_bipolar_reference(raw,
                                      anode=anode,
                                      cathode=cathode,
                                      ch_name=ch_name,
                                      drop_refs=False,
                                      copy=False)

    if config.drop_channels:
        msg = f'Dropping channels: {", ".join(config.drop_channels)}'
        logger.info(
            gen_log_message(message=msg,
                            step=1,
                            subject=subject,
                            session=session))
        raw.drop_channels(config.drop_channels)

    return raw
예제 #24
0
def sync_matlab_and_eeg_events(edf_filename: str,
                               timing_filename: str,
                               event_filename: str = None,
                               init_slice: int = None) -> object:
    """Syncs the matlab events with times in the EEG data, returns imported eeg raw eeg and events"""
    sample_rate = 128

    channels_to_exclude = [
        'COUNTER', 'INTERPOLATED', 'RAW_CQ', 'GYROX', 'GYROY', 'MARKER',
        'MARKER_HARDWARE', 'SYNC', 'TIME_STAMP_s', 'TIME_STAMP_ms'
    ]

    impedance_channel_map = {
        'CQ_AF3': 'im_F8',
        'CQ_F7': 'im_F5',
        'CQ_F3': 'im_Cz',
        'CQ_FC5': 'im_C3',
        'CQ_T7': 'im_Fz',
        'CQ_P7': 'im_Sync1',
        'CQ_O1': 'im_F7',
        'CQ_O2': 'im_Sync2',
        'CQ_P8': 'im_P7',
        'CQ_T8': 'im_P3',
        'CQ_FC6': 'im_P8',
        'CQ_F4': 'im_Oz',
        'CQ_F8': 'im_Pz',
        'CQ_AF4': 'im_P4',
        'CQ_CMS': 'im_CMS',
        'CQ_DRL': 'im_DRL'
    }

    channel_map = {
        'O1': 'F7',
        'P7': 'Sync1',
        'T7': 'Fz',
        'F7': 'F5',
        'AF3': 'F8',
        'FC5': 'C3',
        'F3': 'Cz',
        'O2': 'Sync2',
        'P8': 'P7',
        'T8': 'P3',
        'F8': 'Pz',
        'AF4': 'P4',
        'FC6': 'P8',
        'F4': 'Oz'
    }

    data_channels = [value for key, value in channel_map.items()]
    immedence_channels = [
        value for key, value in impedance_channel_map.items()
    ]

    channel_map.update(impedance_channel_map)

    raw_edf = mne.io.read_raw_edf(edf_filename,
                                  stim_channel=None,
                                  exclude=channels_to_exclude)
    try:
        raw_edf.load_data()
    except IndexError:
        warnings.warn("Failed to load data, skipping subject")
        return
    raw_edf.rename_channels(channel_map)
    raw_edf = mne.set_bipolar_reference(raw_edf, "Sync1", "Sync2", "SyncRR")
    sync_channel0 = raw_edf.copy().pick_channels(["SyncRR"])

    raw_im = raw_edf.copy().pick_channels(immedence_channels)
    raw_edf.pick_channels(data_channels)

    ##Process sync channels
    data, times = sync_channel0[:]  # Extract data
    data = data.transpose()
    data = zscore(data)  # normalize
    times -= init_slice
    data = data[times > 0]
    times = times[times > 0]
    # plt.plot(np.asarray(times), data)
    # plt.show()
    diff_data_raw = np.insert(np.diff(data, axis=0), 0, 0)
    diff_data = diff_data_raw.copy()
    threshold_moving = window_stdev(
        diff_data, 5000) * 3.5  # Calculate a moving threshold by
    diff_data[np.where((diff_data > -threshold_moving)
                       & (diff_data < threshold_moving))] = 0  # Threshold
    diff_data[np.where(
        diff_data < 0)] = -diff_data[np.where(diff_data < 0)]  # Rectify

    # plt.plot(np.asarray(times), diff_data)
    eeg_times = detect_peaks(diff_data, mph=0.2)
    eeg_times_edge = np.where(diff_data_raw[eeg_times] > 0, 1,
                              0)  # rising edge is 1
    rising = eeg_times[eeg_times_edge == 1]
    falling = eeg_times[eeg_times_edge == 0]
    # plt.plot(rising / sample_rate, np.ones(rising.shape), '*')
    # plt.plot(falling / sample_rate, np.ones(falling.shape), '*')
    eeg_times_secs = eeg_times / sample_rate

    event_data = pd.read_excel(timing_filename)
    event_data = event_data[['label', 'getSecsLogTime', 'realTime']]
    event_data.columns = ["label", "matlab_time", 'datetime']
    event_data['matlab_time'] -= event_data['matlab_time'][0]  # Start at zero
    event_data['eeg_time'] = np.nan

    recogRespTimes = event_data.label.apply(
        lambda lab: 'recogRespTime' not in lab)
    event_data_working = add_expected_transitions(event_data[recogRespTimes])
    max_expected_lag = 5  # Initial Differences between matlab and eeg should not be more than 5

    event_data_working['label_generic'] = event_data_working['label'].apply(
        lambda lab: lab[0:lab.rfind("_")])

    # from collections import defaultdict
    # time_testing_dict = defaultdict(list)

    event_data.set_index('label', inplace=True, drop=False)

    matlab_labels = event_data_working['label_generic'].unique()
    for label in matlab_labels:
        timing_data_slice = event_data_working[
            label == event_data_working['label_generic']]
        print("For", label, "attempting to find",
              len(timing_data_slice.matlab_time), "events")
        # plt.figure()
        # plt.plot(timing_data_slice.matlab_time, np.ones(len(timing_data_slice.matlab_time)), '*')
        # a = eeg_times_secs[(eeg_times_secs < (timing_data_slice.matlab_time.iloc[-1] + max_expected_lag)) & (
        # eeg_times_secs > (timing_data_slice.matlab_time.iloc[0] - max_expected_lag))]
        # plt.plot(a, np.ones(len(a)), '*')
        # plt.show()
        expected_diff = np.diff(timing_data_slice.matlab_time)
        if label in ['syncDataLight_BeforeInter_flipTime']:
            sync_idx, sync_lag = find_template_in_sequence(
                eeg_times_secs, eeg_times_edge, expected_diff,
                timing_data_slice.trans_bool, 0, eeg_times_secs[-1] / 4)
            if sync_idx is None:
                warnings.warn('Did not fine sync signal. Terminating....')
                return
            eeg_times_secs = eeg_times_secs[sync_idx[0]:] - sync_lag
            eeg_times_edge = eeg_times_edge[sync_idx[0]:]
            lag_eeg_to_matlab = sync_lag
            print('Found start at', sync_lag)
            sync_idx = range(0, len(sync_idx))
        else:
            sync_idx, sync_lag = find_template_in_sequence(
                eeg_times_secs, eeg_times_edge, expected_diff,
                timing_data_slice.trans_bool,
                timing_data_slice.matlab_time.iloc[0] - max_expected_lag,
                timing_data_slice.matlab_time.iloc[-1] + max_expected_lag)
            # Linearly increasing lag
            max_expected_lag = 5 + 0.01 * timing_data_slice.matlab_time.iloc[-1]

        if sync_idx is None:
            print('Did not find all points for', label)
            continue

        # for key, val in time_testing.items():
        #     time_testing_dict[key].extend(val)

        # print("Found", len(sync_idx), "events at", sync_lag)
        for lab, val in zip(timing_data_slice.label, eeg_times_secs[sync_idx]):
            event_data.set_value(lab, 'eeg_time', val)

    event_data = add_event_data_missing_sync(event_data)
    event_data.sort_values('matlab_time', inplace=True)

    events = interpolate_missing(event_data)
    events['type'] = events['label'].apply(lambda lab: lab[0:lab.rfind("_")])
    events['eeg_samples'] = events['eeg_time'] * sample_rate
    events.set_index('type', inplace=True, drop=False)
    events.lag_eeg_to_matlab = lag_eeg_to_matlab
    events.to_csv(event_filename)

    # times -= lag_eeg_to_matlab
    # data = data[times > 0]
    # times = times[times > 0]
    # plot_sync_times(data, times, event_data)
    eeg = DotDict({})
    eeg.raw = raw_edf
    eeg.impedance = raw_im
    slice_and_add_eeg_montage(eeg, lag_eeg_to_matlab)  #Modifies inplace

    return eeg, events