Ejemplo n.º 1
0
def decayfit(t, y, p=(0.05, 0.9), prepend_zero=False, rse=False, lm=False):
    """
    Fit exponential decay, y(t) = w exp(-t/tau), to latter part of trajectory.
    
    :param t: time
    :param y: variable, e.g. an ion current
    :param p: proportion of return to initial value, 
        as for action potential duration
    :param bool prepend_zero: add a 0 at the start of y (hack for use with 
        ion currents)
    :param bool rse: return relative standard error of slope (not of *tau*!).
    :param bool lm: Return R object for fitted linear model.
    :return tau: -1/slope for estimated slope of log(y) vs t
    
    tau has dimension 'time' and is analogous to half-life: '1/e'-life = 0.37-life.
    
    For use with results from :meth:`Clampable.vecvclamp`, see :func:`decayfits`.
    
    Trivial example.
    
    >>> t = np.arange(10)
    >>> y = np.exp(-t)
    >>> y[0] = 0
    >>> decayfit(t, y)
    1.0
    
    Relative standard error when adding noise.
    
    >>> np.random.seed(0)
    >>> noisy = y + 0.05 * np.random.random(size=y.shape)
    >>> decayfit(t, noisy, rse=True, p=[0.5, 0.99])
    (1.292..., 0.045...)
    """
    assert len(p) == 2
    if prepend_zero:
        t = np.r_[0, t]
        y = np.r_[0, y]
    stats = apd(t, y, p)
    _ip, i0, i1 = stats["i"]
    # Avoid "Warning message: In is.na(rows) : 
    #        is.na() applied to non-(list or vector) of type 'NULL'"
    if i1 <= i0:
        tau = rse_slope = np.nan
        rlm = None
    else:
        with roptions(show_error_messages=False, deparse_max_lines=0):
            try:
                rlm = r.lm("log(y)~t", data=dict(t=t[i0:i1], 
                                                 y=y[i0:i1].squeeze()))
                coef = r2rec(r.as_data_frame(r.coef(r.summary(rlm))))
                _intercept, slope = coef.Estimate
                _rse_intercept, rse_slope = (coef["Std. Error"] / 
                                             abs(coef.Estimate))
                tau = - 1.0 / slope
            except RRuntimeError:
                tau = rse_slope = np.nan
                rlm = None
    result = (tau,)
    if rse:
        result += (rse_slope,)
    if lm:
        result += (rlm,)
    return result if len(result) > 1 else result[0]
Ejemplo n.º 2
0
    >>> mmfit(x, -y)
    (nan, nan)
    """
    with roptions(show_error_messages=False, deparse_max_lines=0):
        kwargs = dict(formula="y~ymax*x/(x+xhalf)", data=dict(x=x, y=y), 
            start=dict(ymax=max(y), xhalf=np.mean(x)))
        try:
            fit = r.nls(**kwargs)
        except RRuntimeError, exc:
            s = str(exc.exc).split("\n")[1].strip()
            errmsg = "Michaelis-Menten fit failed with message '%s'. " % s
            errmsg += "Arguments to r.nls() were: %s"
            logger.debug(errmsg, kwargs)
            ymax = xhalf = rse_ymax = rse_xhalf = np.nan
        else:
            coef = r2rec(r.as_data_frame(r.coef(r.summary(fit))))
            ymax, xhalf = coef.Estimate
            rse_ymax, rse_xhalf = coef["Std. Error"] / coef.Estimate
            if (ymax < 0) or (xhalf < 0):
                errmsg = ("Michalis-Menten fit gave negative estimate(s): "
                    "ymax=%s, xhalf=%s. Arguments to r.nls() were: %s")
                logger.debug(errmsg, ymax, xhalf, kwargs)
                ymax = xhalf = rse_ymax = rse_xhalf = np.nan
        return (ymax, xhalf, rse_ymax, rse_xhalf) if rse else (ymax, xhalf)

def decayfits(L, i, k, abs_=True):
    """
    Convenience wrapper for applying decayfit() to list returned by vecvclamp().
    
    :param L: list of (proto, traj), where *proto* is a list of 
        (duration, voltage) for each pulse, and *traj* is a list of