Esempio n. 1
0
def sure_stimulus_duration(trialsfile, plot, saved=None, **kwargs):
    if saved is not None:
        psure_by_duration_by_coh = saved
    else:
        trials, A, R, M, perf = utils.load(trialsfile)

        # Sort
        trials_by_cond = {}
        for n, trial in enumerate(trials):
            if not trial['wager']:
                continue

            cond = trial['coh']
            if perf.choices[n] is not None:
                trials_by_cond.setdefault(cond, {'durations': [], 'sures': []})

                duration = np.ptp(trial['durations']['stimulus'])
                trials_by_cond[cond]['durations'].append(duration)
                trials_by_cond[cond]['sures'].append(perf.choices[n] == 'S')

        # Number of bins
        nbins = kwargs.get('nbins', 10)

        # Average
        psure_by_duration_by_coh = {}
        for coh, v in trials_by_cond.items():
            (xbins, ybins, xedges,
             binsizes) = datatools.partition(v['durations'], v['sures'], nbins=nbins)
            duration = [np.mean(xbin) for xbin in xbins]
            psure = [utils.divide(np.sum(ybin > 0), len(ybin)) for ybin in ybins]
            psure_by_duration_by_coh[coh] = (duration, psure)

    #=====================================================================================
    # Plot
    #=====================================================================================

    lineprop = {'lw':  kwargs.get('lw', 1)}
    dataprop = {'ms':  kwargs.get('ms', 7),
                'mew': kwargs.get('mew', 0)}
    colors = kwargs.get('colors', kiani2009_colors)

    cohs = sorted(psure_by_duration_by_coh)
    for coh in cohs:
        duration, psure = psure_by_duration_by_coh[coh]

        plot.plot(duration, psure, color=colors[coh], label='{}\%'.format(coh), **lineprop)
        plot.plot(duration, psure, 'o', mfc=colors[coh], **dataprop)

    plot.xlim(100, 800)
    plot.ylim(0, 1)

    #=====================================================================================

    return psure_by_duration_by_coh
Esempio n. 2
0
def sure_stimulus_duration(trialsfile, plot, saved=None, **kwargs):
    if saved is not None:
        psure_by_duration_by_coh = saved
    else:
        trials, A, R, M, perf = utils.load(trialsfile)

        # Sort
        trials_by_cond = {}
        for n, trial in enumerate(trials):
            if not trial['wager']:
                continue

            cond = trial['coh']
            if perf.choices[n] is not None:
                trials_by_cond.setdefault(cond, {'durations': [], 'sures': []})

                duration = np.ptp(trial['durations']['stimulus'])
                trials_by_cond[cond]['durations'].append(duration)
                trials_by_cond[cond]['sures'].append(perf.choices[n] == 'S')

        # Number of bins
        nbins = kwargs.get('nbins', 10)

        # Average
        psure_by_duration_by_coh = {}
        for coh, v in trials_by_cond.items():
            (xbins, ybins, xedges,
             binsizes) = datatools.partition(v['durations'], v['sures'], nbins=nbins)
            duration = [np.mean(xbin) for xbin in xbins]
            psure = [utils.divide(np.sum(ybin > 0), len(ybin)) for ybin in ybins]
            psure_by_duration_by_coh[coh] = (duration, psure)

    #=====================================================================================
    # Plot
    #=====================================================================================

    lineprop = {'lw':  kwargs.get('lw', 1)}
    dataprop = {'ms':  kwargs.get('ms', 7),
                'mew': kwargs.get('mew', 0)}
    colors = kwargs.get('colors', kiani2009_colors)

    cohs = sorted(psure_by_duration_by_coh)
    for coh in cohs:
        duration, psure = psure_by_duration_by_coh[coh]

        plot.plot(duration, psure, color=colors[coh], label='{}\%'.format(coh), **lineprop)
        plot.plot(duration, psure, 'o', mfc=colors[coh], **dataprop)

    plot.xlim(100, 800)
    plot.ylim(0, 1)

    #=====================================================================================

    return psure_by_duration_by_coh
Esempio n. 3
0
def choice_pattern(trialsfile, offers, plot, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    B_by_offer = {}
    n_nondecision = 0
    for n, trial in enumerate(trials):
        if perf.choices[n] is None:
            n_nondecision += 1
            continue

        juice_L, juice_R = trial['juice']
        offer = trial['offer']

        if perf.choices[n] == 'B':
            B = 1
        elif perf.choices[n] == 'A':
            B = 0
        else:
            raise ValueError("invalid choice")

        B_by_offer.setdefault(offer, []).append(B)
    print("Non-decision trials: {}/{}".format(n_nondecision, len(trials)))

    pB_by_offer = {}
    for offer in B_by_offer:
        Bs = B_by_offer[offer]
        pB_by_offer[offer] = utils.divide(sum(Bs), len(Bs))
        #print(offer, pB_by_offer[offer])

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    if plot is None:
        return

    ms = kwargs.get('ms', 7)
    rotation = kwargs.get('rotation', 60)

    for i, offer in enumerate(offers):
        plot.plot(i, 100 * pB_by_offer[offer], 'o', color='k', ms=ms)

    plot.xticks(range(len(offers)))
    plot.xticklabels(['{}B:{}A'.format(*offer) for offer in offers],
                     rotation=rotation)

    plot.xlim(0, len(offers) - 1)
    plot.ylim(0, 100)
Esempio n. 4
0
def performance(trialsfile, plot, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    correct_by_cond = {}
    for n, trial in enumerate(trials):
        if not perf.decisions[n]:
            continue

        gt_lt = trial['gt_lt']
        fpair = trial['fpair']
        if gt_lt == '>':
            f1, f2 = fpair
        else:
            f2, f1 = fpair
        cond = (f1, f2)

        correct_by_cond.setdefault(cond, []).append(perf.corrects[n])

    pcorrect_by_cond = {}
    for c in correct_by_cond:
        corrects = correct_by_cond[c]
        pcorrect_by_cond[c] = utils.divide(sum(corrects), len(corrects))

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    plot.equal()

    lw = kwargs.get('lw', 1)
    fontsize = kwargs.get('fontsize', 10)
    _min, _max = kwargs.get('lims', (10 - 4, 34 + 4))
    r = kwargs.get('r', 1.5)

    for (f1, f2), pcorrect in pcorrect_by_cond.items():
        plot.circle((f1, f2), r, ec='none', fc=smap.to_rgba(f1))
        plot.text(f1,
                  f2,
                  '{}'.format(int(100 * pcorrect)),
                  color='w',
                  fontsize=fontsize,
                  ha='center',
                  va='center')

    plot.xlim(_min, _max)
    plot.ylim(_min, _max)
    plot.plot([_min, _max], [_min, _max], color='k', lw=lw)
Esempio n. 5
0
def choice_pattern(trialsfile, offers, plot, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    B_by_offer    = {}
    n_nondecision = 0
    for n, trial in enumerate(trials):
        if perf.choices[n] is None:
            n_nondecision += 1
            continue

        juice_L, juice_R = trial['juice']
        offer = trial['offer']

        if perf.choices[n] == 'B':
            B = 1
        elif perf.choices[n] == 'A':
            B = 0
        else:
            raise ValueError("invalid choice")

        B_by_offer.setdefault(offer, []).append(B)
    print("Non-decision trials: {}/{}".format(n_nondecision, len(trials)))

    pB_by_offer = {}
    for offer in B_by_offer:
        Bs = B_by_offer[offer]
        pB_by_offer[offer] = utils.divide(sum(Bs), len(Bs))
        #print(offer, pB_by_offer[offer])

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    if plot is None:
        return

    ms       = kwargs.get('ms', 7)
    rotation = kwargs.get('rotation', 60)

    for i, offer in enumerate(offers):
        plot.plot(i, 100*pB_by_offer[offer], 'o', color='k', ms=ms)

    plot.xticks(range(len(offers)))
    plot.xticklabels(['{}B:{}A'.format(*offer) for offer in offers], rotation=rotation)

    plot.xlim(0, len(offers)-1)
    plot.ylim(0, 100)
Esempio n. 6
0
def correct_stimulus_duration(trialsfile, plot, saved=None, **kwargs):
    if saved is not None:
        pcorrect_by_duration_by_coh, pcorrect_by_duration_by_coh_wager = saved
    else:
        trials, A, R, M, perf = utils.load(trialsfile)

        # Sort
        trials_by_cond       = {}
        trials_by_cond_wager = {}
        for n, trial in enumerate(trials):
            coh = trial['coh']
            if coh == 0 or perf.choices[n] not in ['L', 'R']:
                continue

            cond     = coh
            duration = np.ptp(trial['durations']['stimulus'])
            if trial['wager']:
                trials_by_cond_wager.setdefault(cond, {'durations': [], 'corrects': []})
                trials_by_cond_wager[cond]['durations'].append(duration)
                trials_by_cond_wager[cond]['corrects'].append(perf.corrects[n])
            else:
                trials_by_cond.setdefault(cond, {'durations': [], 'corrects': []})
                trials_by_cond[cond]['durations'].append(duration)
                trials_by_cond[cond]['corrects'].append(perf.corrects[n])

        # Number of bins
        nbins = kwargs.get('nbins', 10)

        # Average no-wager trials
        pcorrect_by_duration_by_coh = {}
        for coh, v in trials_by_cond.items():
            (xbins, ybins, xedges,
             binsizes) = datatools.partition(v['durations'], v['corrects'], nbins=nbins)
            duration = [np.mean(xbin) for xbin in xbins]
            pcorrect = [utils.divide(np.sum(ybin > 0), len(ybin)) for ybin in ybins]
            pcorrect_by_duration_by_coh[coh] = (duration, pcorrect)

        # Average wager trials
        pcorrect_by_duration_by_coh_wager = {}
        for coh, v in trials_by_cond_wager.items():
            (xbins, ybins, xedges,
             binsizes) = datatools.partition(v['durations'], v['corrects'], nbins=nbins)
            duration = [np.mean(xbin) for xbin in xbins]
            pcorrect = [utils.divide(np.sum(ybin > 0), len(ybin)) for ybin in ybins]
            pcorrect_by_duration_by_coh_wager[coh] = (duration, pcorrect)

    #=====================================================================================
    # Plot
    #=====================================================================================

    lineprop = {'ls':     '--',
                'lw':     kwargs.get('lw', 1),
                'dashes': kwargs.get('dashes', [9, 4])}
    dataprop = {'mew': kwargs.get('mew', 1)}
    dataprop['ms'] = kwargs.get('ms', 6) + dataprop['mew']/2

    lineprop_wager = {'lw':  kwargs.get('lw', 1)}
    dataprop_wager = {'ms':  kwargs.get('ms', 7),
                      'mew': kwargs.get('mew', 0)}

    colors = kwargs.get('colors', kiani2009_colors)

    # No-wager trials
    cohs = sorted(pcorrect_by_duration_by_coh)
    for coh in cohs:
        duration, pcorrect = pcorrect_by_duration_by_coh[coh]

        plot.plot(duration, pcorrect, color=colors[coh], zorder=10, **lineprop)
        plot.plot(duration, pcorrect, 'o', mfc='w', mec=colors[coh],
                  zorder=10, **dataprop)

    # Wager trials
    cohs = sorted(pcorrect_by_duration_by_coh_wager)
    for coh in cohs:
        duration, pcorrect = pcorrect_by_duration_by_coh_wager[coh]

        plot.plot(duration, pcorrect, color=colors[coh], zorder=5, **lineprop_wager)
        plot.plot(duration, pcorrect, 'o', mfc=colors[coh], mec=colors[coh],
                  zorder=5, **dataprop_wager)

    plot.xlim(100, 800)
    plot.ylim(0.5, 1)

    #=====================================================================================

    return pcorrect_by_duration_by_coh, pcorrect_by_duration_by_coh_wager
Esempio n. 7
0
def psychometric(trialsfile, plot, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    decision_by_freq = {}
    high_by_freq = {}
    for n, trial in enumerate(trials):
        mod = trial['mod']
        freq = trial['freq']
        decision_by_freq.setdefault(mod, {})
        high_by_freq.setdefault(mod, {})
        decision_by_freq[mod].setdefault(freq, [])
        high_by_freq[mod].setdefault(freq, [])
        if perf.decisions[n]:
            decision_by_freq[mod][freq].append(True)

            if perf.choices[n] == 'H':
                high = 1
            else:
                high = 0

            high_by_freq[mod][freq].append(high)
        else:
            decision_by_freq[mod][freq].append(False)

    freqs = {}
    p_decision = {}
    p_high = {}
    for mod in decision_by_freq:
        freqs[mod] = np.sort(high_by_freq[mod].keys())
        p_decision[mod] = np.zeros(len(freqs[mod]))
        p_high[mod] = np.zeros(len(freqs[mod]))
        for i, freq in enumerate(freqs[mod]):
            p_decision[mod][i] = sum(decision_by_freq[mod][freq]) / len(
                decision_by_freq[mod][freq])
            p_high[mod][i] = utils.divide(sum(high_by_freq[mod][freq]),
                                          len(high_by_freq[mod][freq]))

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    lw = kwargs.get('lw', 1.5)
    ms = kwargs.get('ms', 6)

    all_x = []
    all_y = []
    sigmas = {}
    for mod in ['v', 'a', 'va']:
        if mod == 'v':
            label = 'Visual'
        elif mod == 'a':
            label = 'Auditory'
        elif mod == 'va':
            label = 'Multisensory'
        else:
            raise ValueError

        x = freqs[mod]
        y = p_high[mod]

        # Fit psychometric curve
        props = dict(lw=lw, color=colors[mod], label=label)
        try:
            popt, func = fittools.fit_psychometric(x, y)
            sigmas[mod] = popt['sigma']

            fit_x = np.linspace(min(x), max(x), 201)
            fit_y = func(fit_x, **popt)
            plot.plot(fit_x, 100 * fit_y, **props)
        except RuntimeError:
            print("Unable to fit, drawing a line through the points.")
            plot.plot(x, 100 * y, **props)
        plot.plot(x, 100 * y, 'o', ms=ms, mew=0, mfc=props['color'])
        all_x.append(x)

    # Is it optimal?
    print("")
    print("  Optimality test")
    print("  ---------------")
    print("")
    for mod in ['v', 'a', 'va']:
        print("  sigma_{:<2} = {:.6f}".format(mod, sigmas[mod]))
    print("  1/sigma_v**2 + 1/sigma_a**2 = {:.6f}".format(1 / sigmas['v']**2 +
                                                          1 / sigmas['a']**2))
    print("  1/sigma_va**2               = {:.6f}".format(1 / sigmas['va']**2))

    plot.xlim(np.min(all_x), np.max(all_x))
    plot.ylim(0, 100)
    plot.yticks([0, 50, 100])

    plot.xlabel('Frequency (events/sec)')
    plot.ylabel('Percent high')

    return [sigmas[k] for k in ['v', 'a', 'va']]
Esempio n. 8
0
def correct_stimulus_duration(trialsfile, plot, saved=None, **kwargs):
    if saved is not None:
        pcorrect_by_duration_by_coh, pcorrect_by_duration_by_coh_wager = saved
    else:
        trials, A, R, M, perf = utils.load(trialsfile)

        # Sort
        trials_by_cond       = {}
        trials_by_cond_wager = {}
        for n, trial in enumerate(trials):
            coh = trial['coh']
            if coh == 0 or perf.choices[n] not in ['L', 'R']:
                continue

            cond     = coh
            duration = np.ptp(trial['durations']['stimulus'])
            if trial['wager']:
                trials_by_cond_wager.setdefault(cond, {'durations': [], 'corrects': []})
                trials_by_cond_wager[cond]['durations'].append(duration)
                trials_by_cond_wager[cond]['corrects'].append(perf.corrects[n])
            else:
                trials_by_cond.setdefault(cond, {'durations': [], 'corrects': []})
                trials_by_cond[cond]['durations'].append(duration)
                trials_by_cond[cond]['corrects'].append(perf.corrects[n])

        # Number of bins
        nbins = kwargs.get('nbins', 10)

        # Average no-wager trials
        pcorrect_by_duration_by_coh = {}
        for coh, v in trials_by_cond.items():
            (xbins, ybins, xedges,
             binsizes) = datatools.partition(v['durations'], v['corrects'], nbins=nbins)
            duration = [np.mean(xbin) for xbin in xbins]
            pcorrect = [utils.divide(np.sum(ybin > 0), len(ybin)) for ybin in ybins]
            pcorrect_by_duration_by_coh[coh] = (duration, pcorrect)

        # Average wager trials
        pcorrect_by_duration_by_coh_wager = {}
        for coh, v in trials_by_cond_wager.items():
            (xbins, ybins, xedges,
             binsizes) = datatools.partition(v['durations'], v['corrects'], nbins=nbins)
            duration = [np.mean(xbin) for xbin in xbins]
            pcorrect = [utils.divide(np.sum(ybin > 0), len(ybin)) for ybin in ybins]
            pcorrect_by_duration_by_coh_wager[coh] = (duration, pcorrect)

    #=====================================================================================
    # Plot
    #=====================================================================================

    lineprop = {'ls':     '--',
                'lw':     kwargs.get('lw', 1),
                'dashes': kwargs.get('dashes', [9, 4])}
    dataprop = {'mew': kwargs.get('mew', 1)}
    dataprop['ms'] = kwargs.get('ms', 6) + dataprop['mew']/2

    lineprop_wager = {'lw':  kwargs.get('lw', 1)}
    dataprop_wager = {'ms':  kwargs.get('ms', 7),
                      'mew': kwargs.get('mew', 0)}

    colors = kwargs.get('colors', kiani2009_colors)

    # No-wager trials
    cohs = sorted(pcorrect_by_duration_by_coh)
    for coh in cohs:
        duration, pcorrect = pcorrect_by_duration_by_coh[coh]

        plot.plot(duration, pcorrect, color=colors[coh], zorder=10, **lineprop)
        plot.plot(duration, pcorrect, 'o', mfc='w', mec=colors[coh],
                  zorder=10, **dataprop)

    # Wager trials
    cohs = sorted(pcorrect_by_duration_by_coh_wager)
    for coh in cohs:
        duration, pcorrect = pcorrect_by_duration_by_coh_wager[coh]

        plot.plot(duration, pcorrect, color=colors[coh], zorder=5, **lineprop_wager)
        plot.plot(duration, pcorrect, 'o', mfc=colors[coh], mec=colors[coh],
                  zorder=5, **dataprop_wager)

    plot.xlim(100, 800)
    plot.ylim(0.5, 1)

    #=====================================================================================

    return pcorrect_by_duration_by_coh, pcorrect_by_duration_by_coh_wager
Esempio n. 9
0
def indifference_point(trialsfile, offers, plot=None, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    B_by_offer = {}
    n_nondecision = 0
    for n, trial in enumerate(trials):
        if perf.choices[n] is None:
            n_nondecision += 1
            continue

        juice_L, juice_R = trial['juice']
        offer = trial['offer']

        if perf.choices[n] == 'B':
            B = 1
        elif perf.choices[n] == 'A':
            B = 0
        else:
            raise ValueError("invalid choice")

        B_by_offer.setdefault(offer, []).append(B)
    print("Non-decision trials: {}/{}".format(n_nondecision, len(trials)))

    pB_by_offer = {}
    for offer in B_by_offer:
        Bs = B_by_offer[offer]
        pB_by_offer[offer] = utils.divide(sum(Bs), len(Bs))
        #print(offer, pB_by_offer[offer])

    X = []
    Y = []
    for i, offer in enumerate(offers):
        B, A = offer
        X.append((B - A) / (B + A))
        Y.append(pB_by_offer[offer])
    X = np.asarray(X)
    Y = np.asarray(Y)

    idx = np.argsort(X)
    X = X[idx]
    Y = Y[idx]

    #-------------------------------------------------------------------------------------
    # Fit
    #-------------------------------------------------------------------------------------

    try:
        popt, func = fittools.fit_psychometric(X, Y)

        mu = popt['mu']
        idpt = (1 + mu) / (1 - mu)
        print("Indifference point = {}".format(idpt))

        fit_x = np.linspace(min(X), max(X), 201)
        fit_y = func(fit_x, **popt)
        fit = fit_x, fit_y
    except RuntimeError:
        print("Unable to fit, drawing a line through the points.")
        mu = None
        idpt = None
        fit = X, Y

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    if plot is None:
        return idpt

    lw = kwargs.get('lw', 1.5)
    ms = kwargs.get('ms', 7)
    rotation = kwargs.get('rotation', 60)

    plot.plot(fit_x, 100 * fit_y, '-', color='k', lw=lw)
    plot.plot(X, 100 * Y, 'o', color='k', ms=ms)

    plot.hline(50, color='0.5', zorder=2)
    if mu is not None:
        plot.text_upper_left('1A = {:.1f}B'.format(idpt), fontsize=10)
        plot.vline(mu, color='0.5', zorder=2)

    #plot.xticks(range(len(offers)))
    #plot.xticklabels(['{}B:{}A'.format(*offer) for offer in offers], rotation=rotation)

    #plot.xlim(0, len(offers)-1)
    plot.ylim(0, 100)

    return idpt
Esempio n. 10
0
    #-------------------------------------------------------------------------------------
    # Reward
    #-------------------------------------------------------------------------------------

    plot = fig['reward']

    ntrials = []
    rewards = []
    pcorrects = []
    for record in training_history:
        ntrials.append(record['n_trials'])
        rewards.append(record['mean_reward'])

        perf = record['perf']
        pcorrects.append(utils.divide(perf.n_correct, perf.n_decision))
    ntrials = np.asarray(ntrials) / T
    rewards = np.asarray(rewards)
    pcorrects = np.asarray(pcorrects)

    print(rewards)
    w1 = list(np.where(rewards == -1)[0])
    w2 = list(np.where(rewards > 0)[0])
    try:
        w1.append(w2[0])
    except IndexError:
        pass

    dashes = [5, 3]

    #plot.plot(ntrials[w1], rewards[w1], '--', color=color, lw=lw, dashes=dashes)
Esempio n. 11
0
    #-------------------------------------------------------------------------------------
    # Reward
    #-------------------------------------------------------------------------------------

    plot = fig['reward']

    ntrials   = []
    rewards   = []
    pcorrects = []
    for record in training_history:
        ntrials.append(record['n_trials'])
        rewards.append(record['mean_reward'])

        perf = record['perf']
        pcorrects.append(utils.divide(perf.n_correct, perf.n_decision))
    ntrials   = np.asarray(ntrials)/T
    rewards   = np.asarray(rewards)
    pcorrects = np.asarray(pcorrects)

    print(rewards)
    w1 = list(np.where(rewards == -1)[0])
    w2 = list(np.where(rewards > 0)[0])
    try:
        w1.append(w2[0])
    except IndexError:
        pass

    dashes = [5, 3]

    #plot.plot(ntrials[w1], rewards[w1], '--', color=color, lw=lw, dashes=dashes)
Esempio n. 12
0
def indifference_point(trialsfile, offers, plot=None, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    B_by_offer    = {}
    n_nondecision = 0
    for n, trial in enumerate(trials):
        if perf.choices[n] is None:
            n_nondecision += 1
            continue

        juice_L, juice_R = trial['juice']
        offer = trial['offer']

        if perf.choices[n] == 'B':
            B = 1
        elif perf.choices[n] == 'A':
            B = 0
        else:
            raise ValueError("invalid choice")

        B_by_offer.setdefault(offer, []).append(B)
    print("Non-decision trials: {}/{}".format(n_nondecision, len(trials)))

    pB_by_offer = {}
    for offer in B_by_offer:
        Bs = B_by_offer[offer]
        pB_by_offer[offer] = utils.divide(sum(Bs), len(Bs))
        #print(offer, pB_by_offer[offer])

    X = []
    Y = []
    for i, offer in enumerate(offers):
        B, A = offer
        X.append((B - A)/(B + A))
        Y.append(pB_by_offer[offer])
    X = np.asarray(X)
    Y = np.asarray(Y)

    idx = np.argsort(X)
    X   = X[idx]
    Y   = Y[idx]

    #-------------------------------------------------------------------------------------
    # Fit
    #-------------------------------------------------------------------------------------

    try:
        popt, func = fittools.fit_psychometric(X, Y)

        mu   = popt['mu']
        idpt = (1+mu)/(1-mu)
        print("Indifference point = {}".format(idpt))

        fit_x = np.linspace(min(X), max(X), 201)
        fit_y = func(fit_x, **popt)
        fit   = fit_x, fit_y
    except RuntimeError:
        print("Unable to fit, drawing a line through the points.")
        mu   = None
        idpt = None
        fit  = X, Y

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    if plot is None:
        return idpt

    lw       = kwargs.get('lw', 1.5)
    ms       = kwargs.get('ms', 7)
    rotation = kwargs.get('rotation', 60)

    plot.plot(fit_x, 100*fit_y, '-', color='k', lw=lw)
    plot.plot(X, 100*Y, 'o', color='k', ms=ms)

    plot.hline(50, color='0.5', zorder=2)
    if mu is not None:
        plot.text_upper_left('1A = {:.1f}B'.format(idpt), fontsize=10)
        plot.vline(mu, color='0.5', zorder=2)

    #plot.xticks(range(len(offers)))
    #plot.xticklabels(['{}B:{}A'.format(*offer) for offer in offers], rotation=rotation)

    #plot.xlim(0, len(offers)-1)
    plot.ylim(0, 100)

    return idpt
Esempio n. 13
0
def psychometric(trialsfile, plot, **kwargs):
    # Load trials
    trials, A, R, M, perf = utils.load(trialsfile)

    decision_by_freq = {}
    high_by_freq     = {}
    for n, trial in enumerate(trials):
        mod  = trial['mod']
        freq = trial['freq']
        decision_by_freq.setdefault(mod, {})
        high_by_freq.setdefault(mod, {})
        decision_by_freq[mod].setdefault(freq, [])
        high_by_freq[mod].setdefault(freq, [])
        if perf.decisions[n]:
            decision_by_freq[mod][freq].append(True)

            if perf.choices[n] == 'H':
                high = 1
            else:
                high = 0

            high_by_freq[mod][freq].append(high)
        else:
            decision_by_freq[mod][freq].append(False)

    freqs      = {}
    p_decision = {}
    p_high     = {}
    for mod in decision_by_freq:
        freqs[mod]      = np.sort(high_by_freq[mod].keys())
        p_decision[mod] = np.zeros(len(freqs[mod]))
        p_high[mod]     = np.zeros(len(freqs[mod]))
        for i, freq in enumerate(freqs[mod]):
            p_decision[mod][i] = sum(decision_by_freq[mod][freq])/len(decision_by_freq[mod][freq])
            p_high[mod][i]     = utils.divide(sum(high_by_freq[mod][freq]), len(high_by_freq[mod][freq]))

    #-------------------------------------------------------------------------------------
    # Plot
    #-------------------------------------------------------------------------------------

    lw = kwargs.get('lw', 1.5)
    ms = kwargs.get('ms', 6)

    all_x  = []
    all_y  = []
    sigmas = {}
    for mod in ['v', 'a', 'va']:
        if mod == 'v':
            label = 'Visual'
        elif mod == 'a':
            label = 'Auditory'
        elif mod == 'va':
            label = 'Multisensory'
        else:
            raise ValueError

        x = freqs[mod]
        y = p_high[mod]

        # Fit psychometric curve
        props = dict(lw=lw, color=colors[mod], label=label)
        try:
            popt, func = fittools.fit_psychometric(x, y)
            sigmas[mod] = popt['sigma']

            fit_x = np.linspace(min(x), max(x), 201)
            fit_y = func(fit_x, **popt)
            plot.plot(fit_x, 100*fit_y, **props)
        except RuntimeError:
            print("Unable to fit, drawing a line through the points.")
            plot.plot(x, 100*y, **props)
        plot.plot(x, 100*y, 'o', ms=ms, mew=0, mfc=props['color'])
        all_x.append(x)

    # Is it optimal?
    print("")
    print("  Optimality test")
    print("  ---------------")
    print("")
    for mod in ['v', 'a', 'va']:
        print("  sigma_{:<2} = {:.6f}".format(mod, sigmas[mod]))
    print("  1/sigma_v**2 + 1/sigma_a**2 = {:.6f}"
          .format(1/sigmas['v']**2 + 1/sigmas['a']**2))
    print("  1/sigma_va**2               = {:.6f}".format(1/sigmas['va']**2))

    plot.xlim(np.min(all_x), np.max(all_x))
    plot.ylim(0, 100)
    plot.yticks([0, 50, 100])

    plot.xlabel('Frequency (events/sec)')
    plot.ylabel('Percent high')

    return [sigmas[k] for k in ['v', 'a', 'va']]