import numpy as np
import scipy.optimize


def binomial_ci(p, n, alpha=0.05 ):
    """
    Two-sided confidence interval for a binomial test.
   
    Given n successes occurring out of p trials, what is the likely range of
    binomial distribution probabilities that could lead to this observation?
   
    Parameters
    ----------
    p : int
        The number of trials
    n : int
        The number of successful trials
    alpha : int
        The range of the confidence interval to return. (alpha=0.05 gives a 95% confidence interval)
    Credit: http://stackoverflow.com/questions/13059011/is-there-any-python-function-library-for-calculate-binomial-confidence-intervals
    """
    upper_fn = lambda c: scipy.stats.binom.cdf(p, n, c) - alpha
    lower_fn = lambda c: scipy.stats.binom.cdf(p, n, c) - (1.0 - alpha)
    return scipy.optimize.bisect(lower_fn, 0, 1), scipy.optimize.bisect(upper_fn, 0, 1)


def ragged_mean(arrays, method='pad'):
    """Return the mean of a list of arrays, where each array may have 
    different length.
    
    Parameters
    ----------
    arrays : list
        A list of arrays to be averaged
    method : "pad" | "clip"
        If "pad", then the arrays are all padded to the maximum length with NaN.
        If "clip", then the arrays are truncated to the minimum length.
    """
    arrays = arrays[:]
    
    if method == 'pad':
        # Pad all arrays with nan until we have a rectangular array
        max_len = max([len(a) for a in arrays])
        for j,arr in enumerate(arrays):
            if len(arr) < max_len:
                arrays[j] = np.empty(max_len, dtype=arr.dtype)
                arrays[j][:len(arr)] = arr
                arrays[j][len(arr):] = np.nan
    elif method == 'clip':
        min_len = min([len(a) for a in arrays])
        arrays = [arr[:min_len] for arr in arrays]
    else:
        raise ValueError("method must be 'pad' or 'clip'")
            
    # Stack into one array and return the nanmean
    return np.nanmean(np.vstack(arrays), axis=0)

@@ -908,16 +908,2202 @@
 0, 1)%0A%0A%0A
+def binomial_sliding_window(x, success, window, spacing=None, alpha=0.05):%0A    %22%22%22Given a set of success/failure events occurring at different positions,%0A    measure the probability of success versus position using a sliding window.%0A    Also generate confidence intervals on the probability of a binomial%0A    distribution.%0A    %0A    This function is used primarily to measure the probability of synaptic%0A    connection as it varies with the distance between cells. %0A%0A    Parameters%0A    ----------%0A    x : float array%0A        X values of each observation. For cell-cell connectivity, this is the%0A        distance between cells.%0A    success : bool array%0A        True/False indicating success or failure for each observation%0A    window : float%0A        The width of the sliding window within which success probability and%0A        confidence intervals are computed%0A    spacing : float%0A        Distance to advance window for each step.%0A    alpha : float%0A        Width of confidence interval (alpha=0.05 gives 95%25 ci)%0A    %0A    Returns%0A    -------%0A    xvals : array%0A        Center x value of each window step%0A    proportion : array%0A        Proportion of successful trials in each window step%0A    lower : array%0A        Lower binomial confidence interval value at each window step%0A    upper : array%0A        Upper binomial confidence interval value at each window step%0A    %22%22%22%0A    if spacing is None:%0A        spacing = window / 4.0%0A        %0A    xvals = np.arange(window / 2.0, 500e-6, spacing)%0A    upper = %5B%5D%0A    lower = %5B%5D%0A    prop = %5B%5D%0A    ci_xvals = %5B%5D%0A    for x1 in xvals:%0A        minx = x1 - window / 2.0%0A        maxx = x1 + window / 2.0%0A        # select points inside this window%0A        mask = (x %3E= minx) & (x %3C= maxx)%0A        pts_in_window = success%5Bmask%5D%0A        # compute stats for window%0A        n_probed = pts_in_window.shape%5B0%5D%0A        n_conn = pts_in_window.sum()%0A        if n_probed %3E 0:%0A            #prop.append(np.nan)%0A        #else:%0A            prop.append(n_conn / n_probed)%0A            ci = binomial_ci(n_conn, n_probed, alpha=alpha)%0A            lower.append(ci%5B0%5D)%0A            upper.append(ci%5B1%5D)%0A            ci_xvals.append(x1)%0A    %0A    return ci_xvals, prop, lower, upper%0A%0A%0A
 def ragg

add sliding binomial for connectivity characterization