Ejemplo n.º 1
0
def gat_to_single_pred(gat, y, cv, estimator, diagonal_only=False):
    """Use MVPA to combine all gat.y_pred_ into single estimate per trial"""
    from nose.tools import assert_true
    from jr.gat import get_diagonal_ypred
    if diagonal_only:
        # check that diagonal is identifyiable
        assert_true(len(gat.y_pred_) == gat.y_pred_.shape[1])
        y_pred = np.array(get_diagonal_ypred(gat))
        assert_true(len(gat.y_pred_) == len(y_pred))
        # re-insert testing time dimension
        y_pred = np.transpose(y_pred[..., None], [0, 3, 1, 2])
    else:
        y_pred = gat.y_pred_

    # Combine diagonal prediction into single pred
    n_train, n_test, n_trial, n_pred = y_pred.shape

    # flatten gat
    X = np.reshape(y_pred.transpose([2, 0, 1, 3]), [n_trial, -1])

    # keep cross-validation
    single_y_pred = np.empty(n_trial)
    for train, test in cv:
        estimator.fit(X[train], y[train])
        estimator.predict(X[test])
        single_y_pred[test] = estimator.predict(X[test])
    return single_y_pred
def get_predict(gat, sel=None, toi=None, mean=True, typ='diagonal'):
    """Retrieve decoding prediction from a GeneralizationAcrossTime object"""
    from jr.gat import get_diagonal_ypred
    from jr.utils import align_on_diag
    # select data in the gat matrix
    if typ == 'diagonal':
        y_pred = np.transpose(get_diagonal_ypred(gat), [1, 0, 2])
    elif typ == 'align_on_diag':
        y_pred = np.squeeze(align_on_diag(gat.y_pred_)).transpose([2, 0, 1, 3])
    elif typ == 'gat':
        y_pred = np.squeeze(gat.y_pred_).transpose([2, 0, 1, 3])
    elif typ == 'slice':
        raise NotImplementedError('slice')
    y_pred = y_pred % (2 * np.pi)  # make sure data is in on circle
    # Select trials
    sel = range(len(y_pred)) if sel is None else sel
    y_pred = y_pred[sel, ...]
    # select TOI
    times = np.array(gat.train_times_['times'])
    toi = times[[0, -1]] if toi is None else toi
    toi_ = np.where((times >= toi[0]) & (times <= toi[1]))[0]
    y_pred = y_pred[:, toi_, ...]
    # mean across time point
    if mean:
        # weighted circular mean (dim = angle * radius)
        cos = np.mean(np.cos(y_pred[..., 0]) * y_pred[..., 1], axis=1)
        sin = np.mean(np.sin(y_pred[..., 0]) * y_pred[..., 1], axis=1)
        radius = np.median(y_pred[..., 1], axis=1)
        angle = np.arctan2(sin, cos)
        y_pred = lstack(angle, radius)
    return y_pred[:, None] if y_pred.ndim == 1 else y_pred
Ejemplo n.º 3
0
def gat_to_single_pred(gat, y, cv, estimator, diagonal_only=False):
    """Use MVPA to combine all gat.y_pred_ into single estimate per trial"""
    from nose.tools import assert_true
    from jr.gat import get_diagonal_ypred
    if diagonal_only:
        # check that diagonal is identifyiable
        assert_true(len(gat.y_pred_) == gat.y_pred_.shape[1])
        y_pred = np.array(get_diagonal_ypred(gat))
        assert_true(len(gat.y_pred_) == len(y_pred))
        # re-insert testing time dimension
        y_pred = np.transpose(y_pred[..., None], [0, 3, 1, 2])
    else:
        y_pred = gat.y_pred_

    # Combine diagonal prediction into single pred
    n_train, n_test, n_trial, n_pred = y_pred.shape

    # flatten gat
    X = np.reshape(y_pred.transpose([2, 0, 1, 3]), [n_trial, -1])

    # keep cross-validation
    single_y_pred = np.empty(n_trial)
    for train, test in cv:
        estimator.fit(X[train], y[train])
        estimator.predict(X[test])
        single_y_pred[test] = estimator.predict(X[test])
    return single_y_pred
def get_predict(gat, sel=None, toi=None, mean=True, typ='diagonal'):
    """Retrieve decoding prediction from a GeneralizationAcrossTime object"""
    from jr.gat import get_diagonal_ypred
    from jr.utils import align_on_diag
    # select data in the gat matrix
    if typ == 'diagonal':
        y_pred = np.transpose(get_diagonal_ypred(gat), [1, 0, 2])
    elif typ == 'align_on_diag':
        y_pred = np.squeeze(align_on_diag(gat.y_pred_)).transpose([2, 0, 1, 3])
    elif typ == 'gat':
        y_pred = np.squeeze(gat.y_pred_).transpose([2, 0, 1, 3])
    elif typ == 'slice':
        raise NotImplementedError('slice')
    y_pred = y_pred % (2 * np.pi)  # make sure data is in on circle
    # Select trials
    sel = range(len(y_pred)) if sel is None else sel
    y_pred = y_pred[sel, ...]
    # select TOI
    times = np.array(gat.train_times_['times'])
    toi = times[[0, -1]] if toi is None else toi
    toi_ = np.where((times >= toi[0]) & (times <= toi[1]))[0]
    y_pred = y_pred[:, toi_, ...]
    # mean across time point
    if mean:
        # weighted circular mean (dim = angle * radius)
        cos = np.mean(np.cos(y_pred[..., 0]) * y_pred[..., 1], axis=1)
        sin = np.mean(np.sin(y_pred[..., 0]) * y_pred[..., 1], axis=1)
        radius = np.median(y_pred[..., 1], axis=1)
        angle = np.arctan2(sin, cos)
        y_pred = lstack(angle, radius)
    return y_pred[:, None] if y_pred.ndim == 1 else y_pred
def _analyze_continuous(analysis):
    """Regress prediction error as a function of visibility and contrast for
    each time point"""
    ana_name = analysis['name'] + '-continuous'

    # don't recompute if not necessary
    fname = paths('score', analysis=ana_name)
    if os.path.exists(fname):
        return load('score', analysis=ana_name)

    # gather data
    n_subject = 20
    n_time = 151
    scores = dict(visibility=np.zeros((n_subject, n_time, 4)),
                  contrast=np.zeros((n_subject, n_time, 3)))
    R = dict(visibility=np.zeros((n_subject, n_time)),
             contrast=np.zeros((n_subject, n_time)),)
    for s, subject in enumerate(subjects):
        gat, _, events_sel, events = load('decod', subject=subject,
                                          analysis=analysis['name'])
        events = events.iloc[events_sel].reset_index()
        y_pred = np.transpose(get_diagonal_ypred(gat), [1, 0, 2])[..., 0]
        for factor in ['visibility', 'contrast']:
            # subscore per condition (e.g. each visibility rating)
            scores[factor][s, :, :] = _subscore(y_pred, events,
                                                analysis, factor)
            # correlate residuals with factor
            R[factor][s, :] = _subregress(y_pred, events,
                                          analysis, factor, True)

    times = gat.train_times_['times']
    save([scores, R, times], 'score', analysis=ana_name,
         overwrite=True, upload=True)
    return [scores, R, times]
def _average_ypred_toi(gat, toi, analysis):
    """Average single trial predictions of each time point in a given TOI"""
    y_pred = np.transpose(get_diagonal_ypred(gat), [1, 0, 2])
    times = gat.train_times_['times']
    # select time sample
    toi = np.where((times >= toi[0]) & (times <= toi[1]))[0]
    if 'circAngle' in analysis['name']:
        # weight average by regressor radius
        cos = np.cos(y_pred[:, toi, 0])
        sin = np.sin(y_pred[:, toi, 0])
        radius = y_pred[:, toi, 1]
        y_pred = np.angle(np.median((cos + 1j * sin) * radius, axis=1))
    else:
        y_pred = np.median(y_pred[:, toi], axis=1)
    return np.squeeze(y_pred)
def _average_ypred_toi(gat, toi, analysis):
    """Average single trial predictions of each time point in a given TOI"""
    y_pred = np.transpose(get_diagonal_ypred(gat), [1, 0, 2])
    times = gat.train_times_['times']
    # select time sample
    toi = np.where((times >= toi[0]) & (times <= toi[1]))[0]
    if 'circAngle' in analysis['name']:
        # weight average by regressor radius
        cos = np.cos(y_pred[:, toi, 0])
        sin = np.sin(y_pred[:, toi, 0])
        radius = y_pred[:, toi, 1]
        y_pred = np.angle(np.median((cos + 1j * sin) * radius, axis=1))
    else:
        y_pred = np.median(y_pred[:, toi], axis=1)
    return np.squeeze(y_pred)
def _analyze_continuous(analysis):
    """Regress prediction error as a function of visibility and contrast for
    each time point"""
    ana_name = analysis['name'] + '-continuous'

    # don't recompute if not necessary
    fname = paths('score', analysis=ana_name)
    if os.path.exists(fname):
        return load('score', analysis=ana_name)

    # gather data
    n_subject = 20
    n_time = 151
    scores = dict(visibility=np.zeros((n_subject, n_time, 4)),
                  contrast=np.zeros((n_subject, n_time, 3)))
    R = dict(
        visibility=np.zeros((n_subject, n_time)),
        contrast=np.zeros((n_subject, n_time)),
    )
    for s, subject in enumerate(subjects):
        gat, _, events_sel, events = load('decod',
                                          subject=subject,
                                          analysis=analysis['name'])
        events = events.iloc[events_sel].reset_index()
        y_pred = np.transpose(get_diagonal_ypred(gat), [1, 0, 2])[..., 0]
        for factor in ['visibility', 'contrast']:
            # subscore per condition (e.g. each visibility rating)
            scores[factor][s, :, :] = _subscore(y_pred, events, analysis,
                                                factor)
            # correlate residuals with factor
            R[factor][s, :] = _subregress(y_pred, events, analysis, factor,
                                          True)

    times = gat.train_times_['times']
    save([scores, R, times],
         'score',
         analysis=ana_name,
         overwrite=True,
         upload=True)
    return [scores, R, times]