def computeOverlap(self):
        """
        Compute estimate of overlap matrix between the states.

        Returns
        -------
        result_vals : dictonary

        Possible keys in the result_vals dictionary:

        'scalar' : np.ndarray, float, shape=(K, K)
            One minus the largest nontrival eigenvalue (largest is 1 or -1)
        'eigenvalues' : np.ndarray, float, shape=(K)
            The sorted (descending) eigenvalues of the overlap matrix.
        'O' : np.ndarray, float, shape=(K, K)
            Estimated state overlap matrix: O[i,j] is an estimate
            of the probability of observing a sample from state i in state j

        Notes
        -----

        .. code-block:: none

            W.T * W \approx \int (p_i p_j /\sum_k N_k p_k)^2 \sum_k N_k p_k dq^N
                = \int (p_i p_j /\sum_k N_k p_k) dq^N

        Multiplying elementwise by N_i, the elements of row i give the probability
        for a sample from state i being observed in state j.


        Examples
        --------

        >>> from pymbar import testsystems
        >>> (x_kn, u_kn, N_k, s_n) = testsystems.HarmonicOscillatorsTestCase().sample(mode='u_kn')
        >>> mbar = MBAR(u_kn, N_k)
        >>> results = mbar.computeOverlap()

        """

        W = np.matrix(self.getWeights(), np.float64)
        O = np.multiply(self.N_k, W.T * W)
        (eigenvals, eigevec) = linalg.eig(O)
        # sort in descending order
        eigenvals = np.sort(eigenvals)[::-1]
        overlap_scalar = 1 - eigenvals[1] # 1 minus the second largest eigenvalue

        results_vals = dict()
        results_vals['scalar'] = overlap_scalar
        results_vals['eigenvalues'] = eigenvals
        results_vals['matrix'] = O

        return results_vals