Module xelo2.bids.io.dataglove

Expand source code
from pandas import read_csv, to_datetime
from logging import getLogger


lg = getLogger(__name__)


def parse_dataglove_log(dg_file):
    hdr = {
        'SamplingFrequency': None,
        'StartTime': 0,
    }

    possible_hand = {
        'right': 0,
        'left': 0,
        }
    with dg_file.open() as f:

        skiprows = 0
        log_format = 'qttasks'
        names = ['time', 'thumb', 'index', 'middle', 'ring', 'little']

        for i, l in enumerate(f):

            possible_hand['right'] += l.lower().count('right')
            possible_hand['left'] += l.lower().count('left')

            if 'event' in l:
                skiprows = i
                log_format = 'neurobs'  # log from presentation
                names = None

            if 'Onset:' in l:
                skiprows = i
                log_format = 'finger_mapping'  # log from finger mapping c-code
                names = None

    df = read_csv(dg_file, skiprows=skiprows, delimiter=r'\s+', names=names)

    """convert the log file into df with columns:
    time, left thumb, left index, ..., right thumb, ..., right little

    with 'time' im ms
    """
    if log_format == 'neurobs':
        df, hdr['StartTime'] = _fix_neurobs_log(df)
        df['time'] = df['time'].apply(lambda x: x / 1000)
    elif log_format == 'finger_mapping':
        df = _fix_fingermapping(df)
        df['time'] = df['time'].apply(lambda x: x / 1000)
    elif log_format == 'qttasks':
        df, hdr['StartTime'] = _fix_qttask(df)
        possible_hand['right'] = 1  # assume it's right-hand TODO: how to estimate which hand

    if len(df.columns) < 10:
        df = _select_from_one_hand(df, possible_hand)
        if df is None:
            lg.warning(f'Unknown hand side for {dg_file}')

    else:
        df = _select_from_two_hands(df)

    t = df['time'].values
    fs = 1 / ((t[-1] - t[0]) / t.shape[0])
    hdr['SamplingFrequency'] = float('%.3f' % (fs))

    hdr['Columns'] = list(df.columns)

    return df, hdr


def _fix_qttask(df):
    t = to_datetime(df['time'])
    start_time = t[0]
    t = t - t[0]
    df['time'] = t.dt.total_seconds()
    return df, start_time


def _fix_neurobs_log(df):
    df.set_index('event', inplace=True)
    starttime = df.loc['start', 'time'].item()

    df.drop('var', axis=1, inplace=True)
    df.rename(index=str, columns=_expand_l_r, inplace=True)

    df.drop(['start', 'sampleinterval', 'scan', 'samplerate'], axis=0, inplace=True, errors='ignore')

    df = df[df.columns.tolist()[-1:] + df.columns.tolist()[:-1]]

    df.drop_duplicates(inplace=True)
    df.reset_index(drop=True, inplace=True)

    return df, starttime


def _fix_fingermapping(df):

    df.rename(index=str, columns={"Onset:": "time"}, inplace=True)
    df.rename(index=str, columns=_expand_l_r, inplace=True)

    return df


def _expand_l_r(s):
    if s.endswith(':'):
        s = s[:-1].lower()

    if s.startswith('l_'):
        return 'left ' + s[2:]

    elif s.startswith('r_'):
        return 'right ' + s[2:]

    else:
        return s


def _select_from_one_hand(df, possible_hand):

    left_hand = sum([1 for col in df.columns if 'left' in col.lower()])
    right_hand = sum([1 for col in df.columns if 'right' in col.lower()])

    if left_hand == 0 and right_hand == 0:
        if possible_hand['right'] > possible_hand['left']:
            hand_side = 'right'
        elif possible_hand['right'] < possible_hand['left']:
            hand_side = 'left'
        else:
            return None

    columns = []
    for col in df.columns:
        if col != 'time':
            col = hand_side + ' ' + col
        columns.append(col)
    df.columns = columns

    return df

def _select_from_two_hands(df):
    lefthand = (
        df.loc[:, 'left thumb'].sum()
        + df.loc[:, 'left index'].sum()
        + df.loc[:, 'left middle'].sum()
        + df.loc[:, 'left ring'].sum()
        + df.loc[:, 'left little'].sum() != 0)

    righthand = (
        df.loc[:, 'right thumb'].sum()
        + df.loc[:, 'right index'].sum()
        + df.loc[:, 'right middle'].sum()
        + df.loc[:, 'right ring'].sum()
        + df.loc[:, 'right little'].sum() != 0)

    if not righthand:
        df.drop([
            'right thumb',
            'right index',
            'right middle',
            'right ring',
            'right little',
        ], axis='columns', inplace=True)

    if not lefthand:
        df.drop([
            'left thumb',
            'left index',
            'left middle',
            'left ring',
            'left little',
        ], axis='columns', inplace=True)

    return df

Functions

def parse_dataglove_log(dg_file)
Expand source code
def parse_dataglove_log(dg_file):
    hdr = {
        'SamplingFrequency': None,
        'StartTime': 0,
    }

    possible_hand = {
        'right': 0,
        'left': 0,
        }
    with dg_file.open() as f:

        skiprows = 0
        log_format = 'qttasks'
        names = ['time', 'thumb', 'index', 'middle', 'ring', 'little']

        for i, l in enumerate(f):

            possible_hand['right'] += l.lower().count('right')
            possible_hand['left'] += l.lower().count('left')

            if 'event' in l:
                skiprows = i
                log_format = 'neurobs'  # log from presentation
                names = None

            if 'Onset:' in l:
                skiprows = i
                log_format = 'finger_mapping'  # log from finger mapping c-code
                names = None

    df = read_csv(dg_file, skiprows=skiprows, delimiter=r'\s+', names=names)

    """convert the log file into df with columns:
    time, left thumb, left index, ..., right thumb, ..., right little

    with 'time' im ms
    """
    if log_format == 'neurobs':
        df, hdr['StartTime'] = _fix_neurobs_log(df)
        df['time'] = df['time'].apply(lambda x: x / 1000)
    elif log_format == 'finger_mapping':
        df = _fix_fingermapping(df)
        df['time'] = df['time'].apply(lambda x: x / 1000)
    elif log_format == 'qttasks':
        df, hdr['StartTime'] = _fix_qttask(df)
        possible_hand['right'] = 1  # assume it's right-hand TODO: how to estimate which hand

    if len(df.columns) < 10:
        df = _select_from_one_hand(df, possible_hand)
        if df is None:
            lg.warning(f'Unknown hand side for {dg_file}')

    else:
        df = _select_from_two_hands(df)

    t = df['time'].values
    fs = 1 / ((t[-1] - t[0]) / t.shape[0])
    hdr['SamplingFrequency'] = float('%.3f' % (fs))

    hdr['Columns'] = list(df.columns)

    return df, hdr