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 _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]