示例#1
0
def test_to_data_frame(fname):
    """Test EDF/BDF Raw Pandas exporter."""
    ext = op.splitext(fname)[1][1:].lower()
    if ext == 'edf':
        raw = read_raw_edf(fname, preload=True, verbose='error')
    elif ext == 'bdf':
        raw = read_raw_bdf(fname, preload=True, verbose='error')
    _, times = raw[0, :10]
    df = raw.to_data_frame()
    assert (df.columns == raw.ch_names).all()
    assert_array_equal(np.round(times * 1e3), df.index.values[:10])
    df = raw.to_data_frame(index=None, scalings={'eeg': 1e13})
    assert 'time' in df.index.names
    assert_array_equal(df.values[:, 0], raw._data[0] * 1e13)
示例#2
0
def test_load_generator(fname, recwarn):
    """Test IO of annotations from edf and bdf files with raw info."""
    ext = op.splitext(fname)[1][1:].lower()
    if ext == 'edf':
        raw = read_raw_edf(fname)
    elif ext == 'bdf':
        raw = read_raw_bdf(fname)
    assert len(raw.annotations.onset) == 2
    found_types = [k for k, v in
                   channel_indices_by_type(raw.info, picks=None).items()
                   if v]
    assert len(found_types) == 1
    events, event_id = events_from_annotations(raw)
    ch_names = ['squarewave', 'ramp', 'pulse', 'ECG', 'noise', 'sine 1 Hz',
                'sine 8 Hz', 'sine 8.5 Hz', 'sine 15 Hz', 'sine 17 Hz',
                'sine 50 Hz']
    assert raw.get_data().shape == (11, 120000)
    assert raw.ch_names == ch_names
    assert event_id == {'RECORD START': 2, 'REC STOP': 1}
    assert_array_equal(events, [[0, 0, 2], [120000, 0, 1]])
示例#3
0
def test_bdf_crop_save_stim_channel(tmpdir):
    """Test EDF with various sampling rates."""
    raw = read_raw_bdf(bdf_stim_channel_path)
    raw.save(tmpdir.join('test-raw.fif'), tmin=1.2, tmax=4.0, overwrite=True)
示例#4
0
# channels to be exclude from import
exclude = ['EXG5', 'EXG6', 'EXG7', 'EXG8']

# ========================================================================
# --------- loop through files and make bids-files blocks  ---------------
for ind, file in enumerate(files):

    # --- 1) set up paths and file names -----------------------
    filepath, filename = os.path.split(file)
    # subject in question
    subj = re.findall(r'\d+', filename)[0].rjust(3, '0')

    # --- 2) import the data -----------------------------------
    raw = read_raw_bdf(file,
                       preload=False,
                       exclude=exclude)

    # --- 3) dataset info --------------------------------------
    # keep the sampling rate
    sfreq = raw.info['sfreq']
    # all channels in raw
    chans = raw.info['ch_names']
    # channels in montage
    montage_chans = montage.ch_names
    # nr of eeg channels
    n_eeg = len([chan for chan in chans if chan in montage_chans])
    # channel types
    types = []
    for chan in chans:
        if chan in montage_chans:
示例#5
0
def copyfile_edf(src, dest, anonymize=None):
    """Copy an EDF, EDF+, or BDF file to a new location, optionally anonymize.

    .. warning:: EDF/EDF+/BDF files contain two fields for recording dates:
                 A generic "startdate" field that supports only 2-digit years,
                 and a "Startdate" field as part of the "local recording
                 identification", which supports 4-digit years.
                 If you want to anonymize your file, MNE-BIDS will set the
                 "startdate" field to 85 (i.e., 1985), the earliest possible
                 date for that field. However, the "Startdate" field in the
                 file's "local recording identification" and the date in the
                 session's corresponding ``scans.tsv`` will be set correctly
                 according to the argument provided to the ``anonymize``
                 parameter. Note that it is possible that not all EDF/EDF+/BDF
                 reading software parses the accurate recording date, and
                 that for some reading software, the wrong year (1985) may
                 be parsed.

    Parameters
    ----------
    src : str | pathlib.Path
        The source path of the .edf or .bdf file to be copied.
    dest : str | pathlib.Path
        The destination path of the .edf or .bdf file.
    anonymize : dict | None
        If None (default), no anonymization is performed.
        If dict, data will be anonymized depending on the keys provided with
        the dict: `daysback` is a required key, `keep_his` is an optional key.

        `daysback` : int
            Number of days by which to move back the recording date in time.
            In studies with multiple subjects the relative recording date
            differences between subjects can be kept by using the same number
            of `daysback` for all subject anonymizations. `daysback` should be
            great enough to shift the date prior to 1925 to conform with BIDS
            anonymization rules. Due to limitations of the EDF/BDF format, the
            year of the anonymized date will always be set to 1985 in the
            'startdate' field of the file. The correctly-shifted year will be
            written to the 'local recording identification' region of the
            file header, which may not be parsed by all EDF/EDF+/BDF reader
            softwares.

        `keep_his` : bool
            By default (False), all subject information next to the recording
            date will be overwritten as well. If True, keep subject information
            apart from the recording date. Participant names and birthdates
            will always be anonymized if present, regardless of this setting.

    See Also
    --------
    mne.io.anonymize_info
    copyfile_brainvision
    copyfile_bti
    copyfile_ctf
    copyfile_eeglab
    copyfile_kit

    """
    # Ensure source & destination extensions are the same
    fname_src, ext_src = _parse_ext(src)
    fname_dest, ext_dest = _parse_ext(dest)
    if ext_src != ext_dest:
        raise ValueError(f'Need to move data with same extension, '
                         f' but got "{ext_src}" and "{ext_dest}"')

    # Copy data prior to any anonymization
    sh.copyfile(src, dest)

    # Anonymize EDF/BDF data, if requested
    if anonymize is not None:
        if ext_src == '.bdf':
            raw = read_raw_bdf(dest, preload=False, verbose=0)
        elif ext_src == '.edf':
            raw = read_raw_edf(dest, preload=False, verbose=0)
        else:
            raise ValueError('Unsupported file type ({0})'.format(ext_src))

        # Get subject info, recording info, and recording date
        with open(dest, 'rb') as f:
            f.seek(8)  # id_info field starts 8 bytes in
            id_info = f.read(80).decode('ascii').rstrip()
            rec_info = f.read(80).decode('ascii').rstrip()

        # Parse metadata from file
        if len(id_info) == 0 or len(id_info.split(' ')) != 4:
            id_info = "X X X X"
        if len(rec_info) == 0 or len(rec_info.split(' ')) != 5:
            rec_info = "Startdate X X X X"
        pid, sex, birthdate, name = id_info.split(' ')
        start_date, admin_code, tech, equip = rec_info.split(' ')[1:5]

        # Try to anonymize the recording date
        daysback, keep_his = _check_anonymize(anonymize, raw, '.edf')
        anonymize_info(raw.info, daysback=daysback, keep_his=keep_his)
        start_date = '01-JAN-1985'
        meas_date = '01.01.85'

        # Anonymize ID info and write to file
        if keep_his:
            # Always remove participant birthdate and name to be safe
            id_info = [pid, sex, "X", "X"]
            rec_info = ["Startdate", start_date, admin_code, tech, equip]
        else:
            id_info = ["0", "X", "X", "X"]
            rec_info = ["Startdate", start_date, "X",
                        "mne-bids_anonymize", "X"]
        with open(dest, 'r+b') as f:
            f.seek(8)  # id_info field starts 8 bytes in
            f.write(bytes(" ".join(id_info).ljust(80), 'ascii'))
            f.write(bytes(" ".join(rec_info).ljust(80), 'ascii'))
            f.write(bytes(meas_date, 'ascii'))
from config import fname, task_name, montage, parser, LoggingFormat

###############################################################################
# Start processing step

# Handle command line arguments
args = parser.parse_args()
subject = args.subject

print(LoggingFormat.PURPLE + LoggingFormat.BOLD +
      'Converting to BIDS: Subject %s' % subject + LoggingFormat.END)

###############################################################################
# 1) Import the data
input_file = fname.source(source_type='eeg', subject=subject)
raw = read_raw_bdf(input_file, preload=False)

# sampling rate
sfreq = raw.info['sfreq']
# channels in dataset
channels = raw.info['ch_names']

###############################################################################
# 2) Modify dataset info
# identify channel types based on matching names in montage
types = []
for channel in channels:
    if channel in montage.ch_names:
        types.append('eeg')
    elif channel.startswith('EOG') | channel.startswith('EXG'):
        types.append('eog')
示例#7
0
def importbdf(bdfname,
              nchans=34,
              refchans=['EXG1', 'EXG2'],
              hptsname=None,
              mask=255,
              extrachans=[],
              exclude=[],
              verbose=None):
    """Wrapper around mne-python to import BDF files

    Parameters
    ----------

    bdfname - Name of the biosemi .bdf filename with full path

    nchans -  Number of EEG channels (including references)
              (Optional) By default, 34 (32 + 2 references)
    refchans - list of strings with reference channel names
               (Optional) By default ['EXG1','EXG2'].
               Use None for average reference.
    hptsname - Name of the electrode position file in .hpts format with path
               (Optional) By default a 32 channel Biosemi layout is used. If
               the nchans is >= 64 and < 96, a 64 channel Biosemi layout is
               used. If nchans >= 96, a 96 channel biosemi layout is used.
               Formats other than .hpts will also likely work, but behavior
               may vary.
    mask - Integer mask to use for trigger channel (Default is 255).
    extrachans - Additional channels other than EEG and EXG that may be in the
                 bdf file. These will be marked as MISC in mne-python.
                 Specify as list of names.
    exclude - List of channel names to exclude from importing
    verbose - bool, str, int, or None (Optional)
        The verbosity of messages to print. If a str, it can be either DEBUG,
        INFO, WARNING, ERROR, or CRITICAL.

    Returns
    -------
    raw - MNE raw data object of rereferences and preloaded data

    eves - Event list (3 column array as required by mne.Epochs)

    Requires
    --------
    mne-python module > release 0.7
    """

    # Default HPTS file
    if (hptsname is None):
        anlffr_root = os.path.dirname(sys.modules['anlffr'].__file__)
        if nchans >= 64 and nchans < 96:
            logger.info('Number of channels is greater than 64.'
                        ' Hence loading a 64 channel montage.')
            hptspath = os.path.join(anlffr_root, 'helper/sysfiles/')
            hptsname = 'biosemi64.hpts'
            montage = read_dig_hpts(hptspath + hptsname)
            misc = ['EXG3', 'EXG4', 'EXG5', 'EXG6', 'EXG7', 'EXG8']
        else:
            if nchans >= 96:
                logger.info('Number of channels is greater than 96.'
                            ' Hence loading a 96 channel montage.')
                hptspath = os.path.join(anlffr_root, 'helper/sysfiles/')
                hptsname = 'biosemi96.hpts'
                montage = read_dig_hpts(hptspath + hptsname)
                misc = ['EXG3', 'EXG4', 'EXG5', 'EXG6', 'EXG7', 'EXG8']
            else:
                if nchans == 2:
                    logger.info('Number of channels is 2.'
                                'Guessing ABR montage or saccades.')
                    montage = None
                    misc = []
                else:
                    logger.info('Loading a default 32 channel montage.')
                    hptspath = os.path.join(anlffr_root, 'helper/sysfiles/')
                    hptsname = 'biosemi32.hpts'
                    montage = read_dig_hpts(hptspath + hptsname)
                    misc = ['EXG3', 'EXG4', 'EXG5', 'EXG6', 'EXG7', 'EXG8']
    else:
        montage = read_dig_hpts(hptsname)  # User-supplied
        misc = ['EXG3', 'EXG4', 'EXG5', 'EXG6', 'EXG7', 'EXG8']

    misc += extrachans
    raw = read_raw_bdf(bdfname,
                       preload=True,
                       misc=misc,
                       exclude=exclude,
                       stim_channel='auto')
    raw.set_montage(montage, on_missing='warn')

    # Rereference
    if refchans is not None:
        sys.stdout.write('Re-referencing data to: ' + ' '.join(refchans))
        (raw, ref_data) = set_eeg_reference(raw, refchans, copy=False)
        raw.info['bads'] += refchans
    else:
        # Add average reference operator for possible use later
        ave_ref_operator = make_eeg_average_ref_proj(raw.info, activate=False)
        raw = raw.add_proj(ave_ref_operator)

    eves = find_events(raw, shortest_event=1, mask=mask)

    return (raw, eves)
montage = make_standard_montage(kind='standard_1020')
# channels to be exclude from import
exclude = ['EXG5', 'EXG6', 'EXG7', 'EXG8']

# ========================================================================
# ------------ loop through files and extract blocks  --------------------
for file in files:

    # --- 1) set up paths and file names -----------------------
    filepath, filename = op.split(file)
    # subject in question
    subj = re.findall(r'\d+', filename)[0].rjust(3, '0')
    print(subj)

    # --- 2) import the data -----------------------------------
    raw = read_raw_bdf(file, preload=True, exclude=exclude)

    # check data and remove channel with low (i.e., near zero variance)
    flats = np.where(np.std(raw.get_data(), axis=1) * 1e6 < 10.)[0]
    # names
    flats = [raw.ch_names[ch] for ch in flats]
    # print summary
    print('Following channels were dropped as variance ~ 0:', flats)
    # remove them from data set
    raw.drop_channels(flats)

    # --- 3) modify data set information  ----------------------
    # keep the sampling rate
    sfreq = raw.info['sfreq']
    # and date of measurement
    date_of_record = raw.annotations.orig_time
示例#9
0
clip = None

# === LOOP THROUGH FILES AND RUN PRE-PROCESSING ==========================
for file in files:

    # --- 1) Set up paths and file names -----------------------
    filepath, filename = os.path.split(file)
    filename, ext = os.path.splitext(filename)

    subj = re.findall(r'\d+', filename)[0]

    # --- 2) READ IN THE DATA ----------------------------------
    # Set EEG arrangement
    montage = read_montage(kind='biosemi64')
    # Import raw data
    raw = read_raw_bdf(file, montage=montage, preload=True, exclude=exclude)

    # Note the sampling rate of recording
    sfreq = raw.info['sfreq']
    # all channels in raw
    chans = raw.info['ch_names']
    # channels in montage
    montage_chans = montage.ch_names
    # nr of eeg channels
    n_eeg = len([chan for chan in chans if chan in montage_chans])
    # channel types
    types = []
    for chan in chans:
        if chan in montage_chans:
            types.append('eeg')
        elif re.match('EOG|EXG', chan):