Source code for pygsp.operators.operator

# -*- coding: utf-8 -*-

from pygsp.utils import build_logger
from pygsp.data_handling import adj2vec

import numpy as np
from scipy import sparse


logger = build_logger(__name__)


[docs]def div(G, s): r""" Compute Graph divergence of a signal. Parameters ---------- G : Graph structure s : ndarray Signal living on the nodes Returns ------- di : float The graph divergence """ if hasattr(G, 'lap_type'): if G.lap_type == 'combinatorial': raise NotImplementedError('Not implemented yet. However ask Nathanael it is very easy.') if G.Ne != np.shape(s)[0]: raise ValueError('Signal size not equal to number of edges.') D = grad_mat(G) di = D.T * s if s.dtype == 'float32': di = np.float32(di) return di
[docs]def grad(G, s): r""" Compute the Graph gradient. Example ------- >>> import pygsp >>> import numpy as np >>> G = pygsp.graphs.Logo() >>> s = np.random.rand(G.Ne) >>> grad = pygsp.operators.grad(G, s) Parameters ---------- G : Graph structure s : ndarray Signal living on the nodes Returns ------- gr : ndarray Gradient living on the edges """ if hasattr(G, 'lap_type'): if G.lap_type == 'combinatorial': raise NotImplementedError('Not implemented yet. However ask Nathanael it is very easy.') D = grad_mat(G) gr = D * s if s.dtype == 'float32': gr = np.float32(gr) return gr
[docs]def grad_mat(G): # 1 call (above) r""" Gradient sparse matrix of the graph G. Example ------- >>> import pygsp >>> G = pygsp.graphs.Logo() >>> D = grad_mat(G) Parameters ---------- G : Graph structure Returns ------- D : ndarray Gradient sparse matrix """ if not hasattr(G, 'v_in'): G = adj2vec(G) if hasattr(G, 'Diff'): D = G.Diff else: n = G.Ne Dc = np.ones((2 * n)) Dv = np.ones((2 * n)) Dr = np.concatenate((np.arange(n), np.arange(n))) Dc[:n] = G.v_in Dc[n:] = G.v_out Dv[:n] = np.sqrt(G.weights) Dv[n:] = -np.sqrt(G.weight) D = sparse.csc_matrix((Dv, (Dr, Dc)), shape=(n, G.N)) G.Diff = D return D
def gft(G, f): r""" Compute Graph Fourier transform. Parameters ---------- G : Graph or Fourier basis f : ndarray must be in 2d, even if the second dim is 1 signal Returns ------- f_hat : ndarray Graph Fourier transform of *f* """ from pygsp.graphs import Graph if isinstance(G, Graph): if not hasattr(G, 'U'): logger.info('Analysis filter has to compute the eigenvalues and the eigenvectors.') G.compute_fourier_basis() U = G.U else: U = G return np.dot(np.conjugate(U.T), f) # True Hermitian here.
[docs]def igft(G, f_hat): r""" Compute inverse graph Fourier transform. Parameters ---------- G : Graph or Fourier basis f_hat : ndarray Signal Returns ------- f : ndarray Inverse graph Fourier transform of *f_hat* """ from pygsp.graphs import Graph if isinstance(G, Graph): if not hasattr(G, 'U'): logger.info('Analysis filter has to compute the eigenvalues and the eigenvectors.') G.compute_fourier_basis() U = G.U else: U = G return np.dot(U, f_hat)
[docs]def localize(g, i): r""" Localize a kernel g to the node i. Parameters ---------- g : Filter kernel (or filterbank) i : int Index of vertex Returns ------- gt : ndarray Translated signal """ N = g.G.N f = np.zeros((N)) f[i - 1] = 1 gt = np.sqrt(N) * g.analysis(f) return gt
[docs]def modulate(G, f, k): r""" Tranlate the signal f to the node i. Parameters ---------- G : Graph f : ndarray Signal (column) k : int Index of frequencies Returns ------- fm : ndarray Modulated signal """ nt = np.shape(f)[1] fm = np.sqrt(G.N)*np.kron(np.ones((nt, 1)), f)*np.kron(np.ones((1, nt)), G.U[:, k]) return fm
[docs]def translate(G, f, i): r""" Tranlate the signal f to the node i Parameters ---------- G : Graph f : ndarray Signal i : int Indices of vertex Returns ------- ft : translate signal """ fhat = gft(G, f) nt = np.shape(f)[1] ft = np.sqrt(G.N)*igft(G, fhat, np.kron(np.ones((1, nt)), G.U[i])) return ft