Instruction:
Implement a function in Python 3 to
generate synthetic observation data from a given state sequence.

Response:
def generate_observation_trajectory(self, s_t):
        """
        Generate synthetic observation data from a given state sequence.

        Parameters
        ----------
        s_t : numpy.array with shape (T,) of int type
            s_t[t] is the hidden state sampled at time t

        Returns
        -------
        o_t : numpy.array with shape (T,) of type dtype
            o_t[t] is the observation associated with state s_t[t]

        Examples
        --------

        Generate an observation model and synthetic state trajectory.

        >>> nobs = 1000
        >>> output_model = GaussianOutputModel(nstates=3, means=[-1, 0, +1], sigmas=[0.5, 1, 2])
        >>> s_t = np.random.randint(0, output_model.nstates, size=[nobs])

        Generate a synthetic trajectory

        >>> o_t = output_model.generate_observation_trajectory(s_t)

        """

        # Determine number of samples to generate.
        T = s_t.shape[0]

        o_t = np.zeros([T], dtype=config.dtype)
        for t in range(T):
            s = s_t[t]
            o_t[t] = self.sigmas[s] * np.random.randn() + self.means[s]
        return o_t


Instruction:
Can you tell what is the following Python 3 function doing
def initial_distribution_samples(self):
        res = np.empty((self.nsamples, self.nstates), dtype=config.dtype)
        for i in range(self.nsamples):
            res[i, :] = self._sampled_hmms[i].stationary_distribution
        return res

Response: r Returns the samples of the initial distribution


Instruction:
Can you generate the documentation for the following Python 3 function
def lifetimes_samples(self):
        res = np.empty((self.nsamples, self.nstates), dtype=config.dtype)
        for i in range(self.nsamples):
            res[i, :] = self._sampled_hmms[i].lifetimes
        return res

Response: r Returns a numpy array of the lifetimes of the timescales


Instruction:
How would you implement a function in Python 3 that
sets the implementation of this module.

Response:
def set_implementation(self, impl):
        """
        Sets the implementation of this module

        Parameters
        ----------
        impl : str
            One of ["python", "c"]

        """
        if impl.lower() == 'python':
            self.__impl__ = self.__IMPL_PYTHON__
        elif impl.lower() == 'c':
            self.__impl__ = self.__IMPL_C__
        else:
            import warnings
            warnings.warn('Implementation '+impl+' is not known. Using the fallback python implementation.')
            self.__impl__ = self.__IMPL_PYTHON__


Instruction:
How would you explain what the following Python 3 function does
def log_p_obs(self, obs, out=None, dtype=np.float32):
        if out is None:
            return np.log(self.p_obs(obs))
        else:
            self.p_obs(obs, out=out, dtype=dtype)
            np.log(out, out=out)
            return out

Response: Returns the element - wise logarithm of the output probabilities for an entire trajectory and all hidden states.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _handle_outliers(self, p_o):
        if self.ignore_outliers:
            outliers = np.where(p_o.sum(axis=1)==0)[0]
            if outliers.size > 0:
                p_o[outliers, :] = 1.0
                self.found_outliers = True
        return p_o

Response: Sets observation probabilities of outliers to uniform if ignore_outliers is set.


Instruction:
Write a Python 3 script to
compute the forward term of the given sequence A and B.

Response:
def forward(A, pobs, pi, T=None, alpha_out=None, dtype=np.float32):
    """Compute P( obs | A, B, pi ) and all forward coefficients.

    Parameters
    ----------
    A : ndarray((N,N), dtype = float)
        transition matrix of the hidden states
    pobs : ndarray((T,N), dtype = float)
        pobs[t,i] is the observation probability for observation at time t given hidden state i
    pi : ndarray((N), dtype = float)
        initial distribution of hidden states
    T : int, optional, default = None
        trajectory length. If not given, T = pobs.shape[0] will be used.
    alpha_out : ndarray((T,N), dtype = float), optional, default = None
        container for the alpha result variables. If None, a new container will be created.
    dtype : type, optional, default = np.float32
        data type of the result.

    Returns
    -------
    logprob : float
        The probability to observe the sequence `ob` with the model given
        by `A`, `B` and `pi`.
    alpha : ndarray((T,N), dtype = float), optional, default = None
        alpha[t,i] is the ith forward coefficient of time t. These can be
        used in many different algorithms related to HMMs.

    """
    # set T
    if T is None:
        T = pobs.shape[0]  # if not set, use the length of pobs as trajectory length
    elif T > pobs.shape[0]:
        raise ValueError('T must be at most the length of pobs.')
    # set N
    N = A.shape[0]
    # initialize output if necessary
    if alpha_out is None:
        alpha_out = np.zeros((T, N), dtype=dtype)
    elif T > alpha_out.shape[0]:
        raise ValueError('alpha_out must at least have length T in order to fit trajectory.')
    # log-likelihood
    logprob = 0.0

    # initial values
    # alpha_i(0) = pi_i * B_i,ob[0]
    np.multiply(pi, pobs[0, :], out=alpha_out[0])
    # scaling factor
    scale = np.sum(alpha_out[0, :])
    # scale
    alpha_out[0, :] /= scale
    logprob += np.log(scale)

    # induction
    for t in range(T-1):
        # alpha_j(t+1) = sum_i alpha_i(t) * A_i,j * B_j,ob(t+1)
        np.multiply(np.dot(alpha_out[t, :], A), pobs[t+1, :], out=alpha_out[t+1])
        # scaling factor
        scale = np.sum(alpha_out[t+1, :])
        # scale
        alpha_out[t+1, :] /= scale
        # update logprob
        logprob += np.log(scale)

    return logprob, alpha_out


Instruction:
How would you implement a function in Python 3 that
computes all backward coefficients of the hidden states A and pobs.

Response:
def backward(A, pobs, T=None, beta_out=None, dtype=np.float32):
    """Compute all backward coefficients. With scaling!

    Parameters
    ----------
    A : ndarray((N,N), dtype = float)
        transition matrix of the hidden states
    pobs : ndarray((T,N), dtype = float)
        pobs[t,i] is the observation probability for observation at time t given hidden state i
    beta_out : ndarray((T,N), dtype = float), optional, default = None
        containter for the beta result variables. If None, a new container will be created.
    dtype : type, optional, default = np.float32
        data type of the result.

    Returns
    -------
    beta : ndarray((T,N), dtype = float), optional, default = None
        beta[t,i] is the ith backward coefficient of time t. These can be
        used in many different algorithms related to HMMs.

    """
    # set T
    if T is None:
        T = pobs.shape[0]  # if not set, use the length of pobs as trajectory length
    elif T > pobs.shape[0]:
        raise ValueError('T must be at most the length of pobs.')
    # set N
    N = A.shape[0]
    # initialize output if necessary
    if beta_out is None:
        beta_out = np.zeros((T, N), dtype=dtype)
    elif T > beta_out.shape[0]:
        raise ValueError('beta_out must at least have length T in order to fit trajectory.')

    # initialization
    beta_out[T-1, :] = 1.0
    # scaling factor
    scale = np.sum(beta_out[T-1, :])
    # scale
    beta_out[T-1, :] /= scale

    # induction
    for t in range(T-2, -1, -1):
        # beta_i(t) = sum_j A_i,j * beta_j(t+1) * B_j,ob(t+1)
        np.dot(A, beta_out[t+1, :] * pobs[t+1, :], out=beta_out[t, :])
        # scaling factor
        scale = np.sum(beta_out[t, :])
        # scale
        beta_out[t, :] /= scale
    return beta_out


Instruction:
Can you generate the documentation for the following Python 3 function
def transition_counts(alpha, beta, A, pobs, T=None, out=None, dtype=np.float32):
    # set T
    if T is None:
        T = pobs.shape[0]  # if not set, use the length of pobs as trajectory length
    elif T > pobs.shape[0]:
        raise ValueError('T must be at most the length of pobs.')
    # set N
    N = len(A)
    # output
    if out is None:
        out = np.zeros((N, N), dtype=dtype, order='C')
    else:
        out[:] = 0.0
    # compute transition counts
    xi = np.zeros((N, N), dtype=dtype, order='C')
    for t in range(T-1):
        # xi_i,j(t) = alpha_i(t) * A_i,j * B_j,ob(t+1) * beta_j(t+1)
        np.dot(alpha[t, :][:, None] * A, np.diag(pobs[t+1, :] * beta[t+1, :]), out=xi)
        # normalize to 1 for each time step
        xi /= np.sum(xi)
        # add to counts
        np.add(out, xi, out)
    # return
    return out

Response: Sum for all t the probability to transition from state i to state j.


Instruction:
Implement a Python 3 function for
estimating the hidden pathway of maximum likelihood using the Viterbi algorithm.

Response:
def viterbi(A, pobs, pi, dtype=np.float32):
    """ Estimate the hidden pathway of maximum likelihood using the Viterbi algorithm.

    Parameters
    ----------
    A : ndarray((N,N), dtype = float)
        transition matrix of the hidden states
    pobs : ndarray((T,N), dtype = float)
        pobs[t,i] is the observation probability for observation at time t given hidden state i
    pi : ndarray((N), dtype = float)
        initial distribution of hidden states

    Returns
    -------
    q : numpy.array shape (T)
        maximum likelihood hidden path

    """
    T, N = pobs.shape[0], pobs.shape[1]
    # temporary viterbi state
    psi = np.zeros((T, N), dtype=int)
    # initialize
    v = pi * pobs[0, :]
    # rescale
    v /= v.sum()
    psi[0] = 0.0
    # iterate
    for t in range(1, T):
        vA = np.dot(np.diag(v), A)
        # propagate v
        v = pobs[t, :] * np.max(vA, axis=0)
        # rescale
        v /= v.sum()
        psi[t] = np.argmax(vA, axis=0)
    # iterate
    q = np.zeros(T, dtype=int)
    q[T-1] = np.argmax(v)
    for t in range(T-2, -1, -1):
        q[t] = psi[t+1, q[t+1]]
    # done
    return q


Instruction:
How would you implement a function in Python 3 that
samples from the path of the hidden state.

Response:
def sample_path(alpha, A, pobs, T=None, dtype=np.float32):
    """
    alpha : ndarray((T,N), dtype = float), optional, default = None
        alpha[t,i] is the ith forward coefficient of time t.
    beta : ndarray((T,N), dtype = float), optional, default = None
        beta[t,i] is the ith forward coefficient of time t.
    A : ndarray((N,N), dtype = float)
        transition matrix of the hidden states
    pobs : ndarray((T,N), dtype = float)
        pobs[t,i] is the observation probability for observation at time t given hidden state i
    """
    N = pobs.shape[1]
    # set T
    if T is None:
        T = pobs.shape[0]  # if not set, use the length of pobs as trajectory length
    elif T > pobs.shape[0] or T > alpha.shape[0]:
        raise ValueError('T must be at most the length of pobs and alpha.')

    # initialize path
    S = np.zeros(T, dtype=int)

    # Sample final state.
    psel = alpha[T-1, :]
    psel /= psel.sum()  # make sure it's normalized
    # Draw from this distribution.
    S[T-1] = np.random.choice(range(N), size=1, p=psel)

    # Work backwards from T-2 to 0.
    for t in range(T-2, -1, -1):
        # Compute P(s_t = i | s_{t+1}..s_T).
        psel = alpha[t, :] * A[:, S[t+1]]
        psel /= psel.sum()  # make sure it's normalized
        # Draw from this distribution.
        S[t] = np.random.choice(range(N), size=1, p=psel)

    return S


Instruction:
Make a summary of the following Python 3 code
def coarse_grain_transition_matrix(P, M):
    # coarse-grain matrix: Pc = (M' M)^-1 M' P M
    W = np.linalg.inv(np.dot(M.T, M))
    A = np.dot(np.dot(M.T, P), M)
    P_coarse = np.dot(W, A)

    # this coarse-graining can lead to negative elements. Setting them to zero here.
    P_coarse = np.maximum(P_coarse, 0)
    # and renormalize
    P_coarse /= P_coarse.sum(axis=1)[:, None]

    return P_coarse

Response: Coarse grain transition matrix P using memberships M


Instruction:
Can you create a Python 3 function that
regularizes the hidden initial distribution and transition matrix P.

Response:
def regularize_hidden(p0, P, reversible=True, stationary=False, C=None, eps=None):
    """ Regularizes the hidden initial distribution and transition matrix.

    Makes sure that the hidden initial distribution and transition matrix have
    nonzero probabilities by setting them to eps and then renormalizing.
    Avoids zeros that would cause estimation algorithms to crash or get stuck
    in suboptimal states.

    Parameters
    ----------
    p0 : ndarray(n)
        Initial hidden distribution of the HMM
    P : ndarray(n, n)
        Hidden transition matrix
    reversible : bool
        HMM is reversible. Will make sure it is still reversible after modification.
    stationary : bool
        p0 is the stationary distribution of P. In this case, will not regularize
        p0 separately. If stationary=False, the regularization will be applied to p0.
    C : ndarray(n, n)
        Hidden count matrix. Only needed for stationary=True and P disconnected.
    epsilon : float or None
        minimum value of the resulting transition matrix. Default: evaluates
        to 0.01 / n. The coarse-graining equation can lead to negative elements
        and thus epsilon should be set to at least 0. Positive settings of epsilon
        are similar to a prior and enforce minimum positive values for all
        transition probabilities.

    Return
    ------
    p0 : ndarray(n)
        regularized initial distribution
    P : ndarray(n, n)
        regularized transition matrix

    """
    # input
    n = P.shape[0]
    if eps is None:  # default output probability, in order to avoid zero columns
        eps = 0.01 / n

    # REGULARIZE P
    P = np.maximum(P, eps)
    # and renormalize
    P /= P.sum(axis=1)[:, None]
    # ensure reversibility
    if reversible:
        P = _tmatrix_disconnected.enforce_reversible_on_closed(P)

    # REGULARIZE p0
    if stationary:
        _tmatrix_disconnected.stationary_distribution(P, C=C)
    else:
        p0 = np.maximum(p0, eps)
        p0 /= p0.sum()

    return p0, P


Instruction:
Can you create a Python 3 function that
regularizes the output probabilities of the given set of observed states.

Response:
def regularize_pobs(B, nonempty=None, separate=None, eps=None):
    """ Regularizes the output probabilities.

    Makes sure that the output probability distributions has
    nonzero probabilities by setting them to eps and then renormalizing.
    Avoids zeros that would cause estimation algorithms to crash or get stuck
    in suboptimal states.

    Parameters
    ----------
    B : ndarray(n, m)
        HMM output probabilities
    nonempty : None or iterable of int
        Nonempty set. Only regularize on this subset.
    separate : None or iterable of int
        Force the given set of observed states to stay in a separate hidden state.
        The remaining nstates-1 states will be assigned by a metastable decomposition.
    reversible : bool
        HMM is reversible. Will make sure it is still reversible after modification.

    Returns
    -------
    B : ndarray(n, m)
        Regularized output probabilities

    """
    # input
    B = B.copy()  # modify copy
    n, m = B.shape  # number of hidden / observable states
    if eps is None:  # default output probability, in order to avoid zero columns
        eps = 0.01 / m
    # observable sets
    if nonempty is None:
        nonempty = np.arange(m)

    if separate is None:
        B[:, nonempty] = np.maximum(B[:, nonempty], eps)
    else:
        nonempty_nonseparate = np.array(list(set(nonempty) - set(separate)), dtype=int)
        nonempty_separate = np.array(list(set(nonempty).intersection(set(separate))), dtype=int)
        B[:n-1, nonempty_nonseparate] = np.maximum(B[:n-1, nonempty_nonseparate], eps)
        B[n-1, nonempty_separate] = np.maximum(B[n-1, nonempty_separate], eps)

    # renormalize and return copy
    B /= B.sum(axis=1)[:, None]
    return B


Instruction:
Can you generate the documentation for the following Python 3 function
def init_discrete_hmm_spectral(C_full, nstates, reversible=True, stationary=True, active_set=None, P=None,
                               eps_A=None, eps_B=None, separate=None):
    """Initializes discrete HMM using spectral clustering of observation counts

    Initializes HMM as described in [1]_. First estimates a Markov state model
    on the given observations, then uses PCCA+ to coarse-grain the transition
    matrix [2]_ which initializes the HMM transition matrix. The HMM output
    probabilities are given by Bayesian inversion from the PCCA+ memberships [1]_.

    The regularization parameters eps_A and eps_B are used
    to guarantee that the hidden transition matrix and output probability matrix
    have no zeros. HMM estimation algorithms such as the EM algorithm and the
    Bayesian sampling algorithm cannot recover from zero entries, i.e. once they
    are zero, they will stay zero.

    Parameters
    ----------
    C_full : ndarray(N, N)
        Transition count matrix on the full observable state space
    nstates : int
        The number of hidden states.
    reversible : bool
        Estimate reversible HMM transition matrix.
    stationary : bool
        p0 is the stationary distribution of P. In this case, will not
    active_set : ndarray(n, dtype=int) or None
        Index area. Will estimate kinetics only on the given subset of C
    P : ndarray(n, n)
        Transition matrix estimated from C (with option reversible). Use this
        option if P has already been estimated to avoid estimating it twice.
    eps_A : float or None
        Minimum transition probability. Default: 0.01 / nstates
    eps_B : float or None
        Minimum output probability. Default: 0.01 / nfull
    separate : None or iterable of int
        Force the given set of observed states to stay in a separate hidden state.
        The remaining nstates-1 states will be assigned by a metastable decomposition.

    Returns
    -------
    p0 : ndarray(n)
        Hidden state initial distribution
    A : ndarray(n, n)
        Hidden state transition matrix
    B : ndarray(n, N)
        Hidden-to-observable state output probabilities

    Raises
    ------
    ValueError
        If the given active set is illegal.
    NotImplementedError
        If the number of hidden states exceeds the number of observed states.

    Examples
    --------
    Generate initial model for a discrete output model.

    >>> import numpy as np
    >>> C = np.array([[0.5, 0.5, 0.0], [0.4, 0.5, 0.1], [0.0, 0.1, 0.9]])
    >>> initial_model = init_discrete_hmm_spectral(C, 2)

    References
    ----------
    .. [1] F. Noe, H. Wu, J.-H. Prinz and N. Plattner: Projected and hidden
        Markov models for calculating kinetics and  metastable states of
        complex molecules. J. Chem. Phys. 139, 184114 (2013)
    .. [2] S. Kube and M. Weber: A coarse graining method for the identification
        of transition rates between molecular conformations.
        J. Chem. Phys. 126, 024103 (2007)

    """
    # MICROSTATE COUNT MATRIX
    nfull = C_full.shape[0]

    # INPUTS
    if eps_A is None:  # default transition probability, in order to avoid zero columns
        eps_A = 0.01 / nstates
    if eps_B is None:  # default output probability, in order to avoid zero columns
        eps_B = 0.01 / nfull
    # Manage sets
    symsum = C_full.sum(axis=0) + C_full.sum(axis=1)
    nonempty = np.where(symsum > 0)[0]
    if active_set is None:
        active_set = nonempty
    else:
        if np.any(symsum[active_set] == 0):
            raise ValueError('Given active set has empty states')  # don't tolerate empty states
    if P is not None:
        if np.shape(P)[0] != active_set.size:  # needs to fit to active
            raise ValueError('Given initial transition matrix P has shape ' + str(np.shape(P))
                             + 'while active set has size ' + str(active_set.size))
    # when using separate states, only keep the nonempty ones (the others don't matter)
    if separate is None:
        active_nonseparate = active_set.copy()
        nmeta = nstates
    else:
        if np.max(separate) >= nfull:
            raise ValueError('Separate set has indexes that do not exist in full state space: '
                             + str(np.max(separate)))
        active_nonseparate = np.array(list(set(active_set) - set(separate)))
        nmeta = nstates - 1
    # check if we can proceed
    if active_nonseparate.size < nmeta:
        raise NotImplementedError('Trying to initialize ' + str(nmeta) + '-state HMM from smaller '
                                  + str(active_nonseparate.size) + '-state MSM.')

    # MICROSTATE TRANSITION MATRIX (MSM).
    C_active = C_full[np.ix_(active_set, active_set)]
    if P is None:  # This matrix may be disconnected and have transient states
        P_active = _tmatrix_disconnected.estimate_P(C_active, reversible=reversible, maxiter=10000)  # short iteration
    else:
        P_active = P

    # MICROSTATE EQUILIBRIUM DISTRIBUTION
    pi_active = _tmatrix_disconnected.stationary_distribution(P_active, C=C_active)
    pi_full = np.zeros(nfull)
    pi_full[active_set] = pi_active

    # NONSEPARATE TRANSITION MATRIX FOR PCCA+
    C_active_nonseparate = C_full[np.ix_(active_nonseparate, active_nonseparate)]
    if reversible and separate is None:  # in this case we already have a reversible estimate with the right size
        P_active_nonseparate = P_active
    else:  # not yet reversible. re-estimate
        P_active_nonseparate = _tmatrix_disconnected.estimate_P(C_active_nonseparate, reversible=True)

    # COARSE-GRAINING WITH PCCA+
    if active_nonseparate.size > nmeta:
        from msmtools.analysis.dense.pcca import PCCA
        pcca_obj = PCCA(P_active_nonseparate, nmeta)
        M_active_nonseparate = pcca_obj.memberships  # memberships
        B_active_nonseparate = pcca_obj.output_probabilities  # output probabilities
    else:  # equal size
        M_active_nonseparate = np.eye(nmeta)
        B_active_nonseparate = np.eye(nmeta)

    # ADD SEPARATE STATE IF NEEDED
    if separate is None:
        M_active = M_active_nonseparate
    else:
        M_full = np.zeros((nfull, nstates))
        M_full[active_nonseparate, :nmeta] = M_active_nonseparate
        M_full[separate, -1] = 1
        M_active = M_full[active_set]

    # COARSE-GRAINED TRANSITION MATRIX
    P_hmm = coarse_grain_transition_matrix(P_active, M_active)
    if reversible:
        P_hmm = _tmatrix_disconnected.enforce_reversible_on_closed(P_hmm)
    C_hmm = M_active.T.dot(C_active).dot(M_active)
    pi_hmm = _tmatrix_disconnected.stationary_distribution(P_hmm, C=C_hmm)  # need C_hmm in case if A is disconnected

    # COARSE-GRAINED OUTPUT DISTRIBUTION
    B_hmm = np.zeros((nstates, nfull))
    B_hmm[:nmeta, active_nonseparate] = B_active_nonseparate
    if separate is not None:  # add separate states
        B_hmm[-1, separate] = pi_full[separate]

    # REGULARIZE SOLUTION
    pi_hmm, P_hmm = regularize_hidden(pi_hmm, P_hmm, reversible=reversible, stationary=stationary, C=C_hmm, eps=eps_A)
    B_hmm = regularize_pobs(B_hmm, nonempty=nonempty, separate=separate, eps=eps_B)

    # print 'cg pi: ', pi_hmm
    # print 'cg A:\n ', P_hmm
    # print 'cg B:\n ', B_hmm

    logger().info('Initial model: ')
    logger().info('initial distribution = \n'+str(pi_hmm))
    logger().info('transition matrix = \n'+str(P_hmm))
    logger().info('output matrix = \n'+str(B_hmm.T))

    return pi_hmm, P_hmm, B_hmm

Response: Initializes discrete HMM using spectral clustering of observation counts C_full.


Instruction:
How would you explain what the following Python 3 function does
def init_discrete_hmm_ml(C_full, nstates, reversible=True, stationary=True, active_set=None, P=None,
                         eps_A=None, eps_B=None, separate=None):
    """Initializes discrete HMM using maximum likelihood of observation counts"""
    raise NotImplementedError('ML-initialization not yet implemented')

Response: Initializes discrete HMM using maximum likelihood of observation counts


Instruction:
Can you generate the documentation for the following Python 3 function
def is_stationary(self):
        # for disconnected matrices, the stationary distribution depends on the estimator, so we can't compute
        # it directly. Therefore we test whether the initial distribution is stationary.
        return np.allclose(np.dot(self._Pi, self._Tij), self._Pi)

Response: r Returns True if the MSM is stationary.


Instruction:
How would you code a function in Python 3 to
compute the stationary distribution of hidden states if possible.

Response:
def stationary_distribution(self):
        r""" Compute stationary distribution of hidden states if possible.

        Raises
        ------
        ValueError if the HMM is not stationary

        """
        assert _tmatrix_disconnected.is_connected(self._Tij, strong=False), \
            'No unique stationary distribution because transition matrix is not connected'
        import msmtools.analysis as msmana
        return msmana.stationary_distribution(self._Tij)


Instruction:
Create a Python 3 function for
returning the relaxation timescales of the hidden transition matrix.

Response:
def timescales(self):
        r""" Relaxation timescales of the hidden transition matrix

        Returns
        -------
        ts : ndarray(m)
            relaxation timescales in units of the input trajectory time step,
            defined by :math:`-tau / ln | \lambda_i |, i = 2,...,nstates`, where
            :math:`\lambda_i` are the hidden transition matrix eigenvalues.

        """
        from msmtools.analysis.dense.decomposition import timescales_from_eigenvalues as _timescales

        self._ensure_spectral_decomposition()
        ts = _timescales(self._eigenvalues, tau=self._lag)
        return ts[1:]


Instruction:
Implement a Python 3 function for
returning the lifetimes of the hidden transition matrix.

Response:
def lifetimes(self):
        r""" Lifetimes of states of the hidden transition matrix

        Returns
        -------
        l : ndarray(nstates)
            state lifetimes in units of the input trajectory time step,
            defined by :math:`-tau / ln | p_{ii} |, i = 1,...,nstates`, where
            :math:`p_{ii}` are the diagonal entries of the hidden transition matrix.

        """
        return -self._lag / np.log(np.diag(self.transition_matrix))


Instruction:
Given the following Python 3 function, write the documentation
def sub_hmm(self, states):
        # restrict initial distribution
        pi_sub = self._Pi[states]
        pi_sub /= pi_sub.sum()

        # restrict transition matrix
        P_sub = self._Tij[states, :][:, states]
        # checks if this selection is possible
        assert np.all(P_sub.sum(axis=1) > 0), \
            'Illegal sub_hmm request: transition matrix cannot be normalized on ' + str(states)
        P_sub /= P_sub.sum(axis=1)[:, None]

        # restrict output model
        out_sub = self.output_model.sub_output_model(states)

        return HMM(pi_sub, P_sub, out_sub, lag=self.lag)

Response: r Returns the HMM restricted to the selected subset of states


Instruction:
Given the following Python 3 function, write the documentation
def count_matrix(self):
        # TODO: does this belong here or to the BHMM sampler, or in a subclass containing HMM with data?
        """Compute the transition count matrix from hidden state trajectory.

        Returns
        -------
        C : numpy.array with shape (nstates,nstates)
            C[i,j] is the number of transitions observed from state i to state j

        Raises
        ------
        RuntimeError
            A RuntimeError is raised if the HMM model does not yet have a hidden state trajectory associated with it.

        Examples
        --------

        """
        if self.hidden_state_trajectories is None:
            raise RuntimeError('HMM model does not have a hidden state trajectory.')

        C = msmest.count_matrix(self.hidden_state_trajectories, 1, nstates=self._nstates)
        return C.toarray()

Response: Compute the transition count matrix from the hidden state trajectory.


Instruction:
Create a Python 3 function for
computing the counts at the first time step

Response:
def count_init(self):
        """Compute the counts at the first time step

        Returns
        -------
        n : ndarray(nstates)
            n[i] is the number of trajectories starting in state i

        """
        if self.hidden_state_trajectories is None:
            raise RuntimeError('HMM model does not have a hidden state trajectory.')

        n = [traj[0] for traj in self.hidden_state_trajectories]
        return np.bincount(n, minlength=self.nstates)


Instruction:
Here you have a function in Python 3, explain what it does
def collect_observations_in_state(self, observations, state_index):
        # TODO: this would work well in a subclass with data
        """Collect a vector of all observations belonging to a specified hidden state.

        Parameters
        ----------
        observations : list of numpy.array
            List of observed trajectories.
        state_index : int
            The index of the hidden state for which corresponding observations are to be retrieved.
        dtype : numpy.dtype, optional, default=numpy.float64
            The numpy dtype to use to store the collected observations.

        Returns
        -------
        collected_observations : numpy.array with shape (nsamples,)
            The collected vector of observations belonging to the specified hidden state.

        Raises
        ------
        RuntimeError
            A RuntimeError is raised if the HMM model does not yet have a hidden state trajectory associated with it.

        """
        if not self.hidden_state_trajectories:
            raise RuntimeError('HMM model does not have a hidden state trajectory.')

        dtype = observations[0].dtype
        collected_observations = np.array([], dtype=dtype)
        for (s_t, o_t) in zip(self.hidden_state_trajectories, observations):
            indices = np.where(s_t == state_index)[0]
            collected_observations = np.append(collected_observations, o_t[indices])

        return collected_observations

Response: Collect a vector of all observations belonging to a specified hidden state.


Instruction:
Implement a function in Python 3 to
generate a synthetic state trajectory.

Response:
def generate_synthetic_state_trajectory(self, nsteps, initial_Pi=None, start=None, stop=None, dtype=np.int32):
        """Generate a synthetic state trajectory.

        Parameters
        ----------
        nsteps : int
            Number of steps in the synthetic state trajectory to be generated.
        initial_Pi : np.array of shape (nstates,), optional, default=None
            The initial probability distribution, if samples are not to be taken from the intrinsic
            initial distribution.
        start : int
            starting state. Exclusive with initial_Pi
        stop : int
            stopping state. Trajectory will terminate when reaching the stopping state before length number of steps.
        dtype : numpy.dtype, optional, default=numpy.int32
            The numpy dtype to use to store the synthetic trajectory.

        Returns
        -------
        states : np.array of shape (nstates,) of dtype=np.int32
            The trajectory of hidden states, with each element in range(0,nstates).

        Examples
        --------

        Generate a synthetic state trajectory of a specified length.

        >>> from bhmm import testsystems
        >>> model = testsystems.dalton_model()
        >>> states = model.generate_synthetic_state_trajectory(nsteps=100)

        """
        # consistency check
        if initial_Pi is not None and start is not None:
            raise ValueError('Arguments initial_Pi and start are exclusive. Only set one of them.')

        # Generate first state sample.
        if start is None:
            if initial_Pi is not None:
                start = np.random.choice(range(self._nstates), size=1, p=initial_Pi)
            else:
                start = np.random.choice(range(self._nstates), size=1, p=self._Pi)

        # Generate and return trajectory
        from msmtools import generation as msmgen
        traj = msmgen.generate_traj(self.transition_matrix, nsteps, start=start, stop=stop, dt=1)
        return traj.astype(dtype)


Instruction:
How would you explain what the following Python 3 function does
def generate_synthetic_observation_trajectory(self, length, initial_Pi=None):
        # First, generate synthetic state trajetory.
        s_t = self.generate_synthetic_state_trajectory(length, initial_Pi=initial_Pi)

        # Next, generate observations from these states.
        o_t = self.output_model.generate_observation_trajectory(s_t)

        return [o_t, s_t]

Response: Generate a synthetic state trajectory for an equilibrium realization.


Instruction:
Write a Python 3 function for
generating a number of synthetic realization of observables from this model.

Response:
def generate_synthetic_observation_trajectories(self, ntrajectories, length, initial_Pi=None):
        """Generate a number of synthetic realization of observables from this model.

        Parameters
        ----------
        ntrajectories : int
            The number of trajectories to be generated.
        length : int
            Length of synthetic state trajectory to be generated.
        initial_Pi : np.array of shape (nstates,), optional, default=None
            The initial probability distribution, if samples are not to be taken from equilibrium.

        Returns
        -------
        O : list of np.array of shape (nstates,) of dtype=np.float32
            The trajectories of observations
        S : list of np.array of shape (nstates,) of dtype=np.int32
            The trajectories of hidden states

        Examples
        --------

        Generate a number of synthetic trajectories.

        >>> from bhmm import testsystems
        >>> model = testsystems.dalton_model()
        >>> O, S = model.generate_synthetic_observation_trajectories(ntrajectories=10, length=100)

        Use an initial nonequilibrium distribution.

        >>> from bhmm import testsystems
        >>> model = testsystems.dalton_model(nstates=3)
        >>> O, S = model.generate_synthetic_observation_trajectories(ntrajectories=10, length=100, initial_Pi=np.array([1,0,0]))

        """
        O = list()  # observations
        S = list()  # state trajectories
        for trajectory_index in range(ntrajectories):
            o_t, s_t = self.generate_synthetic_observation_trajectory(length=length, initial_Pi=initial_Pi)
            O.append(o_t)
            S.append(s_t)

        return O, S


Instruction:
Implement a Python 3 function for
converting notebook to python script

Response:
def nb_to_python(nb_path):
    """convert notebook to python script"""
    exporter = python.PythonExporter()
    output, resources = exporter.from_filename(nb_path)
    return output


Instruction:
Write a Python 3 script for
converting notebook to html

Response:
def nb_to_html(nb_path):
    """convert notebook to html"""
    exporter = html.HTMLExporter(template_file='full')
    output, resources = exporter.from_filename(nb_path)
    header = output.split('<head>', 1)[1].split('</head>',1)[0]
    body = output.split('<body>', 1)[1].split('</body>',1)[0]

    # http://imgur.com/eR9bMRH
    header = header.replace('<style', '<style scoped="scoped"')
    header = header.replace('body {\n  overflow: visible;\n  padding: 8px;\n}\n', '')

    # Filter out styles that conflict with the sphinx theme.
    filter_strings = [
        'navbar',
        'body{',
        'alert{',
        'uneditable-input{',
        'collapse{',
    ]
    filter_strings.extend(['h%s{' % (i+1) for i in range(6)])

    header_lines = filter(
        lambda x: not any([s in x for s in filter_strings]), header.split('\n'))
    header = '\n'.join(header_lines)

    # concatenate raw html lines
    lines = ['<div class="ipynotebook">']
    lines.append(header)
    lines.append(body)
    lines.append('</div>')
    return '\n'.join(lines)


Instruction:
Implement a function in Python 3 to
return the output probabilities for an entire trajectory and all hidden states at time point t.

Response:
def p_obs(self, obs, out=None):
        """
        Returns the output probabilities for an entire trajectory and all hidden states

        Parameters
        ----------
        obs : ndarray((T), dtype=int)
            a discrete trajectory of length T

        Return
        ------
        p_o : ndarray (T,N)
            the probability of generating the symbol at time point t from any of the N hidden states

        """
        if out is None:
            out = self._output_probabilities[:, obs].T
            # out /= np.sum(out, axis=1)[:,None]
            return self._handle_outliers(out)
        else:
            if obs.shape[0] == out.shape[0]:
                np.copyto(out, self._output_probabilities[:, obs].T)
            elif obs.shape[0] < out.shape[0]:
                out[:obs.shape[0], :] = self._output_probabilities[:, obs].T
            else:
                raise ValueError('output array out is too small: '+str(out.shape[0])+' < '+str(obs.shape[0]))
            # out /= np.sum(out, axis=1)[:,None]
            return self._handle_outliers(out)


Instruction:
Can you generate the documentation for the following Python 3 function
def sample(self, observations_by_state):
        from numpy.random import dirichlet
        N, M = self._output_probabilities.shape  # nstates, nsymbols
        for i, obs_by_state in enumerate(observations_by_state):
            # count symbols found in data
            count = np.bincount(obs_by_state, minlength=M).astype(float)
            # sample dirichlet distribution
            count += self.prior[i]
            positive = count > 0
            # if counts at all: can't sample, so leave output probabilities as they are.
            self._output_probabilities[i, positive] = dirichlet(count[positive])

Response: Sample a new set of distribution parameters given a sample of observations from the given state.


Instruction:
Write a Python 3 script to
generate a single synthetic observation data from a given state.

Response:
def generate_observation_from_state(self, state_index):
        """
        Generate a single synthetic observation data from a given state.

        Parameters
        ----------
        state_index : int
            Index of the state from which observations are to be generated.

        Returns
        -------
        observation : float
            A single observation from the given state.

        Examples
        --------

        Generate an observation model.

        >>> output_model = DiscreteOutputModel(np.array([[0.5,0.5],[0.1,0.9]]))

        Generate sample from each state.

        >>> observation = output_model.generate_observation_from_state(0)

        """
        # generate random generator (note that this is inefficient - better use one of the next functions
        import scipy.stats
        gen = scipy.stats.rv_discrete(values=(range(len(self._output_probabilities[state_index])),
                                              self._output_probabilities[state_index]))
        gen.rvs(size=1)


Instruction:
Can you tell what is the following Python 3 function doing
def generate_observations_from_state(self, state_index, nobs):
        import scipy.stats
        gen = scipy.stats.rv_discrete(values=(range(self._nsymbols), self._output_probabilities[state_index]))
        gen.rvs(size=nobs)

Response: Generate synthetic observation data from a given state.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def generate_observation_trajectory(self, s_t, dtype=None):
        if dtype is None:
            dtype = np.int32

        # Determine number of samples to generate.
        T = s_t.shape[0]
        nsymbols = self._output_probabilities.shape[1]

        if (s_t.max() >= self.nstates) or (s_t.min() < 0):
            msg = ''
            msg += 's_t = %s\n' % s_t
            msg += 's_t.min() = %d, s_t.max() = %d\n' % (s_t.min(), s_t.max())
            msg += 's_t.argmax = %d\n' % s_t.argmax()
            msg += 'self.nstates = %d\n' % self.nstates
            msg += 's_t is out of bounds.\n'
            raise Exception(msg)

        # generate random generators
        # import scipy.stats
        # gens = [scipy.stats.rv_discrete(values=(range(len(self.B[state_index])), self.B[state_index]))
        #         for state_index in range(self.B.shape[0])]
        # o_t = np.zeros([T], dtype=dtype)
        # for t in range(T):
        #     s = s_t[t]
        #     o_t[t] = gens[s].rvs(size=1)
        # return o_t

        o_t = np.zeros([T], dtype=dtype)
        for t in range(T):
            s = s_t[t]
            o_t[t] = np.random.choice(nsymbols, p=self._output_probabilities[s, :])

        return o_t

Response: Generate synthetic observation data from a given state sequence.


Instruction:
Given the following Python 3 function, write the documentation
def set_implementation(impl):
    global __impl__
    if impl.lower() == 'python':
        __impl__ = __IMPL_PYTHON__
    elif impl.lower() == 'c':
        __impl__ = __IMPL_C__
    else:
        import warnings
        warnings.warn('Implementation '+impl+' is not known. Using the fallback python implementation.')
        __impl__ = __IMPL_PYTHON__

Response: Sets the implementation of this module


Instruction:
How would you implement a function in Python 3 that
computes P ( obs | A B pi ) and all forward coefficients.

Response:
def forward(A, pobs, pi, T=None, alpha_out=None):
    """Compute P( obs | A, B, pi ) and all forward coefficients.

    Parameters
    ----------
    A : ndarray((N,N), dtype = float)
        transition matrix of the hidden states
    pobs : ndarray((T,N), dtype = float)
        pobs[t,i] is the observation probability for observation at time t given hidden state i
    pi : ndarray((N), dtype = float)
        initial distribution of hidden states
    T : int, optional, default = None
        trajectory length. If not given, T = pobs.shape[0] will be used.
    alpha_out : ndarray((T,N), dtype = float), optional, default = None
        containter for the alpha result variables. If None, a new container will be created.

    Returns
    -------
    logprob : float
        The probability to observe the sequence `ob` with the model given
        by `A`, `B` and `pi`.
    alpha : ndarray((T,N), dtype = float), optional, default = None
        alpha[t,i] is the ith forward coefficient of time t. These can be
        used in many different algorithms related to HMMs.

    """
    if __impl__ == __IMPL_PYTHON__:
        return ip.forward(A, pobs, pi, T=T, alpha_out=alpha_out, dtype=config.dtype)
    elif __impl__ == __IMPL_C__:
        return ic.forward(A, pobs, pi, T=T, alpha_out=alpha_out, dtype=config.dtype)
    else:
        raise RuntimeError('Nonexisting implementation selected: '+str(__impl__))


Instruction:
Here you have a function in Python 3, explain what it does
def backward(A, pobs, T=None, beta_out=None):
    if __impl__ == __IMPL_PYTHON__:
        return ip.backward(A, pobs, T=T, beta_out=beta_out, dtype=config.dtype)
    elif __impl__ == __IMPL_C__:
        return ic.backward(A, pobs, T=T, beta_out=beta_out, dtype=config.dtype)
    else:
        raise RuntimeError('Nonexisting implementation selected: '+str(__impl__))

Response: Compute all backward coefficients of the hidden states A.


Instruction:
Can you generate the documentation for the following Python 3 function
def state_probabilities(alpha, beta, T=None, gamma_out=None):
    # get summation helper - we use matrix multiplication with 1's because it's faster than the np.sum function (yes!)
    global ones_size
    if ones_size != alpha.shape[1]:
        global ones
        ones = np.ones(alpha.shape[1])[:, None]
        ones_size = alpha.shape[1]
    #
    if alpha.shape[0] != beta.shape[0]:
        raise ValueError('Inconsistent sizes of alpha and beta.')
    # determine T to use
    if T is None:
        if gamma_out is None:
            T = alpha.shape[0]
        else:
            T = gamma_out.shape[0]
    # compute
    if gamma_out is None:
        gamma_out = alpha * beta
        if T < gamma_out.shape[0]:
            gamma_out = gamma_out[:T]
    else:
        if gamma_out.shape[0] < alpha.shape[0]:
            np.multiply(alpha[:T], beta[:T], gamma_out)
        else:
            np.multiply(alpha, beta, gamma_out)
    # normalize
    np.divide(gamma_out, np.dot(gamma_out, ones), out=gamma_out)
    # done
    return gamma_out

Response: Calculates the probability matrix for being in state i at time t.


Instruction:
How would you implement a function in Python 3 that
sums the probabilities of being in state i to time t

Response:
def state_counts(gamma, T, out=None):
    """ Sum the probabilities of being in state i to time t

    Parameters
    ----------
    gamma : ndarray((T,N), dtype = float), optional, default = None
        gamma[t,i] is the probabilty at time t to be in state i !
    T : int
        number of time steps

    Returns
    -------
    count : numpy.array shape (N)
            count[i] is the summed probabilty to be in state i !

    See Also
    --------
    state_probabilities : to calculate `gamma`

    """
    return np.sum(gamma[0:T], axis=0, out=out)


Instruction:
Can you tell what is the following Python 3 function doing
def transition_counts(alpha, beta, A, pobs, T=None, out=None):
    if __impl__ == __IMPL_PYTHON__:
        return ip.transition_counts(alpha, beta, A, pobs, T=T, out=out, dtype=config.dtype)
    elif __impl__ == __IMPL_C__:
        return ic.transition_counts(alpha, beta, A, pobs, T=T, out=out, dtype=config.dtype)
    else:
        raise RuntimeError('Nonexisting implementation selected: '+str(__impl__))

Response: Sum for all t the probability to transition from state i to state j.


Instruction:
How would you explain what the following Python 3 function does
def viterbi(A, pobs, pi):
    if __impl__ == __IMPL_PYTHON__:
        return ip.viterbi(A, pobs, pi, dtype=config.dtype)
    elif __impl__ == __IMPL_C__:
        return ic.viterbi(A, pobs, pi, dtype=config.dtype)
    else:
        raise RuntimeError('Nonexisting implementation selected: '+str(__impl__))

Response: Estimate the hidden pathway of maximum likelihood using the Viterbi algorithm.


Instruction:
Can you tell what is the following Python 3 function doing
def sample_path(alpha, A, pobs, T=None):
    if __impl__ == __IMPL_PYTHON__:
        return ip.sample_path(alpha, A, pobs, T=T, dtype=config.dtype)
    elif __impl__ == __IMPL_C__:
        return ic.sample_path(alpha, A, pobs, T=T, dtype=config.dtype)
    else:
        raise RuntimeError('Nonexisting implementation selected: '+str(__impl__))

Response: Sample the hidden pathway S from the conditional distribution P.


Instruction:
Can you tell what is the following Python 3 function doing
def logger(name='BHMM', pattern='%(asctime)s %(levelname)s %(name)s: %(message)s',
           date_format='%H:%M:%S', handler=logging.StreamHandler(sys.stdout)):
    """
    Retrieves the logger instance associated to the given name.

    :param name: The name of the logger instance.
    :type name: str
    :param pattern: The associated pattern.
    :type pattern: str
    :param date_format: The date format to be used in the pattern.
    :type date_format: str
    :param handler: The logging handler, by default console output.
    :type handler: FileHandler or StreamHandler or NullHandler

    :return: The logger.
    :rtype: Logger
    """
    _logger = logging.getLogger(name)
    _logger.setLevel(config.log_level())
    if not _logger.handlers:
        formatter = logging.Formatter(pattern, date_format)
        handler.setFormatter(formatter)
        handler.setLevel(config.log_level())
        _logger.addHandler(handler)
        _logger.propagate = False
    return _logger

Response: Creates a logger instance associated with the given name.


Instruction:
Can you generate the documentation for the following Python 3 function
def sample(self, nsamples, nburn=0, nthin=1, save_hidden_state_trajectory=False,
               call_back=None):
        """Sample from the BHMM posterior.

        Parameters
        ----------
        nsamples : int
            The number of samples to generate.
        nburn : int, optional, default=0
            The number of samples to discard to burn-in, following which `nsamples` will be generated.
        nthin : int, optional, default=1
            The number of Gibbs sampling updates used to generate each returned sample.
        save_hidden_state_trajectory : bool, optional, default=False
            If True, the hidden state trajectory for each sample will be saved as well.
        call_back : function, optional, default=None
            a call back function with no arguments, which if given is being called
            after each computed sample. This is useful for implementing progress bars.

        Returns
        -------
        models : list of bhmm.HMM
            The sampled HMM models from the Bayesian posterior.

        Examples
        --------

        >>> from bhmm import testsystems
        >>> [model, observations, states, sampled_model] = testsystems.generate_random_bhmm(ntrajectories=5, length=1000)
        >>> nburn = 5 # run the sampler a bit before recording samples
        >>> nsamples = 10 # generate 10 samples
        >>> nthin = 2 # discard one sample in between each recorded sample
        >>> samples = sampled_model.sample(nsamples, nburn=nburn, nthin=nthin)

        """

        # Run burn-in.
        for iteration in range(nburn):
            logger().info("Burn-in   %8d / %8d" % (iteration, nburn))
            self._update()

        # Collect data.
        models = list()
        for iteration in range(nsamples):
            logger().info("Iteration %8d / %8d" % (iteration, nsamples))
            # Run a number of Gibbs sampling updates to generate each sample.
            for thin in range(nthin):
                self._update()
            # Save a copy of the current model.
            model_copy = copy.deepcopy(self.model)
            # print "Sampled: \n",repr(model_copy)
            if not save_hidden_state_trajectory:
                model_copy.hidden_state_trajectory = None
            models.append(model_copy)
            if call_back is not None:
                call_back()

        # Return the list of models saved.
        return models

Response: Sample from the BHMM posterior.


Instruction:
Make a summary of the following Python 3 code
def _update(self):
        initial_time = time.time()

        self._updateHiddenStateTrajectories()
        self._updateEmissionProbabilities()
        self._updateTransitionMatrix()

        final_time = time.time()
        elapsed_time = final_time - initial_time
        logger().info("BHMM update iteration took %.3f s" % elapsed_time)

Response: Update the current model using one round of Gibbs sampling.


Instruction:
Implement a function in Python 3 to
update the hidden state trajectories attribute of the current state model.

Response:
def _updateHiddenStateTrajectories(self):
        """Sample a new set of state trajectories from the conditional distribution P(S | T, E, O)

        """
        self.model.hidden_state_trajectories = list()
        for trajectory_index in range(self.nobs):
            hidden_state_trajectory = self._sampleHiddenStateTrajectory(self.observations[trajectory_index])
            self.model.hidden_state_trajectories.append(hidden_state_trajectory)
        return


Instruction:
Can you write a function in Python 3 where it
samples a hidden state trajectory from the conditional distribution P s | T E o.

Response:
def _sampleHiddenStateTrajectory(self, obs, dtype=np.int32):
        """Sample a hidden state trajectory from the conditional distribution P(s | T, E, o)

        Parameters
        ----------
        o_t : numpy.array with dimensions (T,)
            observation[n] is the nth observation
        dtype : numpy.dtype, optional, default=numpy.int32
            The dtype to to use for returned state trajectory.

        Returns
        -------
        s_t : numpy.array with dimensions (T,) of type `dtype`
            Hidden state trajectory, with s_t[t] the hidden state corresponding to observation o_t[t]

        Examples
        --------
        >>> import bhmm
        >>> [model, observations, states, sampled_model] = bhmm.testsystems.generate_random_bhmm(ntrajectories=5, length=1000)
        >>> o_t = observations[0]
        >>> s_t = sampled_model._sampleHiddenStateTrajectory(o_t)

        """

        # Determine observation trajectory length
        T = obs.shape[0]

        # Convenience access.
        A = self.model.transition_matrix
        pi = self.model.initial_distribution

        # compute output probability matrix
        self.model.output_model.p_obs(obs, out=self.pobs)
        # compute forward variables
        logprob = hidden.forward(A, self.pobs, pi, T=T, alpha_out=self.alpha)[0]
        # sample path
        S = hidden.sample_path(self.alpha, A, self.pobs, T=T)

        return S


Instruction:
How would you code a function in Python 3 to
update the emission probabilites of the current state.

Response:
def _updateEmissionProbabilities(self):
        """Sample a new set of emission probabilites from the conditional distribution P(E | S, O)

        """
        observations_by_state = [self.model.collect_observations_in_state(self.observations, state)
                                 for state in range(self.model.nstates)]
        self.model.output_model.sample(observations_by_state)


Instruction:
How would you implement a function in Python 3 that
updates the hidden - state transition matrix and the initial distribution.

Response:
def _updateTransitionMatrix(self):
        """
        Updates the hidden-state transition matrix and the initial distribution

        """
        # TRANSITION MATRIX
        C = self.model.count_matrix() + self.prior_C  # posterior count matrix

        # check if we work with these options
        if self.reversible and not _tmatrix_disconnected.is_connected(C, strong=True):
            raise NotImplementedError('Encountered disconnected count matrix with sampling option reversible:\n '
                                      + str(C) + '\nUse prior to ensure connectivity or use reversible=False.')
        # ensure consistent sparsity pattern (P0 might have additional zeros because of underflows)
        # TODO: these steps work around a bug in msmtools. Should be fixed there
        P0 = msmest.transition_matrix(C, reversible=self.reversible, maxiter=10000, warn_not_converged=False)
        zeros = np.where(P0 + P0.T == 0)
        C[zeros] = 0
        # run sampler
        Tij = msmest.sample_tmatrix(C, nsample=1, nsteps=self.transition_matrix_sampling_steps,
                                    reversible=self.reversible)

        # INITIAL DISTRIBUTION
        if self.stationary:  # p0 is consistent with P
            p0 = _tmatrix_disconnected.stationary_distribution(Tij, C=C)
        else:
            n0 = self.model.count_init().astype(float)
            first_timestep_counts_with_prior = n0 + self.prior_n0
            positive = first_timestep_counts_with_prior > 0
            p0 = np.zeros_like(n0)
            p0[positive] = np.random.dirichlet(first_timestep_counts_with_prior[positive])  # sample p0 from posterior

        # update HMM with new sample
        self.model.update(p0, Tij)


Instruction:
Can you create a Python 3 function that
initializes using an MLHMM and generate a model

Response:
def _generateInitialModel(self, output_model_type):
        """Initialize using an MLHMM.

        """
        logger().info("Generating initial model for BHMM using MLHMM...")
        from bhmm.estimators.maximum_likelihood import MaximumLikelihoodEstimator
        mlhmm = MaximumLikelihoodEstimator(self.observations, self.nstates, reversible=self.reversible,
                                           output=output_model_type)
        model = mlhmm.fit()
        return model


Instruction:
Create a Python 3 function to
compute the connected sets of the given count matrix.

Response:
def connected_sets(C, mincount_connectivity=0, strong=True):
    """ Computes the connected sets of C.

    C : count matrix
    mincount_connectivity : float
        Minimum count which counts as a connection.
    strong : boolean
        True: Seek strongly connected sets. False: Seek weakly connected sets.

    """
    import msmtools.estimation as msmest
    Cconn = C.copy()
    Cconn[np.where(C <= mincount_connectivity)] = 0
    # treat each connected set separately
    S = msmest.connected_sets(Cconn, directed=strong)
    return S


Instruction:
Given the following Python 3 function, write the documentation
def closed_sets(C, mincount_connectivity=0):
    n = np.shape(C)[0]
    S = connected_sets(C, mincount_connectivity=mincount_connectivity, strong=True)
    closed = []
    for s in S:
        mask = np.zeros(n, dtype=bool)
        mask[s] = True
        if C[np.ix_(mask, ~mask)].sum() == 0:  # closed set, take it
            closed.append(s)
    return closed

Response: Computes strongly connected closed sets of a single site.


Instruction:
Can you create a Python 3 function that
returns the set of states that have at least one incoming or outgoing count.

Response:
def nonempty_set(C, mincount_connectivity=0):
    """ Returns the set of states that have at least one incoming or outgoing count """
    # truncate to states with at least one observed incoming or outgoing count.
    if mincount_connectivity > 0:
        C = C.copy()
        C[np.where(C < mincount_connectivity)] = 0
    return np.where(C.sum(axis=0) + C.sum(axis=1) > 0)[0]


Instruction:
How would you code a function in Python 3 to
estimate full transition matrix for general connectivity structure.

Response:
def estimate_P(C, reversible=True, fixed_statdist=None, maxiter=1000000, maxerr=1e-8, mincount_connectivity=0):
    """ Estimates full transition matrix for general connectivity structure

    Parameters
    ----------
    C : ndarray
        count matrix
    reversible : bool
        estimate reversible?
    fixed_statdist : ndarray or None
        estimate with given stationary distribution
    maxiter : int
        Maximum number of reversible iterations.
    maxerr : float
        Stopping criterion for reversible iteration: Will stop when infinity
        norm  of difference vector of two subsequent equilibrium distributions
        is below maxerr.
    mincount_connectivity : float
        Minimum count which counts as a connection.

    """
    import msmtools.estimation as msmest
    n = np.shape(C)[0]
    # output matrix. Set initially to Identity matrix in order to handle empty states
    P = np.eye(n, dtype=np.float64)
    # decide if we need to proceed by weakly or strongly connected sets
    if reversible and fixed_statdist is None:  # reversible to unknown eq. dist. - use strongly connected sets.
        S = connected_sets(C, mincount_connectivity=mincount_connectivity, strong=True)
        for s in S:
            mask = np.zeros(n, dtype=bool)
            mask[s] = True
            if C[np.ix_(mask, ~mask)].sum() > np.finfo(C.dtype).eps:  # outgoing transitions - use partial rev algo.
                transition_matrix_partial_rev(C, P, mask, maxiter=maxiter, maxerr=maxerr)
            else:  # closed set - use standard estimator
                I = np.ix_(mask, mask)
                if s.size > 1:  # leave diagonal 1 if single closed state.
                    P[I] = msmest.transition_matrix(C[I], reversible=True, warn_not_converged=False,
                                                    maxiter=maxiter, maxerr=maxerr)
    else:  # nonreversible or given equilibrium distribution - weakly connected sets
        S = connected_sets(C, mincount_connectivity=mincount_connectivity, strong=False)
        for s in S:
            I = np.ix_(s, s)
            if not reversible:
                Csub = C[I]
                # any zero rows? must set Cii = 1 to avoid dividing by zero
                zero_rows = np.where(Csub.sum(axis=1) == 0)[0]
                Csub[zero_rows, zero_rows] = 1.0
                P[I] = msmest.transition_matrix(Csub, reversible=False)
            elif reversible and fixed_statdist is not None:
                P[I] = msmest.transition_matrix(C[I], reversible=True, fixed_statdist=fixed_statdist,
                                                maxiter=maxiter, maxerr=maxerr)
            else:  # unknown case
                raise NotImplementedError('Transition estimation for the case reversible=' + str(reversible) +
                                          ' fixed_statdist=' + str(fixed_statdist is not None) + ' not implemented.')
    # done
    return P


Instruction:
Explain what the following Python 3 code does
def transition_matrix_partial_rev(C, P, S, maxiter=1000000, maxerr=1e-8):
    # test input
    assert np.array_equal(C.shape, P.shape)
    # constants
    A = C[S][:, S]
    B = C[S][:, ~S]
    ATA = A + A.T
    countsums = C[S].sum(axis=1)
    # initialize
    X = 0.5 * ATA
    Y = C[S][:, ~S]
    # normalize X, Y
    totalsum = X.sum() + Y.sum()
    X /= totalsum
    Y /= totalsum
    # rowsums
    rowsums = X.sum(axis=1) + Y.sum(axis=1)
    err = 1.0
    it = 0
    while err > maxerr and it < maxiter:
        # update
        d = countsums / rowsums
        X = ATA / (d[:, None] + d)
        Y = B / d[:, None]
        # normalize X, Y
        totalsum = X.sum() + Y.sum()
        X /= totalsum
        Y /= totalsum
        # update sums
        rowsums_new = X.sum(axis=1) + Y.sum(axis=1)
        # compute error
        err = np.max(np.abs(rowsums_new - rowsums))
        # update
        rowsums = rowsums_new
        it += 1
    # write to P
    P[np.ix_(S, S)] = X
    P[np.ix_(S, ~S)] = Y
    P[S] /= P[S].sum(axis=1)[:, None]

Response: This function computes the partial reversible transition matrix.


Instruction:
Explain what the following Python 3 code does
def enforce_reversible_on_closed(P):
    import msmtools.analysis as msmana
    n = np.shape(P)[0]
    Prev = P.copy()
    # treat each weakly connected set separately
    sets = closed_sets(P)
    for s in sets:
        I = np.ix_(s, s)
        # compute stationary probability
        pi_s = msmana.stationary_distribution(P[I])
        # symmetrize
        X_s = pi_s[:, None] * P[I]
        X_s = 0.5 * (X_s + X_s.T)
        # normalize
        Prev[I] = X_s / X_s.sum(axis=1)[:, None]
    return Prev

Response: Enforces transition matrix P to be reversible on its closed sets.


Instruction:
Write a Python 3 function for
returning if P is reversible on its weakly connected sets.

Response:
def is_reversible(P):
    """ Returns if P is reversible on its weakly connected sets """
    import msmtools.analysis as msmana
    # treat each weakly connected set separately
    sets = connected_sets(P, strong=False)
    for s in sets:
        Ps = P[s, :][:, s]
        if not msmana.is_transition_matrix(Ps):
            return False  # isn't even a transition matrix!
        pi = msmana.stationary_distribution(Ps)
        X = pi[:, None] * Ps
        if not np.allclose(X, X.T):
            return False
    # survived.
    return True


Instruction:
Can you generate the documentation for the following Python 3 function
def _guess_output_type(observations):
    from bhmm.util import types as _types

    o1 = _np.array(observations[0])

    # CASE: vector of int? Then we want a discrete HMM
    if _types.is_int_vector(o1):
        return 'discrete'

    # CASE: not int type, but everything is an integral number. Then we also go for discrete
    if _np.allclose(o1, _np.round(o1)):
        isintegral = True
        for i in range(1, len(observations)):
            if not _np.allclose(observations[i], _np.round(observations[i])):
                isintegral = False
                break
        if isintegral:
            return 'discrete'

    # CASE: vector of double? Then we want a gaussian
    if _types.is_float_vector(o1):
        return 'gaussian'

    # None of the above? Then we currently do not support this format!
    raise TypeError('Observations is neither sequences of integers nor 1D-sequences of floats. The current version'
                    'does not support your input.')

Response: Suggests a HMM model type based on the observation data.


Instruction:
How would you explain what the following Python 3 function does
def lag_observations(observations, lag, stride=1):
    obsnew = []
    for obs in observations:
        for shift in range(0, lag, stride):
            obs_lagged = (obs[shift:][::lag])
            if len(obs_lagged) > 1:
                obsnew.append(obs_lagged)
    return obsnew

Response: r Returns a list of observations that are subsampled at lag but shifted by 1.


Instruction:
Write a Python 3 script to
initialize a 1D - Gaussian HMM with the given initial distribution pi P and means and sigmas. Returns a 1D - Gaussian HMM containing the current state of the current state.

Response:
def gaussian_hmm(pi, P, means, sigmas):
    """ Initializes a 1D-Gaussian HMM

    Parameters
    ----------
    pi : ndarray(nstates, )
        Initial distribution.
    P : ndarray(nstates,nstates)
        Hidden transition matrix
    means : ndarray(nstates, )
        Means of Gaussian output distributions
    sigmas : ndarray(nstates, )
        Standard deviations of Gaussian output distributions
    stationary : bool, optional, default=True
        If True: initial distribution is equal to stationary distribution of transition matrix
    reversible : bool, optional, default=True
        If True: transition matrix will fulfill detailed balance constraints.

    """
    from bhmm.hmm.gaussian_hmm import GaussianHMM
    from bhmm.output_models.gaussian import GaussianOutputModel
    # count states
    nstates = _np.array(P).shape[0]
    # initialize output model
    output_model = GaussianOutputModel(nstates, means, sigmas)
    # initialize general HMM
    from bhmm.hmm.generic_hmm import HMM as _HMM
    ghmm = _HMM(pi, P, output_model)
    # turn it into a Gaussian HMM
    ghmm = GaussianHMM(ghmm)
    return ghmm


Instruction:
Here you have a function in Python 3, explain what it does
def discrete_hmm(pi, P, pout):
    from bhmm.hmm.discrete_hmm import DiscreteHMM
    from bhmm.output_models.discrete import DiscreteOutputModel
    # initialize output model
    output_model = DiscreteOutputModel(pout)
    # initialize general HMM
    from bhmm.hmm.generic_hmm import HMM as _HMM
    dhmm = _HMM(pi, P, output_model)
    # turn it into a Gaussian HMM
    dhmm = DiscreteHMM(dhmm)
    return dhmm

Response: Initializes a discrete HMM with the given initial distribution P and pout.


Instruction:
Here you have a function in Python 3, explain what it does
def init_hmm(observations, nstates, lag=1, output=None, reversible=True):
    # select output model type
    if output is None:
        output = _guess_output_type(observations)

    if output == 'discrete':
        return init_discrete_hmm(observations, nstates, lag=lag, reversible=reversible)
    elif output == 'gaussian':
        return init_gaussian_hmm(observations, nstates, lag=lag, reversible=reversible)
    else:
        raise NotImplementedError('output model type '+str(output)+' not yet implemented.')

Response: Use a heuristic scheme to generate an initial model for a set of states.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def init_gaussian_hmm(observations, nstates, lag=1, reversible=True):
    from bhmm.init import gaussian
    if lag > 1:
        observations = lag_observations(observations, lag)
    hmm0 = gaussian.init_model_gaussian1d(observations, nstates, reversible=reversible)
    hmm0._lag = lag
    return hmm0

Response: Generate a new initial model for a gaussian model.


Instruction:
Given the following Python 3 function, write the documentation
def init_discrete_hmm(observations, nstates, lag=1, reversible=True, stationary=True, regularize=True,
                      method='connect-spectral', separate=None):
    """Use a heuristic scheme to generate an initial model.

    Parameters
    ----------
    observations : list of ndarray((T_i))
        list of arrays of length T_i with observation data
    nstates : int
        The number of states.
    lag : int
        Lag time at which the observations should be counted.
    reversible : bool
        Estimate reversible HMM transition matrix.
    stationary : bool
        p0 is the stationary distribution of P. Currently only reversible=True is implemented
    regularize : bool
        Regularize HMM probabilities to avoid 0's.
    method : str
        * 'lcs-spectral' : Does spectral clustering on the largest connected set
            of observed states.
        * 'connect-spectral' : Uses a weak regularization to connect the weakly
            connected sets and then initializes HMM using spectral clustering on
            the nonempty set.
        * 'spectral' : Uses spectral clustering on the nonempty subsets. Separated
            observed states will end up in separate hidden states. This option is
            only recommended for small observation spaces. Use connect-spectral for
            large observation spaces.
    separate : None or iterable of int
        Force the given set of observed states to stay in a separate hidden state.
        The remaining nstates-1 states will be assigned by a metastable decomposition.

    Examples
    --------

    Generate initial model for a discrete output model.

    >>> import bhmm
    >>> [model, observations, states] = bhmm.testsystems.generate_synthetic_observations(output='discrete')
    >>> initial_model = init_discrete_hmm(observations, model.nstates)

    """
    import msmtools.estimation as msmest
    from bhmm.init.discrete import init_discrete_hmm_spectral
    C = msmest.count_matrix(observations, lag).toarray()
    # regularization
    if regularize:
        eps_A = None
        eps_B = None
    else:
        eps_A = 0
        eps_B = 0
    if not stationary:
        raise NotImplementedError('Discrete-HMM initialization with stationary=False is not yet implemented.')

    if method=='lcs-spectral':
        lcs = msmest.largest_connected_set(C)
        p0, P, B = init_discrete_hmm_spectral(C, nstates, reversible=reversible, stationary=stationary,
                                              active_set=lcs, separate=separate, eps_A=eps_A, eps_B=eps_B)
    elif method=='connect-spectral':
        # make sure we're strongly connected
        C += msmest.prior_neighbor(C, 0.001)
        nonempty = _np.where(C.sum(axis=0) + C.sum(axis=1) > 0)[0]
        C[nonempty, nonempty] = _np.maximum(C[nonempty, nonempty], 0.001)
        p0, P, B = init_discrete_hmm_spectral(C, nstates, reversible=reversible, stationary=stationary,
                                              active_set=nonempty, separate=separate, eps_A=eps_A, eps_B=eps_B)
    elif method=='spectral':
        p0, P, B = init_discrete_hmm_spectral(C, nstates, reversible=reversible, stationary=stationary,
                                              active_set=None, separate=separate, eps_A=eps_A, eps_B=eps_B)
    else:
        raise NotImplementedError('Unknown discrete-HMM initialization method ' + str(method))

    hmm0 = discrete_hmm(p0, P, B)
    hmm0._lag = lag
    return hmm0

Response: Generate a discrete HMM for a given set of observations.


Instruction:
How would you explain what the following Python 3 function does
def estimate_hmm(observations, nstates, lag=1, initial_model=None, output=None,
                 reversible=True, stationary=False, p=None, accuracy=1e-3, maxit=1000, maxit_P=100000,
                 mincount_connectivity=1e-2):
    r""" Estimate maximum-likelihood HMM

    Generic maximum-likelihood estimation of HMMs

    Parameters
    ----------
    observations : list of numpy arrays representing temporal data
        `observations[i]` is a 1d numpy array corresponding to the observed trajectory index `i`
    nstates : int
        The number of states in the model.
    lag : int
        the lag time at which observations should be read
    initial_model : HMM, optional, default=None
        If specified, the given initial model will be used to initialize the BHMM.
        Otherwise, a heuristic scheme is used to generate an initial guess.
    output : str, optional, default=None
        Output model type from [None, 'gaussian', 'discrete']. If None, will automatically select an output
        model type based on the format of observations.
    reversible : bool, optional, default=True
        If True, a prior that enforces reversible transition matrices (detailed balance) is used;
        otherwise, a standard  non-reversible prior is used.
    stationary : bool, optional, default=False
        If True, the initial distribution of hidden states is self-consistently computed as the stationary
        distribution of the transition matrix. If False, it will be estimated from the starting states.
        Only set this to true if you're sure that the observation trajectories are initiated from a global
        equilibrium distribution.
    p : ndarray (nstates), optional, default=None
        Initial or fixed stationary distribution. If given and stationary=True, transition matrices will be
        estimated with the constraint that they have p as their stationary distribution. If given and
        stationary=False, p is the fixed initial distribution of hidden states.
    accuracy : float
        convergence threshold for EM iteration. When two the likelihood does not increase by more than accuracy, the
        iteration is stopped successfully.
    maxit : int
        stopping criterion for EM iteration. When so many iterations are performed without reaching the requested
        accuracy, the iteration is stopped without convergence (a warning is given)

    Return
    ------
    hmm : :class:`HMM <bhmm.hmm.generic_hmm.HMM>`

    """
    # select output model type
    if output is None:
        output = _guess_output_type(observations)

    if lag > 1:
        observations = lag_observations(observations, lag)

    # construct estimator
    from bhmm.estimators.maximum_likelihood import MaximumLikelihoodEstimator as _MaximumLikelihoodEstimator
    est = _MaximumLikelihoodEstimator(observations, nstates, initial_model=initial_model, output=output,
                                      reversible=reversible, stationary=stationary, p=p, accuracy=accuracy,
                                      maxit=maxit, maxit_P=maxit_P)
    # run
    est.fit()
    # set lag time
    est.hmm._lag = lag
    # return model
    # TODO: package into specific class (DiscreteHMM, GaussianHMM)
    return est.hmm

Response: r Estimates the maximum - likelihood of a given set of observations.


Instruction:
Make a summary of the following Python 3 code
def bayesian_hmm(observations, estimated_hmm, nsample=100, reversible=True, stationary=False,
                 p0_prior='mixed', transition_matrix_prior='mixed', store_hidden=False, call_back=None):
    r""" Bayesian HMM based on sampling the posterior

    Generic maximum-likelihood estimation of HMMs

    Parameters
    ----------
    observations : list of numpy arrays representing temporal data
        `observations[i]` is a 1d numpy array corresponding to the observed trajectory index `i`
    estimated_hmm : HMM
        HMM estimated from estimate_hmm or initialize_hmm
    reversible : bool, optional, default=True
        If True, a prior that enforces reversible transition matrices (detailed balance) is used;
        otherwise, a standard  non-reversible prior is used.
    stationary : bool, optional, default=False
        If True, the stationary distribution of the transition matrix will be used as initial distribution.
        Only use True if you are confident that the observation trajectories are started from a global
        equilibrium. If False, the initial distribution will be estimated as usual from the first step
        of the hidden trajectories.
    nsample : int, optional, default=100
        number of Gibbs sampling steps
    p0_prior : None, str, float or ndarray(n)
        Prior for the initial distribution of the HMM. Will only be active
        if stationary=False (stationary=True means that p0 is identical to
        the stationary distribution of the transition matrix).
        Currently implements different versions of the Dirichlet prior that
        is conjugate to the Dirichlet distribution of p0. p0 is sampled from:
        .. math:
            p0 \sim \prod_i (p0)_i^{a_i + n_i - 1}
        where :math:`n_i` are the number of times a hidden trajectory was in
        state :math:`i` at time step 0 and :math:`a_i` is the prior count.
        Following options are available:
        |  'mixed' (default),  :math:`a_i = p_{0,init}`, where :math:`p_{0,init}`
            is the initial distribution of initial_model.
        |  'uniform',  :math:`a_i = 1`
        |  ndarray(n) or float,
            the given array will be used as A.
        |  None,  :math:`a_i = 0`. This option ensures coincidence between
            sample mean an MLE. Will sooner or later lead to sampling problems,
            because as soon as zero trajectories are drawn from a given state,
            the sampler cannot recover and that state will never serve as a starting
            state subsequently. Only recommended in the large data regime and
            when the probability to sample zero trajectories from any state
            is negligible.
    transition_matrix_prior : str or ndarray(n, n)
        Prior for the HMM transition matrix.
        Currently implements Dirichlet priors if reversible=False and reversible
        transition matrix priors as described in [1]_ if reversible=True. For the
        nonreversible case the posterior of transition matrix :math:`P` is:
        .. math:
            P \sim \prod_{i,j} p_{ij}^{b_{ij} + c_{ij} - 1}
        where :math:`c_{ij}` are the number of transitions found for hidden
        trajectories and :math:`b_{ij}` are prior counts.
        |  'mixed' (default),  :math:`b_{ij} = p_{ij,init}`, where :math:`p_{ij,init}`
            is the transition matrix of initial_model. That means one prior
            count will be used per row.
        |  'uniform',  :math:`b_{ij} = 1`
        |  ndarray(n, n) or broadcastable,
            the given array will be used as B.
        |  None,  :math:`b_ij = 0`. This option ensures coincidence between
            sample mean an MLE. Will sooner or later lead to sampling problems,
            because as soon as a transition :math:`ij` will not occur in a
            sample, the sampler cannot recover and that transition will never
            be sampled again. This option is not recommended unless you have
            a small HMM and a lot of data.
    store_hidden : bool, optional, default=False
        store hidden trajectories in sampled HMMs
    call_back : function, optional, default=None
        a call back function with no arguments, which if given is being called
        after each computed sample. This is useful for implementing progress bars.

    Return
    ------
    hmm : :class:`SampledHMM <bhmm.hmm.generic_sampled_hmm.SampledHMM>`

    References
    ----------
    .. [1] Trendelkamp-Schroer, B., H. Wu, F. Paul and F. Noe:
        Estimation and uncertainty of reversible Markov models.
        J. Chem. Phys. 143, 174101 (2015).

    """
    # construct estimator
    from bhmm.estimators.bayesian_sampling import BayesianHMMSampler as _BHMM
    sampler = _BHMM(observations, estimated_hmm.nstates, initial_model=estimated_hmm,
                    reversible=reversible, stationary=stationary, transition_matrix_sampling_steps=1000,
                    p0_prior=p0_prior, transition_matrix_prior=transition_matrix_prior,
                    output=estimated_hmm.output_model.model_type)

    # Sample models.
    sampled_hmms = sampler.sample(nsamples=nsample, save_hidden_state_trajectory=store_hidden,
                                  call_back=call_back)
    # return model
    from bhmm.hmm.generic_sampled_hmm import SampledHMM
    return SampledHMM(estimated_hmm, sampled_hmms)

Response: r Bayesian HMM based on sampling the observed data.


Instruction:
Write a Python 3 script to
compute the sum of arr assuming arr is in the log domain.

Response:
def logsumexp(arr, axis=0):
    """Computes the sum of arr assuming arr is in the log domain.

    Returns log(sum(exp(arr))) while minimizing the possibility of
    over/underflow.

    Examples
    --------

    >>> import numpy as np
    >>> from sklearn.utils.extmath import logsumexp
    >>> a = np.arange(10)
    >>> np.log(np.sum(np.exp(a)))
    9.4586297444267107
    >>> logsumexp(a)
    9.4586297444267107
    """
    arr = np.rollaxis(arr, axis)
    # Use the max to normalize, as with the log this is what accumulates
    # the less errors
    vmax = arr.max(axis=0)
    out = np.log(np.sum(np.exp(arr - vmax), axis=0))
    out += vmax
    return out


Instruction:
Can you generate the documentation for the following Python 3 function
def _ensure_sparse_format(spmatrix, accept_sparse, dtype, order, copy,
                          force_all_finite):
    """Convert a sparse matrix to a given format.

    Checks the sparse format of spmatrix and converts if necessary.

    Parameters
    ----------
    spmatrix : scipy sparse matrix
        Input to validate and convert.

    accept_sparse : string, list of string or None (default=None)
        String[s] representing allowed sparse matrix formats ('csc',
        'csr', 'coo', 'dok', 'bsr', 'lil', 'dia'). None means that sparse
        matrix input will raise an error.  If the input is sparse but not in
        the allowed format, it will be converted to the first listed format.

    dtype : string, type or None (default=none)
        Data type of result. If None, the dtype of the input is preserved.

    order : 'F', 'C' or None (default=None)
        Whether an array will be forced to be fortran or c-style.

    copy : boolean (default=False)
        Whether a forced copy will be triggered. If copy=False, a copy might
        be triggered by a conversion.

    force_all_finite : boolean (default=True)
        Whether to raise an error on np.inf and np.nan in X.

    Returns
    -------
    spmatrix_converted : scipy sparse matrix.
        Matrix that is ensured to have an allowed type.
    """
    if accept_sparse is None:
        raise TypeError('A sparse matrix was passed, but dense '
                        'data is required. Use X.toarray() to '
                        'convert to a dense numpy array.')
    sparse_type = spmatrix.format
    if dtype is None:
        dtype = spmatrix.dtype
    if sparse_type in accept_sparse:
        # correct type
        if dtype == spmatrix.dtype:
            # correct dtype
            if copy:
                spmatrix = spmatrix.copy()
        else:
            # convert dtype
            spmatrix = spmatrix.astype(dtype)
    else:
        # create new
        spmatrix = spmatrix.asformat(accept_sparse[0]).astype(dtype)
    if force_all_finite:
        if not hasattr(spmatrix, "data"):
            warnings.warn("Can't check %s sparse matrix for nan or inf."
                          % spmatrix.format)
        else:
            _assert_all_finite(spmatrix.data)
    if hasattr(spmatrix, "data"):
        spmatrix.data = np.array(spmatrix.data, copy=False, order=order)
    return spmatrix

Response: Convert a sparse matrix to a given format.


Instruction:
Can you tell what is the following Python 3 function doing
def check_array(array, accept_sparse=None, dtype="numeric", order=None,
                copy=False, force_all_finite=True, ensure_2d=True,
                allow_nd=False, ensure_min_samples=1, ensure_min_features=1):
    """Input validation on an array, list, sparse matrix or similar.

    By default, the input is converted to an at least 2nd numpy array.
    If the dtype of the array is object, attempt converting to float,
    raising on failure.

    Parameters
    ----------
    array : object
        Input object to check / convert.

    accept_sparse : string, list of string or None (default=None)
        String[s] representing allowed sparse matrix formats, such as 'csc',
        'csr', etc.  None means that sparse matrix input will raise an error.
        If the input is sparse but not in the allowed format, it will be
        converted to the first listed format.

    dtype : string, type or None (default="numeric")
        Data type of result. If None, the dtype of the input is preserved.
        If "numeric", dtype is preserved unless array.dtype is object.

    order : 'F', 'C' or None (default=None)
        Whether an array will be forced to be fortran or c-style.

    copy : boolean (default=False)
        Whether a forced copy will be triggered. If copy=False, a copy might
        be triggered by a conversion.

    force_all_finite : boolean (default=True)
        Whether to raise an error on np.inf and np.nan in X.

    ensure_2d : boolean (default=True)
        Whether to make X at least 2d.

    allow_nd : boolean (default=False)
        Whether to allow X.ndim > 2.

    ensure_min_samples : int (default=1)
        Make sure that the array has a minimum number of samples in its first
        axis (rows for a 2D array). Setting to 0 disables this check.

    ensure_min_features : int (default=1)
        Make sure that the 2D array has some minimum number of features
        (columns). The default value of 1 rejects empty datasets.
        This check is only enforced when the input data has effectively 2
        dimensions or is originally 1D and ``ensure_2d`` is True. Setting to 0
        disables this check.

    Returns
    -------
    X_converted : object
        The converted and validated X.
    """
    if isinstance(accept_sparse, str):
        accept_sparse = [accept_sparse]

    # store whether originally we wanted numeric dtype
    dtype_numeric = dtype == "numeric"

    if sp.issparse(array):
        if dtype_numeric:
            dtype = None
        array = _ensure_sparse_format(array, accept_sparse, dtype, order,
                                      copy, force_all_finite)
    else:
        if ensure_2d:
            array = np.atleast_2d(array)
        if dtype_numeric:
            if hasattr(array, "dtype") and getattr(array.dtype, "kind", None) == "O":
                # if input is object, convert to float.
                dtype = np.float64
            else:
                dtype = None
        array = np.array(array, dtype=dtype, order=order, copy=copy)
        # make sure we actually converted to numeric:
        if dtype_numeric and array.dtype.kind == "O":
            array = array.astype(np.float64)
        if not allow_nd and array.ndim >= 3:
            raise ValueError("Found array with dim %d. Expected <= 2" %
                             array.ndim)
        if force_all_finite:
            _assert_all_finite(array)

    shape_repr = _shape_repr(array.shape)
    if ensure_min_samples > 0:
        n_samples = _num_samples(array)
        if n_samples < ensure_min_samples:
            raise ValueError("Found array with %d sample(s) (shape=%s) while a"
                             " minimum of %d is required."
                             % (n_samples, shape_repr, ensure_min_samples))

    if ensure_min_features > 0 and array.ndim == 2:
        n_features = array.shape[1]
        if n_features < ensure_min_features:
            raise ValueError("Found array with %d feature(s) (shape=%s) while"
                             " a minimum of %d is required."
                             % (n_features, shape_repr, ensure_min_features))
    return array

Response: Input validation on an array.


Instruction:
Here you have a function in Python 3, explain what it does
def beta_confidence_intervals(ci_X, ntrials, ci=0.95):
    # Compute low and high confidence interval for symmetric CI about mean.
    ci_low = 0.5 - ci/2;
    ci_high = 0.5 + ci/2;

    # Compute for every element of ci_X.
    from scipy.stats import beta
    Plow = ci_X * 0.0;
    Phigh = ci_X * 0.0;
    for i in range(ci_X.shape[0]):
        for j in range(ci_X.shape[1]):
            Plow[i,j] = beta.ppf(ci_low, a = ci_X[i,j] * ntrials, b = (1-ci_X[i,j]) * ntrials);
            Phigh[i,j] = beta.ppf(ci_high, a = ci_X[i,j] * ntrials, b = (1-ci_X[i,j]) * ntrials);

    return [Plow, Phigh]

Response: Returns a random set of confidence intervals for beta distributions.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def empirical_confidence_interval(sample, interval=0.95):
    # Sort sample in increasing order.
    sample = np.sort(sample)

    # Determine sample size.
    N = len(sample)

    # Compute low and high indices.
    low_index = int(np.round((N-1) * (0.5 - interval/2))) + 1
    high_index = int(np.round((N-1) * (0.5 + interval/2))) + 1

    # Compute low and high.
    low = sample[low_index]
    high = sample[high_index]

    return [low, high]

Response: Compute specified symmetric confidence interval for empirical sample.


Instruction:
Can you tell what is the following Python 3 function doing
def generate_latex_table(sampled_hmm, conf=0.95, dt=1, time_unit='ms', obs_name='force', obs_units='pN',
                         caption='', outfile=None):
    """
    Generate a LaTeX column-wide table showing various computed properties and uncertainties.

    Parameters
    ----------
    conf : float
        confidence interval. Use 0.68 for 1 sigma, 0.95 for 2 sigma etc.

    """
    # check input
    from bhmm.hmm.generic_sampled_hmm import SampledHMM
    from bhmm.hmm.gaussian_hmm import SampledGaussianHMM
    assert issubclass(sampled_hmm.__class__, SampledHMM), 'sampled_hmm ist not a SampledHMM'

    # confidence interval
    sampled_hmm.set_confidence(conf)
    # dt
    dt = float(dt)
    # nstates
    nstates = sampled_hmm.nstates

    table = """
\\begin{table}
    \\begin{tabular*}{\columnwidth}{@{\extracolsep{\\fill}}lcc}
        \hline
        {\\bf Property} & {\\bf Symbol} & {\\bf Value} \\\\
        \hline
            """
    # Stationary probability.
    p = sampled_hmm.stationary_distribution_mean
    p_lo, p_hi = sampled_hmm.stationary_distribution_conf
    for i in range(nstates):
        if i == 0:
            table += '\t\tEquilibrium probability '
        table += '\t\t& $\pi_{%d}$ & $%0.3f_{\:%0.3f}^{\:%0.3f}$ \\\\' % (i+1, p[i], p_lo[i], p_hi[i]) + '\n'
    table += '\t\t\hline' + '\n'

    # Transition probabilities.
    P = sampled_hmm.transition_matrix_mean
    P_lo, P_hi = sampled_hmm.transition_matrix_conf
    for i in range(nstates):
        for j in range(nstates):
            if i == 0 and j == 0:
                table += '\t\tTransition probability ($\Delta t = $%s) ' % (str(dt)+' '+time_unit)
            table += '\t\t& $T_{%d%d}$ & $%0.4f_{\:%0.4f}^{\:%0.4f}$ \\\\' % (i+1, j+1, P[i, j], P_lo[i, j], P_hi[i, j]) + '\n'
    table += '\t\t\hline' + '\n'
    table += '\t\t\hline' + '\n'

    # Transition rates via pseudogenerator.
    K = P - np.eye(sampled_hmm.nstates)
    K /= dt
    K_lo = P_lo - np.eye(sampled_hmm.nstates)
    K_lo /= dt
    K_hi = P_hi - np.eye(sampled_hmm.nstates)
    K_hi /= dt
    for i in range(nstates):
        for j in range(nstates):
            if i == 0 and j == 0:
                table += '\t\tTransition rate (%s$^{-1}$) ' % time_unit
            if i != j:
                table += '\t\t& $k_{%d%d}$ & $%2.4f_{\:%2.4f}^{\:%2.4f}$ \\\\' % (i+1, j+1, K[i, j], K_lo[i, j], K_hi[i, j]) + '\n'
    table += '\t\t\hline' + '\n'

    # State mean lifetimes.
    l = sampled_hmm.lifetimes_mean
    l *= dt
    l_lo, l_hi = sampled_hmm.lifetimes_conf
    l_lo *= dt
    l_hi *= dt
    for i in range(nstates):
        if i == 0:
            table += '\t\tState mean lifetime (%s) ' % time_unit
        table += '\t\t& $t_{%d}$ & $%.3f_{\:%.3f}^{\:%.3f}$ \\\\' % (i+1, l[i], l_lo[i], l_hi[i]) + '\n'
    table += '\t\t\hline' + '\n'

    # State relaxation timescales.
    t = sampled_hmm.timescales_mean
    t *= dt
    t_lo, t_hi = sampled_hmm.timescales_conf
    t_lo *= dt
    t_hi *= dt
    for i in range(nstates-1):
        if i == 0:
            table += '\t\tRelaxation time (%s) ' % time_unit
        table += '\t\t& $\\tau_{%d}$ & $%.3f_{\:%.3f}^{\:%.3f}$ \\\\' % (i+1, t[i], t_lo[i], t_hi[i]) + '\n'
    table += '\t\t\hline' + '\n'

    if issubclass(sampled_hmm.__class__, SampledGaussianHMM):
        table += '\t\t\hline' + '\n'

        # State mean forces.
        m = sampled_hmm.means_mean
        m_lo, m_hi = sampled_hmm.means_conf
        for i in range(nstates):
            if i == 0:
                table += '\t\tState %s mean (%s) ' % (obs_name, obs_units)
            table += '\t\t& $\mu_{%d}$ & $%.3f_{\:%.3f}^{\:%.3f}$ \\\\' % (i+1, m[i], m_lo[i], m_hi[i]) + '\n'
        table += '\t\t\hline' + '\n'

        # State force standard deviations.
        s = sampled_hmm.sigmas_mean
        s_lo, s_hi = sampled_hmm.sigmas_conf
        for i in range(nstates):
            if i == 0:
                table += '\t\tState %s std dev (%s) ' % (obs_name, obs_units)
            table += '\t\t& $s_{%d}$ & $%.3f_{\:%.3f}^{\:%.3f}$ \\\\' % (i+1, s[i], s_lo[i], s_hi[i]) + '\n'
        table += '\t\t\hline' + '\n'

    table += """
        \\hline
    \\end{tabular*}
    \\caption{{\\bf %s}}
\\end{table}
            """ % caption

    # write to file if wanted:
    if outfile is not None:
        f = open(outfile, 'w')
        f.write(table)
        f.close()

    return table

Response: Generates LaTeX table for the given SampledHMM.


Instruction:
Can you create a Python 3 function that
computes the mean and alpha - confidence interval of the given sample set.

Response:
def confidence_interval(data, alpha):
    """
    Computes the mean and alpha-confidence interval of the given sample set

    Parameters
    ----------
    data : ndarray
        a 1D-array of samples
    alpha : float in [0,1]
        the confidence level, i.e. percentage of data included in the interval

    Returns
    -------
    [m,l,r] where m is the mean of the data, and (l,r) are the m-alpha/2 and m+alpha/2
    confidence interval boundaries.
    """
    if alpha < 0 or alpha > 1:
        raise ValueError('Not a meaningful confidence level: '+str(alpha))

    # compute mean
    m = np.mean(data)
    # sort data
    sdata = np.sort(data)
    # index of the mean
    im = np.searchsorted(sdata, m)
    if im == 0 or im == len(sdata):
        pm = im
    else:
        pm = (im-1) + (m-sdata[im-1]) / (sdata[im]-sdata[im-1])
    # left interval boundary
    pl = pm - alpha * pm
    il1 = max(0, int(math.floor(pl)))
    il2 = min(len(sdata)-1, int(math.ceil(pl)))
    l = sdata[il1] + (pl - il1)*(sdata[il2] - sdata[il1])
    # right interval boundary
    pr = pm + alpha * (len(data)-im)
    ir1 = max(0, int(math.floor(pr)))
    ir2 = min(len(sdata)-1, int(math.ceil(pr)))
    r = sdata[ir1] + (pr - ir1)*(sdata[ir2] - sdata[ir1])

    # return
    return m, l, r


Instruction:
Write a Python 3 script to
return the connection status both locally and remotely.

Response:
def status(self, remote=False):
        """
        Return the connection status, both locally and remotely.

        The local connection status is a dictionary that gives:
        * the count of multiple queries sent to the server.
        * the count of single queries sent to the server.
        * the count of actions sent to the server.
        * the count of actions executed successfully by the server.
        * the count of actions queued to go to the server.

        The remote connection status includes whether the server is live,
        as well as data about version and build.  The server data is
        cached, unless the remote flag is specified.

        :param remote: whether to query the server for its latest status
        :return: tuple of status dicts: (local, server).
        """
        if remote:
            components = urlparse.urlparse(self.endpoint)
            try:
                result = self.session.get(components[0] + "://" + components[1] + "/status", timeout=self.timeout)
            except Exception as e:
                if self.logger: self.logger.debug("Failed to connect to server for status: %s", e)
                result = None
            if result and result.status_code == 200:
                self.server_status = result.json()
                self.server_status["endpoint"] = self.endpoint
            elif result:
                if self.logger: self.logger.debug("Server status response not understandable: Status: %d, Body: %s",
                                                  result.status_code, result.text)
                self.server_status = {"endpoint": self.endpoint,
                                      "status": ("Unexpected HTTP status " + str(result.status_code) + " at: " +
                                                 strftime("%d %b %Y %H:%M:%S +0000", gmtime()))}
            else:
                self.server_status = {"endpoint": self.endpoint,
                                      "status": "Unreachable at: " + strftime("%d %b %Y %H:%M:%S +0000", gmtime())}
        return self.local_status, self.server_status