def _stats(analysis):
    """2nd order stats across subjects"""

    # if already computed lets just load it
    ana_name = 'stats_' + analysis['name'] + '_vhp'
    if op.exists(paths('score', analysis=ana_name)):
        return load('score', analysis=ana_name)

    # gather scores across subjects
    scores = list()
    for subject in range(1, 21):
        kwargs = dict(subject=subject, analysis=analysis['name'] + '_vhp')
        fname = paths('score', **kwargs)
        if op.exists(fname):
            score, times = load(**kwargs)
        else:
            score, times = _decod(subject, analysis)
        scores.append(score)
    scores = np.array(scores)

    # compute stats across subjects
    p_values = stats(scores - analysis['chance'])
    diag_offdiag = scores - np.tile([np.diag(sc) for sc in scores],
                                    [len(times), 1, 1]).transpose(1, 0, 2)
    p_values_off = stats(diag_offdiag)

    # Save stats results
    out = dict(scores=scores, p_values=p_values, p_values_off=p_values_off,
               times=times, analysis=analysis)
    save(out, 'score',  analysis=ana_name)
    return out
def _stats(analysis):
    """2nd order stats across subjects"""

    # if already computed lets just load it
    ana_name = 'stats_' + analysis['name'] + '_vhp'
    if op.exists(paths('score', analysis=ana_name)):
        return load('score', analysis=ana_name)

    # gather scores across subjects
    scores = list()
    for subject in range(1, 21):
        kwargs = dict(subject=subject, analysis=analysis['name'] + '_vhp')
        fname = paths('score', **kwargs)
        if op.exists(fname):
            score, times = load(**kwargs)
        else:
            score, times = _decod(subject, analysis)
        scores.append(score)
    scores = np.array(scores)

    # compute stats across subjects
    p_values = stats(scores - analysis['chance'])
    diag_offdiag = scores - np.tile([np.diag(sc) for sc in scores],
                                    [len(times), 1, 1]).transpose(1, 0, 2)
    p_values_off = stats(diag_offdiag)

    # Save stats results
    out = dict(scores=scores,
               p_values=p_values,
               p_values_off=p_values_off,
               times=times,
               analysis=analysis)
    save(out, 'score', analysis=ana_name)
    return out
def _subscore_pipeline(analysis):  # FIXME merge with subscore
    """Subscore each analysis as a function of the reported visibility"""
    ana_name = analysis['name'] + '-vis'

    # 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
    all_scores = list()
    for subject in subjects:
        gat, _, events_sel, events = load('decod',
                                          subject=subject,
                                          analysis=analysis['name'])
        times = gat.train_times_['times']
        # remove irrelevant trials
        events = events.iloc[events_sel].reset_index()
        scores = list()
        gat.score_mode = 'mean-sample-wise'
        for vis in range(4):
            sel = np.where(events['detect_button'] == vis)[0]
            # If target present, we use the AUC against all absent trials
            if len(sel) < 5:
                scores.append(np.nan * np.empty(gat.y_pred_.shape[:2]))
                continue
            if analysis['name'] == 'target_present':
                sel = np.r_[sel,
                            np.where(
                                events['target_present'] == False)[0]]  # noqa
            score = subscore(gat, sel)
            scores.append(score)
        all_scores.append(scores)
    all_scores = np.array(all_scores)

    # stats
    pval = list()
    for vis in range(4):
        pval.append(stats(all_scores[:, vis, :, :] - analysis['chance']))

    save([all_scores, pval, times],
         'score',
         analysis=ana_name,
         overwrite=True,
         upload=True)
    return all_scores, pval, times
def _correlate(analysis):
    """Correlate estimator prediction with a visibility reports"""
    ana_name = analysis['name'] + '-Rvis'

    # 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
    all_R = list()
    for subject in subjects:
        gat, _, events_sel, events = load('decod',
                                          subject=subject,
                                          analysis=analysis['name'])
        times = gat.train_times_['times']
        # remove irrelevant trials
        events = events.iloc[events_sel].reset_index()
        y_vis = np.array(events['detect_button'])

        # only analyse present trials
        sel = np.where(events['target_present'])[0]
        y_vis = y_vis[sel]
        gat.y_pred_ = gat.y_pred_[:, :, sel, :]

        # make 2D y_pred
        y_pred = gat.y_pred_.transpose(2, 0, 1, 3)[..., 0]
        y_pred = y_pred.reshape(len(y_pred), -1)
        # regress
        R = repeated_spearman(y_pred, y_vis)
        # reshape and store
        R = R.reshape(*gat.y_pred_.shape[:2])
        all_R.append(R)
    all_R = np.array(all_R)

    # stats
    pval = stats(all_R)

    save([all_R, pval, times],
         'score',
         analysis=ana_name,
         overwrite=True,
         upload=True)
    return all_R, pval, times
def _subscore_pipeline(analysis):  # FIXME merge with subscore
    """Subscore each analysis as a function of the reported visibility"""
    ana_name = analysis['name'] + '-vis'

    # 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
    all_scores = list()
    for subject in subjects:
        gat, _, events_sel, events = load('decod', subject=subject,
                                          analysis=analysis['name'])
        times = gat.train_times_['times']
        # remove irrelevant trials
        events = events.iloc[events_sel].reset_index()
        scores = list()
        gat.score_mode = 'mean-sample-wise'
        for vis in range(4):
            sel = np.where(events['detect_button'] == vis)[0]
            # If target present, we use the AUC against all absent trials
            if len(sel) < 5:
                scores.append(np.nan * np.empty(gat.y_pred_.shape[:2]))
                continue
            if analysis['name'] == 'target_present':
                sel = np.r_[sel,
                            np.where(events['target_present'] == False)[0]]  # noqa
            score = subscore(gat, sel)
            scores.append(score)
        all_scores.append(scores)
    all_scores = np.array(all_scores)

    # stats
    pval = list()
    for vis in range(4):
        pval.append(stats(all_scores[:, vis, :, :] - analysis['chance']))

    save([all_scores, pval, times],
         'score', analysis=ana_name, overwrite=True, upload=True)
    return all_scores, pval, times
def _correlate(analysis):
    """Correlate estimator prediction with a visibility reports"""
    ana_name = analysis['name'] + '-Rvis'

    # 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
    all_R = list()
    for subject in subjects:
        gat, _, events_sel, events = load('decod', subject=subject,
                                          analysis=analysis['name'])
        times = gat.train_times_['times']
        # remove irrelevant trials
        events = events.iloc[events_sel].reset_index()
        y_vis = np.array(events['detect_button'])

        # only analyse present trials
        sel = np.where(events['target_present'])[0]
        y_vis = y_vis[sel]
        gat.y_pred_ = gat.y_pred_[:, :, sel, :]

        # make 2D y_pred
        y_pred = gat.y_pred_.transpose(2, 0, 1, 3)[..., 0]
        y_pred = y_pred.reshape(len(y_pred), -1)
        # regress
        R = repeated_spearman(y_pred, y_vis)
        # reshape and store
        R = R.reshape(*gat.y_pred_.shape[:2])
        all_R.append(R)
    all_R = np.array(all_R)

    # stats
    pval = stats(all_R)

    save([all_R, pval, times], 'score', analysis=ana_name,
         overwrite=True, upload=True)
    return all_R, pval, times
def _duration_toi(analysis):
    """Estimate temporal generalization
    Re-align on diagonal, average per toi and compute stats."""
    ana_name = analysis['name'] + '-duration-toi'
    if os.path.exists(paths('score', analysis=ana_name)):
        return load('score', analysis=ana_name)
    all_scores, _, times = load('score', analysis=analysis['name'] + '-vis')
    # Add average duration
    n_subject = len(all_scores)
    all_score_tois = np.zeros((n_subject, 4, len(tois), len(times)))
    all_pval_tois = np.zeros((4, len(tois), len(times)))
    for vis in range(4):
        scores = all_scores[:, vis, ...]
        # align score on training time
        scores = [align_on_diag(score) for score in scores]
        # center effect
        scores = np.roll(scores, len(times) // 2, axis=2)
        for t, toi in enumerate(tois):
            toi = np.where((times >= toi[0]) & (times <= toi[1]))[0]
            score_toi = np.mean(scores[:, toi, :], axis=1)
            all_score_tois[:, vis, t, :] = score_toi
            all_pval_tois[vis, t, :] = stats(score_toi - analysis['chance'])
    save([all_score_tois, all_pval_tois, times], 'score', analysis=ana_name)
    return [all_score_tois, all_pval_tois, times]
def _duration_toi(analysis):
    """Estimate temporal generalization
    Re-align on diagonal, average per toi and compute stats."""
    ana_name = analysis['name'] + '-duration-toi'
    if os.path.exists(paths('score', analysis=ana_name)):
        return load('score', analysis=ana_name)
    all_scores, _, times = load('score', analysis=analysis['name'] + '-vis')
    # Add average duration
    n_subject = len(all_scores)
    all_score_tois = np.zeros((n_subject, 4, len(tois), len(times)))
    all_pval_tois = np.zeros((4, len(tois), len(times)))
    for vis in range(4):
        scores = all_scores[:, vis, ...]
        # align score on training time
        scores = [align_on_diag(score) for score in scores]
        # center effect
        scores = np.roll(scores, len(times) // 2, axis=2)
        for t, toi in enumerate(tois):
            toi = np.where((times >= toi[0]) & (times <= toi[1]))[0]
            score_toi = np.mean(scores[:, toi, :], axis=1)
            all_score_tois[:, vis, t, :] = score_toi
            all_pval_tois[vis, t, :] = stats(score_toi - analysis['chance'])
    save([all_score_tois, all_pval_tois, times], 'score', analysis=ana_name)
    return [all_score_tois, all_pval_tois, times]
    scores = np.array([np.diag(subject) for subject in scores])
    if analysis['name'] in relevant:
        score_relevant.append(scores)
    elif analysis['name'] in irrelevant:
        score_irrelevant.append(scores)

fig, ax = plt.subplots(1, figsize=[6, 2])
# non parametric necessitate to take the mean of the sign of the effects
# because each decoding score uses different metrics
scores_interaction = np.mean(np.sign(score_relevant) -
                             np.sign(score_irrelevant),
                             axis=0)
scores_relevant = np.mean(np.sign(score_relevant), axis=0)
scores_irrelevant = np.mean(np.sign(score_irrelevant), axis=0)

sig = stats(scores_interaction) < alpha
pretty_decod(scores_relevant,
             times=times,
             ax=ax,
             color='y',
             sig=sig,
             fill=True,
             width=0.)
sig = stats(scores_relevant) < alpha
pretty_decod(scores_relevant, times=times, ax=ax, color='r', sig=sig)
sig = stats(scores_irrelevant) < alpha
pretty_decod(scores_irrelevant,
             times=times,
             ax=ax,
             color='w',
             sig=np.ones_like(times),
    save(out, 'score', analysis=ana_name)
    return out


# only recompute on the relevant analyses
analyses = [
    ana for ana in analyses
    if ana['name'] in ['target_present', 'target_circAngle']
]
for analysis in analyses:
    out = _stats(analysis)
    scores = out['scores']
    if 'circAngle' in analysis['name']:
        scores /= 2.
    times = out['times']
    alpha = .05
    chance = analysis['chance']
    p_values = stats(scores - chance)
    clim = np.percentile(np.diag(np.mean(scores, axis=0)), 97)
    clim = [chance - (clim - chance), clim]
    fig, ax_gat = plt.subplots(1, figsize=[7, 5.5])
    pretty_gat(np.mean(scores, axis=0),
               times=times,
               sig=p_values < alpha,
               chance=chance,
               ax=ax_gat,
               clim=clim)
    report.add_figs_to_section([fig], [analysis['name']], analysis['name'])

report.save()
    # not 154 time points
    scores = np.array([np.diag(subject) for subject in scores])
    if analysis['name'] in relevant:
        score_relevant.append(scores)
    elif analysis['name'] in irrelevant:
        score_irrelevant.append(scores)

fig, ax = plt.subplots(1, figsize=[6, 2])
# non parametric necessitate to take the mean of the sign of the effects
# because each decoding score uses different metrics
scores_interaction = np.mean(np.sign(score_relevant) -
                             np.sign(score_irrelevant), axis=0)
scores_relevant = np.mean(np.sign(score_relevant), axis=0)
scores_irrelevant = np.mean(np.sign(score_irrelevant), axis=0)

sig = stats(scores_interaction) < alpha
pretty_decod(scores_relevant, times=times, ax=ax, color='y', sig=sig,
             fill=True, width=0.)
sig = stats(scores_relevant) < alpha
pretty_decod(scores_relevant, times=times, ax=ax, color='r', sig=sig)
sig = stats(scores_irrelevant) < alpha
pretty_decod(scores_irrelevant, times=times, ax=ax, color='w',
             sig=np.ones_like(times), fill=True, width=0.)
pretty_decod(scores_irrelevant, times=times, ax=ax, color='k', sig=sig)
ax.set_ylim(-1., 1.)
ax.set_yticks([-1., 1])
ax.set_yticklabels([-1, 1])
xticks = np.arange(-.100, 1.101, .100)
ax.set_xticks(xticks)
ax.set_xticklabels([int(1e3*ii) if ii in np.linspace(-0.1, 1., 12.)
                    else '' for ii in xticks])
Beispiel #12
0
        score, times = load('score',
                            subject=subject,
                            analysis=analysis['name'])
        scores.append(score)

    scores = [sc for sc in scores if not np.isnan(sc[0][0])]
    if len(scores) < 7:
        print('%s: not enough subjects' % analysis['name'])
        continue
    chance = analysis['chance']
    alpha = 0.05

    # Compute stats: is decoding different from theoretical chance level (using
    # permutations across subjects)
    print('stats', analysis['name'])
    p_values = stats(np.array(scores) - chance)
    diag_offdiag = scores - np.tile([np.diag(sc) for sc in scores],
                                    [len(times), 1, 1]).transpose(1, 0, 2)
    p_values_off = stats(diag_offdiag)

    scores_diag = [np.diag(sc) for sc in scores]
    p_values_diag = stats(np.array(scores_diag)[:, :, None] - chance)

    # Save stats results
    print('save', analysis['name'])
    out = dict(scores=scores,
               p_values=p_values,
               p_values_off=p_values_off,
               times=times,
               analysis=analysis,
               p_values_diag=p_values_diag)
            # Init
            if label.name not in evokeds.keys():
                evokeds[label.name] = list()
            evoked = np.squeeze(stc.extract_label_time_course(
                label, inv['src'], mode='mean', verbose=False))
            evokeds[label.name].append(evoked)
    labels = np.array(evokeds.keys())
    data = np.transpose([evokeds.values()], [0, 2, 1, 3])[0]
    times = stc.times

    # Stats on region of interest across subjects
    scores = list()
    for roi in rois:
        idx = np.where([roi in this_roi for this_roi in labels])[0]
        scores.append(np.mean(data[:, idx, :], axis=1))
    p_values = stats(np.transpose(scores, [1, 2, 0]) - chance, n_jobs=-1)

    fig, axes = plt.subplots(len(rois), 1, sharex=True, sharey=True,
                             figsize=[10, 40])
    cmap = plt.get_cmap('rainbow')
    colors = cmap(np.linspace(0., 1., len(rois)))
    ylim = [2, -2]

    # Plot
    details_toi, details_roi = list(), list()
    for ii, (score, p_val, ax, color, roi) in enumerate(zip(
            scores, p_values.T, axes, colors, rois)):
        pretty_decod(score, sig=p_val < .05, times=times-np.min(times),
                     color=color, ax=ax, fill=True, chance=chance)

        xlim = ax.get_xlim()
                y_error = get_predict_error(gat,
                                            toi=toi_probe,
                                            sel=sel,
                                            mean=True,
                                            y_true=y_true[sel])
                probas, bins = circ_tuning(y_error, n=n_bins)
                tuning.append(probas)
            results['tuning'][s, ii, jj, :, :] = np.transpose(tuning)

# test significance of target versus probe train test
# for biases (signed values)
results['bias_pval'] = np.zeros_like((results['bias'][0]))
for ii in range(2):
    for jj in range(2):
        scores = results['bias'][:, ii, jj, :, :]
        results['bias_pval'][ii, jj, :, :] = stats(scores)

# for accuracy (absolute values)
results['target_probe_pval'] = np.zeros((n_time, n_time, 2, 2))
for ii in range(2):
    for jj in range(2):
        results['target_probe_pval'][:, :, ii,
                                     jj] = stats(results['accuracy'][:, ii,
                                                                     jj, :, :])

# load absent target prediction to perform the control analysis of virtual
# biases
results['target_absent'] = np.zeros((20, n_time, 181))
results['target_absent_bias_toi'] = np.zeros((20, len(tois)))
for s, subject in enumerate(subjects):  # Loop across each subject
    print(subject)
                if len(sel) == 0 or np.isnan(y_true[sel]).any():
                    tuning.append(np.nan * np.zeros(n_bins))
                    continue
                y_error = get_predict_error(gat, toi=toi_probe, sel=sel,
                                            mean=True, y_true=y_true[sel])
                probas, bins = circ_tuning(y_error, n=n_bins)
                tuning.append(probas)
            results['tuning'][s, ii, jj, :, :] = np.transpose(tuning)

# test significance of target versus probe train test
# for biases (signed values)
results['bias_pval'] = np.zeros_like((results['bias'][0]))
for ii in range(2):
    for jj in range(2):
        scores = results['bias'][:, ii, jj, :, :]
        results['bias_pval'][ii, jj, :, :] = stats(scores)

# for accuracy (absolute values)
results['target_probe_pval'] = np.zeros((n_time, n_time, 2, 2))
for ii in range(2):
    for jj in range(2):
        results['target_probe_pval'][:, :, ii, jj] = stats(
            results['accuracy'][:, ii, jj, :, :])

# load absent target prediction to perform the control analysis of virtual
# biases
results['target_absent'] = np.zeros((20, n_time, 181))
results['target_absent_bias_toi'] = np.zeros((20, len(tois)))
for s, subject in enumerate(subjects):  # Loop across each subject
    print(subject)
    gat, analysis, events_sel, events = load(
Beispiel #16
0
             overwrite=True,
             upload=True)
    return stcs, connectivity


connectivity = spatial_tris_connectivity(grade_to_tris(5))
for analysis in analyses:
    print(analysis)
    # don't compute if already on S3
    try:
        load('score_pval', subject='fsaverage', analysis=analysis['name'])
        continue
    except Exception:
        pass

    # Retrieve data
    chance = analysis['chance']
    stcs, connectivity = _append_data(analysis)

    # Source Stats
    X = stcs - chance
    p_val = stats(X.transpose(0, 2, 1), connectivity=connectivity, n_jobs=1)

    # Save and upload
    save(p_val,
         'score_pval',
         subject='fsaverage',
         analysis=analysis['name'],
         overwrite=True,
         upload=False)
                                    [len(times), 1, 1]).transpose(1, 0, 2)
    p_values_off = stats(diag_offdiag)

    # Save stats results
    out = dict(scores=scores, p_values=p_values, p_values_off=p_values_off,
               times=times, analysis=analysis)
    save(out, 'score',  analysis=ana_name)
    return out


# only recompute on the relevant analyses
analyses = [ana for ana in analyses if ana['name'] in
            ['target_present', 'target_circAngle']]
for analysis in analyses:
    out = _stats(analysis)
    scores = out['scores']
    if 'circAngle' in analysis['name']:
        scores /= 2.
    times = out['times']
    alpha = .05
    chance = analysis['chance']
    p_values = stats(scores - chance)
    clim = np.percentile(np.diag(np.mean(scores, axis=0)), 97)
    clim = [chance-(clim-chance), clim]
    fig, ax_gat = plt.subplots(1, figsize=[7, 5.5])
    pretty_gat(np.mean(scores, axis=0), times=times, sig=p_values < alpha,
               chance=chance, ax=ax_gat, clim=clim)
    report.add_figs_to_section([fig], [analysis['name']], analysis['name'])

report.save()
    gat.estimators_ = [gat.estimators_[t] for t in toi_]
    gat.train_times_['times'] = [gat.train_times_['times'][t] for t in toi_]
    gat.train_times_['slices'] = [gat.train_times_['slices'][t] for t in toi_]
    # predict all trials, including absent to keep cv scheme
    gat.predict(epochs[sel_gat])

    # subscore on present only
    gat.scores_ = subscore(gat, sel, y[sel])
    scores.append(gat.scores_)

    # Save classifier results
    save([gat, analysis, sel_gat, events],
         'decod',
         subject=subject,
         analysis=analysis['name'] + '_probe_to_target')

times = epochs.times[:-5]
score_diag = np.array([np.diag(np.array(score)[4:, :]) for score in scores])
p_val = stats(score_diag)
pretty_decod(score_diag,
             times=times,
             sig=p_val < .05,
             color=analysis['color'],
             fill=True)
# toi_ = np.where((times >= toi[0]) & (times < toi[1]))[0]
toi_ = np.where(p_val < .05)[0]
score = np.mean(score_diag[:, toi_], axis=1)
print(np.mean(score, axis=0),
      np.std(score, axis=0) / np.sqrt(len(score_diag)), np.min(p_val[toi_]),
      times[toi_])
            all_score_tois[:, vis, t, :] = score_toi
            all_pval_tois[vis, t, :] = stats(score_toi - analysis['chance'])
    save([all_score_tois, all_pval_tois, times], 'score', analysis=ana_name)
    return [all_score_tois, all_pval_tois, times]


# Main plotting
colors = dict(visibility=plt.get_cmap('bwr')(np.linspace(0, 1, 4.)),
              contrast=plt.get_cmap('hot_r')([.5, .75, 1.]))

# Loop across visibility and orientation analyses
for analysis in analyses:
    # Plot correlation of decoding score with visibility and contrast
    scores, R, times = _analyze_continuous(analysis)
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=[20, 10])
    sig = stats(R['visibility']) < .05
    pretty_decod(-R['visibility'], times=times, sig=sig, ax=ax1,
                 color='purple', fill=True)
    sig = stats(R['contrast']) < .05
    pretty_decod(-R['contrast'], times=times, sig=sig, ax=ax2,
                 color='orange', fill=True)
    report.add_figs_to_section([fig], ['continuous regress'], analysis['name'])

    # Plot decoding score for each visibility level
    all_scores, score_pvals, times = _subscore_pipeline(analysis)
    if 'circAngle' in analysis['name']:
        all_scores /= 2.  # from circle to half circle
    figs, axes = list(), list()
    for vis in range(4):
        fig, ax = plt.subplots(1, figsize=[14, 11])
        scores = all_scores[:, vis, ...]
    gat, _, sel_gat, _ = load('decod', subject=subject, analysis='probe_phase')
    # only keep estimators after probe onset
    times = gat.train_times_['times']
    toi_ = np.where((times >= (.800 + toi[0])) & (times < (.800 + toi[1])))[0]
    gat.estimators_ = [gat.estimators_[t] for t in toi_]
    gat.train_times_['times'] = [gat.train_times_['times'][t] for t in toi_]
    gat.train_times_['slices'] = [gat.train_times_['slices'][t] for t in toi_]
    # predict all trials, including absent to keep cv scheme
    gat.predict(epochs[sel_gat])

    # subscore on present only
    gat.scores_ = subscore(gat, sel, y[sel])
    scores.append(gat.scores_)

    # Save classifier results
    save([gat, analysis, sel_gat, events], 'decod', subject=subject,
         analysis=analysis['name'] + '_probe_to_target')

times = epochs.times[:-5]
score_diag = np.array([np.diag(np.array(score)[4:, :]) for score in scores])
p_val = stats(score_diag)
pretty_decod(score_diag, times=times, sig=p_val < .05, color=analysis['color'],
             fill=True)
# toi_ = np.where((times >= toi[0]) & (times < toi[1]))[0]
toi_ = np.where(p_val < .05)[0]
score = np.mean(score_diag[:, toi_], axis=1)
print(np.mean(score, axis=0),
      np.std(score, axis=0) / np.sqrt(len(score_diag)),
      np.min(p_val[toi_]),
      times[toi_])
    scores = list()
    for subject in subjects:
        # define path to file to be loaded
        score, times = load('score', subject=subject,
                            analysis=analysis['name'])
        scores.append(score)

    scores = [sc for sc in scores if not np.isnan(sc[0][0])]
    if len(scores) < 7:
        print('%s: not enough subjects' % analysis['name'])
        continue
    chance = analysis['chance']
    alpha = 0.05

    # Compute stats: is decoding different from theoretical chance level (using
    # permutations across subjects)
    print('stats', analysis['name'])
    p_values = stats(np.array(scores) - chance)
    diag_offdiag = scores - np.tile([np.diag(sc) for sc in scores],
                                    [len(times), 1, 1]).transpose(1, 0, 2)
    p_values_off = stats(diag_offdiag)

    scores_diag = [np.diag(sc) for sc in scores]
    p_values_diag = stats(np.array(scores_diag)[:, :, None] - chance)

    # Save stats results
    print('save', analysis['name'])
    out = dict(scores=scores, p_values=p_values, p_values_off=p_values_off,
               times=times, analysis=analysis, p_values_diag=p_values_diag)
    save(out, 'score',  analysis=('stats_' + analysis['name']), overwrite=True)
            # apply morph
            stc_morph = morph_data_precomputed(subject, 'fsaverage', stc,
                                               vertices_to, morph)
            stcs.append(stc_morph.data)
        stcs = np.array(stcs)
        save([stcs, connectivity], 'score_source', subject='fsaverage',
             analysis=analysis['name'], overwrite=True, upload=True)
    return stcs, connectivity

connectivity = spatial_tris_connectivity(grade_to_tris(5))
for analysis in analyses:
    print(analysis)
    # don't compute if already on S3
    try:
        load('score_pval', subject='fsaverage', analysis=analysis['name'])
        continue
    except Exception:
        pass

    # Retrieve data
    chance = analysis['chance']
    stcs, connectivity = _append_data(analysis)

    # Source Stats
    X = stcs - chance
    p_val = stats(X.transpose(0, 2, 1), connectivity=connectivity, n_jobs=1)

    # Save and upload
    save(p_val, 'score_pval', subject='fsaverage',
         analysis=analysis['name'], overwrite=True, upload=False)
from config import load, subjects, report

fig = plt.figure(figsize=[18, 5])
axes = gridspec.GridSpec(2, 5, left=0.05, right=.95, hspace=0.35, wspace=.25)
for ii, (analysis, ax) in enumerate(zip(analyses, axes)):
    ax = fig.add_subplot(ax)
    scores = list()
    for subject in subjects:
        score, times, freqs = load('score_tfr', subject=subject,
                                   analysis=analysis['name'])
        scores.append(score)
    scores = np.array(scores)
    if 'circAngle' in analysis['name']:
        scores /= 2
    # compute stats
    p_val = stats(scores - analysis['chance'])
    sig = p_val < .05

    # plot effect size
    scores = np.mean(scores, axis=0)
    im = ax.matshow(scores, aspect='auto', origin='lower',
                    extent=[times[0], times[-1], 0, len(freqs)],
                    vmin=analysis['chance'], vmax=np.max(scores),
                    cmap=analysis['cmap'])

    # plot stats
    xx, yy = np.meshgrid(times, range(len(freqs)), copy=False, indexing='xy')
    ax.contour(xx, yy, sig, colors='black', levels=[0],
               linestyles='dotted')

    # pretty plot
            all_score_tois[:, vis, t, :] = score_toi
            all_pval_tois[vis, t, :] = stats(score_toi - analysis['chance'])
    save([all_score_tois, all_pval_tois, times], 'score', analysis=ana_name)
    return [all_score_tois, all_pval_tois, times]


# Main plotting
colors = dict(visibility=plt.get_cmap('bwr')(np.linspace(0, 1, 4.)),
              contrast=plt.get_cmap('hot_r')([.5, .75, 1.]))

# Loop across visibility and orientation analyses
for analysis in analyses:
    # Plot correlation of decoding score with visibility and contrast
    scores, R, times = _analyze_continuous(analysis)
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=[20, 10])
    sig = stats(R['visibility']) < .05
    pretty_decod(-R['visibility'],
                 times=times,
                 sig=sig,
                 ax=ax1,
                 color='purple',
                 fill=True)
    sig = stats(R['contrast']) < .05
    pretty_decod(-R['contrast'],
                 times=times,
                 sig=sig,
                 ax=ax2,
                 color='orange',
                 fill=True)
    report.add_figs_to_section([fig], ['continuous regress'], analysis['name'])