def mfpts(msm, sinks=None, lag_time=1., errors=False, n_samples=100):
    """
    Gets the Mean First Passage Time (MFPT) for all states to a *set*
    of sinks.

    Parameters
    ----------
    msm : msmbuilder.MarkovStateModel
        MSM fit to the data.
    sinks : array_like, int, optional
        Indices of the sink states. There are two use-cases:
            - None [default] : All MFPTs will be calculated, and the
                result is a matrix of the MFPT from state i to state j.
                This uses the fundamental matrix formalism.
            - list of ints or int : Only the MFPTs into these sink
                states will be computed. The result is a vector, with
                entry i corresponding to the average time it takes to
                first get to *any* sink state from state i
    lag_time : float, optional
        Lag time for the model. The MFPT will be reported in whatever
        units are given here. Default is (1) which is in units of the
        lag time of the MSM.
    errors : bool, optional
        Pass "True" if you want to calculate a distribution of MFPTs accounting for MSM model error due to finite 
        sampling 
    n_samples : int, optional
        If "errors" is True, this is the number of MFPTs you want to compute (default = 100). 
        For each computation, all nonzero transition probabilities (i,j) will be treated as 
        Gaussian random variables, with mean equal to the transition probability and standard 
        deviation equal to the standard errot of the mean of the binomial distribution with 
        n observations, where n is the row-summed counts of row i. 
        
        NOTE: This implicitly assumes the Central Limit Theorem is a good approximation for the error, 
        so this method works best with well-sampled data. 
        
    Returns
    -------
    mfpts : np.ndarray, float
        MFPT in time units of lag_time, which depends on the input
        value of sinks:

        - If sinks is None, then mfpts's shape is (n_states, n_states).
            Where mfpts[i, j] is the mean first passage time to state j
            from state i.

        - If sinks contains one or more states, then mfpts's shape
            is (n_states,). Where mfpts[i] is the mean first passage
            time from state i to any state in sinks.
        
    References
    ----------
    .. [1] Grinstead, C. M. and Snell, J. L. Introduction to
           Probability. American Mathematical Soc., 1998.

    As of November 2014, this chapter was available for free online:
        http://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
    """

    if hasattr(msm, 'all_transmats_'):
        if errors:
            output = []
            for i in range(n_samples):
                mfpts = np.zeros_like(msm.all_transmats_)
                for i, el in enumerate(zip(msm.all_transmats_, msm.all_countsmats_)):
                    loc, scale = create_perturb_params(el[1])
                    tprob = perturb_tmat(loc, scale)
                    populations = _solve_msm_eigensystem(tprob, 1)[1]
                    mfpts[i, :, :] = _mfpts(tprob, populations, sinks, lag_time)
                output.append(np.median(mfpts, axis=0))             
            return np.array(output)
        
        mfpts = np.zeros_like(msm.all_transmats_)
        for i, el in enumerate(zip(msm.all_transmats_, msm.all_populations_)):
            tprob = el[0]
            populations = el[1]
            mfpts[i, :, :] = _mfpts(tprob, populations, sinks, lag_time)
        return np.median(mfpts, axis=0)
    
    if errors:
        loc, scale = create_perturb_params(msm.countsmat_)
        output = []
        for i in range(n_samples):
            tprob = perturb_tmat(loc, scale)
            populations = _solve_msm_eigensystem(tprob, 1)[1]
            output.append(_mfpts(tprob, populations, sinks, lag_time))
        return np.array(output)
    return _mfpts(msm.transmat_, msm.populations_, sinks, lag_time)