Пример #1
0
def getHKS(mesh, num_samples=3, num_components=50, feature_name='hks', tau=1, eps=1e-5, normalize=True, **kwargs):
    try:
        from scipy.sparse.linalg import eigsh as sp_eigs
        from scipy.sparse import diags
    except ModuleNotFoundError:
        raise ModuleNotFoundError("The dependency 'SciPy' is required for this functionality!")
    
    # compute eigenvalues and eigenvectors of Laplace-Beltrami operator
    L = -mesh.cot_matrix
    M = mesh.mass_matrix
    
    try:
        evals, evecs = sp_eigs(L, k=num_components, M=M,  which='LM', sigma=0, **kwargs)
    except RuntimeError:
        # add small value to cot matrix to try and make it invertable
        D = diags(eps*np.ones(L.shape[0]))
        L = L + D
        evals, evecs = sp_eigs(L, k=num_components, M=M,  which='LM', sigma=0, **kwargs)
    
    if normalize:
        evals = evals/evals.sum()
        scale = mesh.area
    else:
        scale = 1
    
    # determine time samples
    tmin = tau/min(evals.max(), 1e+1)
    tmax = tau/max(evals.min(), 1e-3)
    tsamps = np.exp(np.linspace(np.log(tmin), np.log(tmax), num_samples))
    
    # compute heat kernel signatures
    evecs = evecs**2
    feature_names = []
    for i, t in enumerate(tsamps):
        fn = "{}{}".format(feature_name, i+1)
        HKS = scale*np.sum(np.exp(-t*evals)*evecs, axis=1)
        mesh.vertex_attributes[fn] = clipOutliers(HKS)
        feature_names.append(fn)
    
    return feature_names 
Пример #2
0
def cond(A, M=None):
    'Get the condition number of A or inv(B)*A'
    if __method__ == 'scipy':
        large, _ = sp_eigs(A, k=2, M=M, which='LM')
        small, _ = sp_eigs(A, k=4, M=M, which='LM', sigma=1E-8, tol=1E-10)

        l_max = np.max(large)
        l_min = np.min(small)

        print 'Lambda_max', l_max, 'Lambda_min', l_min

        return abs(l_max)/abs(l_min)

    elif __method__ == 'matlab':
        # Dump the matrix to A.m
        dump_matrix('A.m', 'A', A)
        # Call matlab to get eigs for problem      B*u = a*u, stored in cond.m
        os.system('matlab -nodesktop < run_A.m')
        # Parse the file to get condition number
        with open('cond.m') as f:
            for line in f:
                print float((line.strip().split())[0])
Пример #3
0
def segment(img_brightness):
    '''
    Compute and return the two segments of the image as described in the text. 
    Compute L, the laplacian matrix. Then compute D^(-1/2)LD^(-1/2),and find
    the eigenvector corresponding to the second smallest eigenvalue.
    Use this eigenvector to calculate a mask that will be usedto extract 
    the segments of the image.
    Inputs:
        img_brightness (array): an array of brightnesses given by the function
            getImage().
    Returns:
        seg1 (array): an array the same size as img_brightness, but with 0's
                for each pixel not included in the positive
                segment (which corresponds to the positive
                entries of the computed eigenvector)
        seg2 (array): an array the same size as img_brightness, but with 0's
                for each pixel not included in the negative
                segment.
    '''
    m, n = img_brightness.shape
    W, D_vals = adjacency(img_brightness, radius=6.0)
    temp_D = np.diagflat(D_vals)
    L = temp_D - W
    L = csc_matrix(L)
    D_vals = 1. / np.sqrt(D_vals)
    sqrD_matrix = np.diagflat(D_vals)
    sqrD_matrix = csc_matrix(sqrD_matrix)
    DLD = sqrD_matrix.dot(L.dot(sqrD_matrix))
    k, v = sp_eigs(DLD, which="SR")
    e_val = k[1]
    e_vec = v[:, 1]
    mask1 = e_vec > 0
    mask2 = e_vec <= 0
    mask1 = np.reshape(mask1, (m, n))
    mask2 = np.reshape(mask2, (m, n))
    seg1 = np.multiply(img_brightness, mask1)
    seg2 = np.multiply(img_brightness, mask2)
    return seg1, seg2
Пример #4
0
def segment(img_brightness):
    '''
    Compute and return the two segments of the image as described in the text. 
    Compute L, the laplacian matrix. Then compute D^(-1/2)LD^(-1/2),and find
    the eigenvector corresponding to the second smallest eigenvalue.
    Use this eigenvector to calculate a mask that will be usedto extract 
    the segments of the image.
    Inputs:
        img_brightness (array): an array of brightnesses given by the function
            getImage().
    Returns:
        seg1 (array): an array the same size as img_brightness, but with 0's
                for each pixel not included in the positive
                segment (which corresponds to the positive
                entries of the computed eigenvector)
        seg2 (array): an array the same size as img_brightness, but with 0's
                for each pixel not included in the negative
                segment.
    '''
    m,n = img_brightness.shape
    W,D_vals = adjacency(img_brightness, radius=6.0)
    temp_D = np.diagflat(D_vals)
    L = temp_D-W
    L = csc_matrix(L)
    D_vals = 1./np.sqrt(D_vals)
    sqrD_matrix = np.diagflat(D_vals)
    sqrD_matrix = csc_matrix(sqrD_matrix)
    DLD = sqrD_matrix.dot(L.dot(sqrD_matrix))
    k,v = sp_eigs(DLD, which="SR")
    e_val = k[1]
    e_vec = v[:,1] 
    mask1 = e_vec > 0
    mask2 = e_vec <= 0
    mask1 = np.reshape(mask1, (m,n))
    mask2 = np.reshape(mask2, (m,n))
    seg1 = np.multiply(img_brightness,mask1)
    seg2 = np.multiply(img_brightness,mask2)
    return seg1, seg2
Пример #5
0
def getHKS(mesh, num_samples=3, num_components=50, feature_name='hks', tau=1, **kwargs):
    
    # compute eigenvalues and eigenvectors of Laplace-Beltrami operator
    L = -mesh.cot_matrix
    M = mesh.mass_matrix
    
    evals, evecs = sp_eigs(L, k=num_components, M=M,  which='LM', sigma=0, **kwargs)
    
    # determine time samples
    tmin = tau/min(evals.max(), 1e+1)
    tmax = tau/max(evals.min(), 1e-3)
    tsamps = np.exp(np.linspace(np.log(tmin), np.log(tmax), num_samples))
    
    # compute heat kernel signatures
    evecs = evecs**2
    feature_names = []
    for i, t in enumerate(tsamps):
        fn = "{}{}".format(feature_name, i+1)
        HKS = np.sum(np.exp(-t*evals)*evecs, axis=1)
        mesh.vertex_attributes[fn] = clipOutliers(HKS)
        feature_names.append(fn)
    
    return feature_names 
Пример #6
0
    def eigs(self,
             neigs=None,
             symmetric=False,
             niter=None,
             uselobpcg=False,
             **kwargs_eig):
        r"""Most significant eigenvalues of linear operator.

        Return an estimate of the most significant eigenvalues
        of the linear operator. If the operator has rectangular
        shape (``shape[0]!=shape[1]``), eigenvalues are first
        computed for the square operator :math:`\mathbf{A^H}\mathbf{A}`
        and the square-root values are returned.

        Parameters
        ----------
        neigs : :obj:`int`
            Number of eigenvalues to compute (if ``None``, return all). Note
            that for ``explicit=False``, only :math:`N-1` eigenvalues can be
            computed where :math:`N` is the size of the operator in the
            model space
        symmetric : :obj:`bool`, optional
            Operator is symmetric (``True``) or not (``False``). User should
            set this parameter to ``True`` only when it is guaranteed that the
            operator is real-symmetric or complex-hermitian matrices
        niter : :obj:`int`, optional
            Number of iterations for eigenvalue estimation
        uselobpcg : :obj:`bool`, optional
            Use :func:`scipy.sparse.linalg.lobpcg`
        **kwargs_eig
            Arbitrary keyword arguments for :func:`scipy.sparse.linalg.eigs`,
            :func:`scipy.sparse.linalg.eigsh`, or
            :func:`scipy.sparse.linalg.lobpcg`

        Returns
        -------
        eigenvalues : :obj:`numpy.ndarray`
            Operator eigenvalues.

        Raises
        -------
        ValueError
            If ``uselobpcg=True`` for a non-symmetric square matrix with
            complex type

        Notes
        -----
        Depending on the size of the operator, whether it is explicit or not
        and the number of eigenvalues requested, different algorithms are
        used by this routine.

        More precisely, when only a limited number of eigenvalues is requested
        the :func:`scipy.sparse.linalg.eigsh` method is used in case of
        ``symmetric=True`` and the :func:`scipy.sparse.linalg.eigs` method
        is used ``symmetric=False``. However, when the matrix is represented
        explicitly within the linear operator (``explicit=True``) and all the
        eigenvalues are requested the :func:`scipy.linalg.eigvals` is used
        instead.

        Finally, when only a limited number of eigenvalues is required,
        it is also possible to explicitly choose to use the
        ``scipy.sparse.linalg.lobpcg`` method via the ``uselobpcg`` input
        parameter flag.

        Most of these algorithms are a port of ARPACK [1]_, a Fortran package
        which provides routines for quickly finding eigenvalues/eigenvectors
        of a matrix. As ARPACK requires only left-multiplication
        by the matrix in question, eigenvalues/eigenvectors can also be
        estimated for linear operators when the dense matrix is not available.

        .. [1] http://www.caam.rice.edu/software/ARPACK/

        """
        if self.explicit and isinstance(self.A, np.ndarray):
            if self.shape[0] == self.shape[1]:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = eigvals(self.A)
                else:
                    if not symmetric and np.iscomplexobj(self) and uselobpcg:
                        raise ValueError(
                            'cannot use scipy.sparse.linalg.lobpcg '
                            'for non-symmetric square matrices of '
                            'complex type...')
                    if symmetric and uselobpcg:
                        X = np.random.rand(self.shape[0], neigs)
                        eigenvalues = \
                            sp_lobpcg(self.A, X=X, maxiter=niter,
                                      **kwargs_eig)[0]
                    elif symmetric:
                        eigenvalues = sp_eigsh(self.A,
                                               k=neigs,
                                               maxiter=niter,
                                               **kwargs_eig)[0]
                    else:
                        eigenvalues = sp_eigs(self.A,
                                              k=neigs,
                                              maxiter=niter,
                                              **kwargs_eig)[0]

            else:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = np.sqrt(
                        eigvals(np.dot(np.conj(self.A.T), self.A)))
                else:
                    if uselobpcg:
                        X = np.random.rand(self.shape[1], neigs)
                        eigenvalues = np.sqrt(
                            sp_lobpcg(np.dot(np.conj(self.A.T), self.A),
                                      X=X,
                                      maxiter=niter,
                                      **kwargs_eig)[0])
                    else:
                        eigenvalues = np.sqrt(
                            sp_eigsh(np.dot(np.conj(self.A.T), self.A),
                                     k=neigs,
                                     maxiter=niter,
                                     **kwargs_eig)[0])
        else:
            if neigs is None or neigs >= self.shape[1]:
                neigs = self.shape[1] - 2
            if self.shape[0] == self.shape[1]:
                if not symmetric and np.iscomplexobj(self) and uselobpcg:
                    raise ValueError(
                        'cannot use scipy.sparse.linalg.lobpcg for '
                        'non symmetric square matrices of '
                        'complex type...')
                if symmetric and uselobpcg:
                    X = np.random.rand(self.shape[0], neigs)
                    eigenvalues = \
                        sp_lobpcg(self, X=X, maxiter=niter, **kwargs_eig)[0]
                elif symmetric:
                    eigenvalues = sp_eigsh(self,
                                           k=neigs,
                                           maxiter=niter,
                                           **kwargs_eig)[0]
                else:
                    eigenvalues = sp_eigs(self,
                                          k=neigs,
                                          maxiter=niter,
                                          **kwargs_eig)[0]
            else:
                if uselobpcg:
                    X = np.random.rand(self.shape[1], neigs)
                    eigenvalues = np.sqrt(
                        sp_lobpcg(self.H * self,
                                  X=X,
                                  maxiter=niter,
                                  **kwargs_eig)[0])
                else:
                    eigenvalues = np.sqrt(
                        sp_eigs(self.H * self,
                                k=neigs,
                                maxiter=niter,
                                **kwargs_eig)[0])
        return -np.sort(-eigenvalues)
Пример #7
0
    def eigs(self, neigs=None, symmetric=False, niter=None, **kwargs_eig):
        r"""Most significant eigenvalues of linear operator.

        Return an estimate of the most significant eigenvalues
        of the linear operator. If the operator has rectangular
        shape (``shape[0]!=shape[1]``), eigenvalues are first
        computed for the square operator :math:`\mathbf{A^H}\mathbf{A}`
        and the square-root values are returned.

        Parameters
        ----------
        neigs : :obj:`int`
            Number of eigenvalues to compute (if ``None``, return all). Note
            that for ``explicit=False``, only :math:`N-1` eigenvalues can be
            computed where :math:`N` is the size of the operator in the
            model space
        symmetric : :obj:`bool`, optional
            Operator is symmetric (``True``) or not (``False``). User should
            set this parameter to ``True`` only when it is guaranteed that the
            operator is real-symmetric or complex-hermitian matrices
        niter : :obj:`int`, optional
            Number of iterations for eigenvalue estimation
        **kwargs_eig
            Arbitrary keyword arguments for
            :func:`scipy.sparse.linalg.eigs` or
            :func:`scipy.sparse.linalg.eigsh`

        Returns
        -------
        eigenvalues : :obj:`numpy.ndarray`
            Operator eigenvalues.

        Notes
        -----
        Eigenvalues are estimated using :func:`scipy.sparse.linalg.eigs`
        (``explicit=True``) or :func:`scipy.sparse.linalg.eigsh`
        (``explicit=False``).

        This is a port of ARPACK [1]_, a Fortran package which provides
        routines for quickly finding eigenvalues/eigenvectors
        of a matrix. As ARPACK requires only left-multiplication
        by the matrix in question, eigenvalues/eigenvectors can also be
        estimated for linear operators when the dense matrix is not available.

        .. [1] http://www.caam.rice.edu/software/ARPACK/

        """
        if self.explicit and isinstance(self.A, np.ndarray):
            if self.shape[0] == self.shape[1]:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = eigvals(self.A)
                else:
                    if symmetric:
                        eigenvalues = sp_eigsh(self.A,
                                               k=neigs,
                                               maxiter=niter,
                                               **kwargs_eig)[0]
                    else:
                        eigenvalues = sp_eigs(self.A,
                                              k=neigs,
                                              maxiter=niter,
                                              **kwargs_eig)[0]

            else:
                if neigs is None or neigs == self.shape[1]:
                    eigenvalues = np.sqrt(
                        eigvals(np.dot(np.conj(self.A.T), self.A)))
                else:
                    eigenvalues = np.sqrt(
                        sp_eigsh(np.dot(np.conj(self.A.T), self.A),
                                 k=neigs,
                                 maxiter=niter,
                                 **kwargs_eig)[0])
        else:
            if neigs is None or neigs >= self.shape[1]:
                neigs = self.shape[1] - 2
            if self.shape[0] == self.shape[1]:
                if symmetric:
                    eigenvalues = sp_eigsh(self,
                                           k=neigs,
                                           maxiter=niter,
                                           **kwargs_eig)[0]
                else:
                    eigenvalues = sp_eigs(self,
                                          k=neigs,
                                          maxiter=niter,
                                          **kwargs_eig)[0]
            else:
                eigenvalues = np.sqrt(
                    sp_eigs(self.H * self,
                            k=neigs,
                            maxiter=niter,
                            **kwargs_eig)[0])
        return -np.sort(-eigenvalues)