Ejemplo n.º 1
0
fig.text(.05, .47, r"logistic", rotation=90, **fontspecs)
fig.text(.1, .47, r"$f(x)=\frac{1}{1+\exp(-x)}$", rotation=90, **fontspecs)
fig.text(.05, .2, r"exponential", rotation=90, **fontspecs)
fig.text(.1, .2, r"$f(x)=1-\exp(-x)$", rotation=90, **fontspecs)

fig.text(.6, .95, r"ab", **fontspecs)
fig.text(.6, .9, r"$g(x,a,b)=\frac{x-a}{b}$", **fontspecs)
fig.text(.85, .95, r"poly", **fontspecs)
fig.text(.85, .9, r"$g(x,a,b)=(\frac{x}{a})^b$", **fontspecs)

axes_ab = [ax_ab, ax_logist, ax_logistab, ax_lgumbel, ax_gumbelab]
axes_wei = [ax_weibull, ax_logistweib, ax_gumbelweib]

abcore = sft.abCore()
weicore = sft.polyCore(sft.PsiData([1, 2, 3], [2, 2, 2], [2, 2, 2], 2))
logistic = sft.PsiLogistic()
gumbel = sft.PsiExponential()

x = p.mgrid[-7:7:1000j]

ax_logist.plot(x, [logistic.f(xx) for xx in x], color="k")
ax_lgumbel.plot(x, [gumbel.f(xx) for xx in x], color="k")

prm = [(1, 2, .02), (2, 2, .02), (1, 1, .02), (2, 1, .02)]
col = ['b', 'r', 'g', 'c']

for pr, c in zip(prm, col):
    dab = [abcore.g(xx, pr) for xx in x]
    ax_ab.plot(x, dab, color=c)
    ax_logistab.plot(x, [logistic.f(dd) for dd in dab], color=c)
Ejemplo n.º 2
0
def diagnostics(data,
                params,
                nafc=2,
                sigmoid='logistic',
                core='ab',
                cuts=None,
                gammaislambda=False):
    """ Some diagnostic statistics for a psychometric function fit.

    This function is a bit messy since it has three functions depending on the
    type of the `data` argument.

    Parameters
    ----------

    data : variable
        real data : A list of lists or an array of data.
            The first column should be stimulus intensity, the second column should
            be number of correct responses (in 2AFC) or number of yes- responses (in
            Yes/No), the third column should be number of trials. See also: the examples
            section below.
        intensities : sequence of floats
            The x-values of the psychometric function, then we obtain only the
            predicted values.
        no data : empty sequence
            In this case we evaluate the psychometric function at the cuts. All
            other return values are then irrelevant.

    params : sequence of len nparams
        parameter vector at which the diagnostic information should be evaluated

    nafc : int
        Number of responses alternatives for nAFC tasks. If nafc==1 a Yes/No task is
        assumed.

    sigmoid : string
        Name of the sigmoid to be fitted. Valid sigmoids include:
                logistic
                gauss
                gumbel_l
                gumbel_r
        See `swignifit.utility.available_sigmoids()` for all available sigmoids.

    core : string
        \"core\"-type of the psychometric function. Valid choices include:
                ab       (x-a)/b
                mw%g     midpoint and width
                linear   a+bx
                log      a+b log(x)
        See `swignifit.utility.available_cores()` for all available sigmoids.

    cuts : sequence of floats
        Cuts at which thresholds should be determined.  That is if cuts =
        (.25,.5,.75), thresholds (F^{-1} ( 0.25 ), F^{-1} ( 0.5 ), F^{-1} ( 0.75
        )) are returned.  Here F^{-1} denotes the inverse of the function
        specified by sigmoid. If cuts==None, this is modified to cuts=[0.5].

    Output
    ------

    (predicted, deviance_residuals, deviance, thres, Rpd, Rkd)

    predicted : numpy array of length nblocks
        predicted values associated with the respective stimulus intensities

    deviance_residuals : numpy array of length nblocks
        deviance residuals of the data

    deviance float
        deviance of the data

    thres : numpy array length ncuts
        the model prediction at the cuts

    Rpd : float
        correlation between predicted performance and deviance residuals

    Rkd : float
        correlation between block index and deviance residuals

    Example
    -------
    >>> x = [float(2*k) for k in xrange(6)]
    >>> k = [34,32,40,48,50,48]
    >>> n = [50]*6
    >>> d = [[xx,kk,nn] for xx,kk,nn in zip(x,k,n)]
    >>> prm = [2.75, 1.45, 0.015]
    >>> pred,di,D,thres,slope,Rpd,Rkd = diagnostics(d,prm)
    >>> D
    8.0748485860836254
    >>> di[0]
    1.6893279652591433
    >>> Rpd
    -0.19344675783032755

    """

    # here we need to hack stuff, since data can be either 'real' data, or just
    # a list of intensities, or just an empty sequence

    # in order to remain compatible with psipy we must check for an empty
    # sequence here, and return a specially crafted return value in that case.
    # sorry..
    # TODO after removal of psipy we can probably change this.
    if op.isSequenceType(data) and len(data) == 0:
        pmf, nparams = sfu.make_pmf(sfr.PsiData([0], [0], [0], 1),
                                    nafc,
                                    sigmoid,
                                    core,
                                    None,
                                    gammaislambda=gammaislambda)
        thres = np.array(
            [pmf.getThres(params, cut) for cut in sfu.get_cuts(cuts)])
        slope = np.array([pmf.getSlope(params, th) for th in thres])
        return np.array([]), np.array([]), 0.0, thres, np.nan, np.nan

    shape = np.shape(np.array(data))
    intensities_only = False
    if len(shape) == 1:
        # just intensities, make a dataset with k and n all zero
        k = n = [0] * shape[0]
        data = [[xx, kk, nn] for xx, kk, nn in zip(data, k, n)]
        intensities_only = True
    else:
        # data is 'real', just do nothing
        pass

    dataset, pmf, nparams = sfu.make_dataset_and_pmf(
        data, nafc, sigmoid, core, None, gammaislambda=gammaislambda)
    cuts = sfu.get_cuts(cuts)
    params = sfu.get_params(params, nparams)
    predicted = np.array([
        pmf.evaluate(intensity, params)
        for intensity in dataset.getIntensities()
    ])

    if intensities_only:
        return predicted
    else:
        deviance_residuals = pmf.getDevianceResiduals(params, dataset)
        deviance = pmf.deviance(params, dataset)
        thres = np.array([pmf.getThres(params, cut) for cut in cuts])
        slope = np.array([pmf.getSlope(params, th) for th in thres])
        rpd = pmf.getRpd(deviance_residuals, params, dataset)
        rkd = pmf.getRkd(deviance_residuals, dataset)
        return predicted, deviance_residuals, deviance, thres, slope, rpd, rkd
Ejemplo n.º 3
0
 def generate_test_dataset():
     x = sfr.vector_double([0.,2.,4.,6., 8., 10.])
     k = sfr.vector_int([24, 32, 40,48, 50,48])
     n = sfr.vector_int(6*[50])
     return sfr.PsiData(x, n, k, 2)