Skip to content

Commit

Permalink
Merge pull request #44 from epfl-lts2/improvements
Browse files Browse the repository at this point in the history
Many small improvements to the Graph class
  • Loading branch information
mdeff authored Mar 1, 2019
2 parents ec1a4cb + 3524584 commit d780954
Show file tree
Hide file tree
Showing 33 changed files with 391 additions and 365 deletions.
6 changes: 3 additions & 3 deletions pygsp/filters/approximations.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,16 @@ def cheby_rect(G, bounds, signal, **kwargs):
Parameters
----------
G : Graph
bounds : array-like
bounds : array_like
The bounds of the pass-band filter
signal : array-like
signal : array_like
Signal to filter
order : int (optional)
Order of the Chebyshev polynomial (default: 30)
Returns
-------
r : array-like
r : array_like
Result of the filtering
"""
Expand Down
13 changes: 7 additions & 6 deletions pygsp/filters/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def evaluate(self, x):
Parameters
----------
x : ndarray
x : array_like
Graph frequencies at which to evaluate the filter.
Returns
Expand All @@ -138,6 +138,7 @@ def evaluate(self, x):
[<matplotlib.lines.Line2D object at ...>]
"""
x = np.asanyarray(x)
# Avoid to copy data as with np.array([g(x) for g in self._kernels]).
y = np.empty([self.Nf] + list(x.shape))
for i, kernel in enumerate(self._kernels):
Expand Down Expand Up @@ -179,7 +180,7 @@ def filter(self, s, method='chebyshev', order=30):
Parameters
----------
s : ndarray
s : array_like
Graph signals, a tensor of shape ``(N_NODES, N_SIGNALS,
N_FEATURES)``, where ``N_NODES`` is the number of nodes in the
graph, ``N_SIGNALS`` the number of independent signals you want to
Expand Down Expand Up @@ -265,9 +266,7 @@ def filter(self, s, method='chebyshev', order=30):
True
"""
if s.shape[0] != self.G.N:
raise ValueError('First dimension should be the number of nodes '
'G.N = {}, got {}.'.format(self.G.N, s.shape))
s = self.G._check_signal(s)

# TODO: not in self.Nin (Nf = Nin x Nout).
if s.ndim == 1 or s.shape[-1] not in [1, self.Nf]:
Expand Down Expand Up @@ -412,7 +411,7 @@ def estimate_frame_bounds(self, x=None):
Parameters
----------
x : ndarray
x : array_like
Graph frequencies at which to evaluate the filter bank `g(x)`.
The default is `x = np.linspace(0, G.lmax, 1000)`.
The exact bounds are given by evaluating the filter bank at the
Expand Down Expand Up @@ -499,6 +498,8 @@ def estimate_frame_bounds(self, x=None):
"""
if x is None:
x = np.linspace(0, self.G.lmax, 1000)
else:
x = np.asanyarray(x)

sum_filters = np.sum(self.evaluate(x)**2, axis=0)

Expand Down
2 changes: 1 addition & 1 deletion pygsp/filters/mexicanhat.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class MexicanHat(Filter):
lpfactor : float
Low-pass factor. lmin=lmax/lpfactor will be used to determine scales.
The scaling function will be created to fill the low-pass gap.
scales : array-like
scales : array_like
Scales to be used.
By default, initialized with :func:`pygsp.utils.compute_log_scales`.
normalize : bool
Expand Down
2 changes: 1 addition & 1 deletion pygsp/filters/meyer.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def kernel(x, kernel_type):
* meyer scaling function kernel: supported on [0,4/3]
"""

x = np.asarray(x)
x = np.asanyarray(x)

l1 = 2/3.
l2 = 4/3. # 2*l1
Expand Down
2 changes: 1 addition & 1 deletion pygsp/filters/simpletight.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SimpleTight(Filter):
G : graph
Nf : int
Number of filters to cover the interval [0, lmax].
scales : array-like
scales : array_like
Scales to be used. Defaults to log scale.
Examples
Expand Down
2 changes: 1 addition & 1 deletion pygsp/filters/wave.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def __init__(self, G, time=10, speed=1):
raise ValueError('If both parameters are iterable, '
'they should have the same length.')

if np.any(np.asarray(speed) >= 2):
if np.any(np.asanyarray(speed) >= 2):
raise ValueError('The wave propagation speed should be in [0, 2[')

def kernel(x, time, speed):
Expand Down
2 changes: 1 addition & 1 deletion pygsp/graphs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@
.. autosummary::
Graph.check_weights
Graph.is_connected
Graph.is_directed
Graph.has_loops
Plotting
--------
Expand Down
2 changes: 1 addition & 1 deletion pygsp/graphs/airfoil.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,5 @@ def __init__(self, **kwargs):
"limits": np.array([-1e-4, 1.01*data['x'].max(),
-1e-4, 1.01*data['y'].max()])}

super(Airfoil, self).__init__(W=W, coords=coords, plotting=plotting,
super(Airfoil, self).__init__(W, coords=coords, plotting=plotting,
**kwargs)
2 changes: 1 addition & 1 deletion pygsp/graphs/barabasialbert.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def __init__(self, N=1000, m0=1, m=1, seed=None, **kwargs):
W[elem, i] = 1
W[i, elem] = 1

super(BarabasiAlbert, self).__init__(W=W, **kwargs)
super(BarabasiAlbert, self).__init__(W, **kwargs)

def _get_extra_repr(self):
return dict(m0=self.m0, m=self.m, seed=self.seed)
2 changes: 1 addition & 1 deletion pygsp/graphs/comet.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def __init__(self, N=32, k=12, **kwargs):
np.min(tmpcoords[:, 1]),
np.max(tmpcoords[:, 1])])}

super(Comet, self).__init__(W=W, coords=tmpcoords,
super(Comet, self).__init__(W, coords=tmpcoords,
plotting=plotting, **kwargs)

def _get_extra_repr(self):
Expand Down
2 changes: 1 addition & 1 deletion pygsp/graphs/community.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def __init__(self,
for key, value in {'Nc': Nc, 'info': info}.items():
setattr(self, key, value)

super(Community, self).__init__(W=W, coords=coords, **kwargs)
super(Community, self).__init__(W, coords=coords, **kwargs)

def _get_extra_repr(self):
attrs = {'Nc': self.Nc,
Expand Down
2 changes: 1 addition & 1 deletion pygsp/graphs/davidsensornet.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def __init__(self, N=64, seed=None, **kwargs):

plotting = {"limits": [0, 1, 0, 1]}

super(DavidSensorNet, self).__init__(W=W, coords=coords,
super(DavidSensorNet, self).__init__(W, coords=coords,
plotting=plotting, **kwargs)

def _get_extra_repr(self):
Expand Down
35 changes: 17 additions & 18 deletions pygsp/graphs/difference.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,11 @@ def compute_differential_operator(self):
The difference operator is an incidence matrix.
Example with a undirected graph.
>>> adjacency = np.array([
>>> graph = graphs.Graph([
... [0, 2, 0],
... [2, 0, 1],
... [0, 1, 0],
... ])
>>> graph = graphs.Graph(adjacency)
>>> graph.compute_laplacian('combinatorial')
>>> graph.compute_differential_operator()
>>> graph.D.toarray()
Expand All @@ -116,12 +115,11 @@ def compute_differential_operator(self):
Example with a directed graph.
>>> adjacency = np.array([
>>> graph = graphs.Graph([
... [0, 2, 0],
... [2, 0, 1],
... [0, 0, 0],
... ])
>>> graph = graphs.Graph(adjacency)
>>> graph.compute_laplacian('combinatorial')
>>> graph.compute_differential_operator()
>>> graph.D.toarray()
Expand Down Expand Up @@ -199,7 +197,7 @@ def grad(self, x):
Parameters
----------
x : ndarray
x : array_like
Signal of length :attr:`n_vertices` living on the vertices.
Returns
Expand All @@ -217,27 +215,26 @@ def grad(self, x):
--------
>>> graph = graphs.Path(4, directed=False, lap_type='combinatorial')
>>> graph.compute_differential_operator()
>>> graph.grad(np.array([0, 2, 4, 2]))
>>> graph.grad([0, 2, 4, 2])
array([ 2., 2., -2.])
>>> graph = graphs.Path(4, directed=True, lap_type='combinatorial')
>>> graph.compute_differential_operator()
>>> graph.grad(np.array([0, 2, 4, 2]))
>>> graph.grad([0, 2, 4, 2])
array([ 1.41421356, 1.41421356, -1.41421356])
>>> graph = graphs.Path(4, directed=False, lap_type='normalized')
>>> graph.compute_differential_operator()
>>> graph.grad(np.array([0, 2, 4, 2]))
>>> graph.grad([0, 2, 4, 2])
array([ 1.41421356, 1.41421356, -0.82842712])
>>> graph = graphs.Path(4, directed=True, lap_type='normalized')
>>> graph.compute_differential_operator()
>>> graph.grad(np.array([0, 2, 4, 2]))
>>> graph.grad([0, 2, 4, 2])
array([ 1.41421356, 1.41421356, -0.82842712])
"""
if self.N != x.shape[0]:
raise ValueError('Signal length should be the number of nodes.')
x = self._check_signal(x)
return self.D.T.dot(x)

def div(self, y):
Expand Down Expand Up @@ -273,7 +270,7 @@ def div(self, y):
Parameters
----------
y : ndarray
y : array_like
Signal of length :attr:`n_edges` living on the edges.
Returns
Expand All @@ -291,25 +288,27 @@ def div(self, y):
--------
>>> graph = graphs.Path(4, directed=False, lap_type='combinatorial')
>>> graph.compute_differential_operator()
>>> graph.div(np.array([2, -2, 0]))
>>> graph.div([2, -2, 0])
array([-2., 4., -2., 0.])
>>> graph = graphs.Path(4, directed=True, lap_type='combinatorial')
>>> graph.compute_differential_operator()
>>> graph.div(np.array([2, -2, 0]))
>>> graph.div([2, -2, 0])
array([-1.41421356, 2.82842712, -1.41421356, 0. ])
>>> graph = graphs.Path(4, directed=False, lap_type='normalized')
>>> graph.compute_differential_operator()
>>> graph.div(np.array([2, -2, 0]))
>>> graph.div([2, -2, 0])
array([-2. , 2.82842712, -1.41421356, 0. ])
>>> graph = graphs.Path(4, directed=True, lap_type='normalized')
>>> graph.compute_differential_operator()
>>> graph.div(np.array([2, -2, 0]))
>>> graph.div([2, -2, 0])
array([-2. , 2.82842712, -1.41421356, 0. ])
"""
if self.Ne != y.shape[0]:
raise ValueError('Signal length should be the number of edges.')
y = np.asanyarray(y)
if y.shape[0] != self.Ne:
raise ValueError('First dimension must be the number of edges '
'G.Ne = {}, got {}.'.format(self.Ne, y.shape))
return self.D.dot(y)
12 changes: 4 additions & 8 deletions pygsp/graphs/fourier.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ def gft(self, s):
Parameters
----------
s : ndarray
s : array_like
Graph signal in the vertex domain.
Returns
Expand All @@ -219,9 +219,7 @@ def gft(self, s):
True
"""
if s.shape[0] != self.N:
raise ValueError('First dimension should be the number of nodes '
'G.N = {}, got {}.'.format(self.N, s.shape))
s = self._check_signal(s)
U = np.conjugate(self.U) # True Hermitian. (Although U is often real.)
return np.tensordot(U, s, ([0], [0]))

Expand All @@ -237,7 +235,7 @@ def igft(self, s_hat):
Parameters
----------
s_hat : ndarray
s_hat : array_like
Graph signal in the Fourier domain.
Returns
Expand All @@ -256,7 +254,5 @@ def igft(self, s_hat):
True
"""
if s_hat.shape[0] != self.N:
raise ValueError('First dimension should be the number of nodes '
'G.N = {}, got {}.'.format(self.N, s_hat.shape))
s_hat = self._check_signal(s_hat)
return np.tensordot(self.U, s_hat, ([1], [0]))
2 changes: 1 addition & 1 deletion pygsp/graphs/fullconnected.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ def __init__(self, N=10, **kwargs):
W = np.ones((N, N)) - np.identity(N)
plotting = {'limits': np.array([-1, 1, -1, 1])}

super(FullConnected, self).__init__(W=W, plotting=plotting, **kwargs)
super(FullConnected, self).__init__(W, plotting=plotting, **kwargs)
Loading

0 comments on commit d780954

Please sign in to comment.