Skip to content

Commit

Permalink
Merge 225edb6 into 9690d37
Browse files Browse the repository at this point in the history
  • Loading branch information
MengLiuPurdue committed Nov 26, 2018
2 parents 9690d37 + 225edb6 commit 5381008
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 3 deletions.
148 changes: 146 additions & 2 deletions localgraphclustering/GraphLocal.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@
import warnings
import collections as cole
from .cpp import *
import random

import gzip
import bz2
import lzma

import multiprocessing as mp

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import LineCollection
from mpl_toolkits.mplot3d.art3d import Line3DCollection
from matplotlib.colors import to_rgb,to_rgba

def _load_from_shared(sabuf, dtype, shape):
return np.frombuffer(sabuf, dtype=dtype).reshape(shape)

Expand Down Expand Up @@ -558,8 +565,6 @@ def local_extrema(self,vals,strict=False,reverse=False):
Parameters
----------
G: GraphLocal
vals: Sequence[float]
a feature value per node used to find the ex against each other, i.e. conductance
Expand Down Expand Up @@ -616,3 +621,142 @@ def local_extrema(self,vals,strict=False,reverse=False):
minvals = vals[minverts]

return minverts, minvals

def draw(self,coords,alpha=1.0,nodesize=5,linewidth=1,
nodealpha=1.0,edgealpha=0.01,nodecolor='r',
edgecolor='k',nodemarker='o',setalpha=1.0,
setcolor='y',axs=None,fig=None,nodeset=None,
groups=None):
"""
standard drawing function of GraphLocal object
Parameters
----------
coords: a n-by-2 or n-by-3 array with coordinates for each node of the graph.
Optional parameters
------------------
alpha: float (1.0 by default)
the overall alpha scaling of the plot, [0,1]
nodealpha: float (1.0 by default)
the overall node alpha scaling of the plot, [0, 1]
edgealpha: float (1.0 by default)
the overall edge alpha scaling of the plot, [0, 1]
setalpha: float (1.0 by default)
the overall set alpha scaling of the plot, [0, 1]
nodecolor: string or RGB ('r' by default)
edgecolor: string or RGB ('k' by default)
setcolor: string or RGB ('y' by default)
nodemarker: string ('o' by default)
nodesize: float (5.0 by default)
linewidth: float (1.0 by default)
nodeset: Sequence[int] (None by default)
a set of nodes to highlight
groups: Sequence[Sequence[int]] (None by default)
node partitions, different colors will be assigned to different groups
axs,fig: None,None (default)
by default it will create a new figure, or this will plot in axs if not None.
Returns
-------
a dictionary with:
fig, ax, setnodes, groupnodes
"""
if axs is None:
fig = plt.figure()
if len(coords[0]) == 3:
axs = fig.add_subplot(111, projection='3d')
else:
axs = fig.add_subplot(111)
axs.set_axis_off()
nodeset = set(nodeset) if nodeset is not None else set()
nodelist_in = []
nodelist_out = []
for i in range(self._num_vertices):
if i in nodeset:
nodelist_in.append(i)
else:
nodelist_out.append(i)
#store color information for each node
node_color_list = np.empty((self._num_vertices,4))
node_color_list[nodelist_out] = to_rgba(nodecolor,alpha*nodealpha)
node_color_list[nodelist_in] = to_rgba(setcolor,alpha*setalpha)
#reassign node colors based on partition
if groups is not None:
number_of_colors = len(groups)
color = ["#"+''.join([random.choice('0123456789ABCDEF') for j in range(6)])
for i in range(number_of_colors)]
for i,g in enumerate(groups):
for k in g:
node_color_list[k] = to_rgba(color[i],alpha*nodealpha)
if len(coords[0]) == 3:
self.draw_3d(coords,axs,nodemarker=nodemarker,nodesize=nodesize,edgealpha=alpha*edgealpha,
linewidth=linewidth,node_color_list=node_color_list)
else:
self.draw_2d(coords,axs,nodemarker=nodemarker,nodesize=nodesize,edgealpha=alpha*edgealpha,
linewidth=linewidth,node_color_list=node_color_list)

ret_dict = {"fig":fig,"ax":axs,"setnodes":nodelist_in,"groupnodes":groups}
return ret_dict

@staticmethod
def draw_star(center,points,pos,edge_pos):
for i,p in enumerate(points):
if p >= center:
edge_pos.append([pos[center],pos[p]])

def draw_2d(self,pos,axs,nodemarker='o',nodesize=5,edgealpha=0.01,linewidth=1,
node_color_list=None,edgecolor='k',nodecolor='r',node_list=None):
if node_color_list is not None:
node_collection = axs.scatter([p[0] for p in pos],[p[1] for p in pos],c=node_color_list,s=nodesize,marker=nodemarker)
else:
node_collection = axs.scatter([p[0] for p in pos],[p[1] for p in pos],c=nodecolor,s=nodesize,marker=nodemarker)
#make sure nodes are on the top
node_collection.set_zorder(2)
node_list = range(self._num_vertices) if node_list is None else node_list
edge_pos = []
for i in node_list:
self.draw_star(i,self.aj[self.ai[i]:self.ai[i+1]],pos,edge_pos)
edge_pos = np.asarray(edge_pos)
edge_collection = LineCollection(edge_pos,colors=to_rgba(edgecolor,edgealpha),linewidths=linewidth)
#make sure edges are at the bottom
edge_collection.set_zorder(1)
axs.add_collection(edge_collection)
axs.autoscale()

def draw_3d(self,pos,axs,nodemarker='o',nodesize=5,edgealpha=0.01,linewidth=1,
node_color_list=None,angle=30,edgecolor='k',nodecolor='r',node_list=None):
if node_color_list is not None:
node_collection = axs.scatter([p[0] for p in pos],[p[1] for p in pos],[p[2] for p in pos],c=node_color_list,
s=nodesize,marker=nodemarker,zorder=2)
else:
node_collection = axs.scatter([p[0] for p in pos],[p[1] for p in pos],[p[2] for p in pos],c=nodecolor,
s=nodesize,marker=nodemarker,zorder=2)
#make sure nodes are on the top
node_list = range(self._num_vertices) if node_list is None else node_list
edge_pos = []
for i in node_list:
self.draw_star(i,self.aj[self.ai[i]:self.ai[i+1]],pos,edge_pos)
edge_pos = np.asarray(edge_pos)
edge_collection = Line3DCollection(edge_pos,colors=to_rgba(edgecolor,edgealpha),linewidths=linewidth)
#make sure edges are at the bottom
edge_collection.set_zorder(1)
axs.add_collection(edge_collection)
axs.autoscale()
# Set the initial view
axs.view_init(30, angle)
40 changes: 40 additions & 0 deletions localgraphclustering/tests/test_algs.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
from localgraphclustering import *
import time
import numpy as np
import networkx as nx
import random

def load_example_graph(vtype,itype):
return GraphLocal("localgraphclustering/tests/data/dolphins.edges",separator=" ",vtype=vtype,itype=itype)

def generate_random_3Dgraph(n_nodes, radius, seed=None):

if seed is not None:
random.seed(seed)

# Generate a dict of positions
pos = {i: (random.uniform(0, 1), random.uniform(0, 1), random.uniform(0, 1)) for i in range(n_nodes)}

# Create random 3D network
G = nx.random_geometric_graph(n_nodes, radius, pos=pos)

return G

def test_GraphLocal_methods():
g = load_example_graph(np.uint32,np.uint32)
g.largest_component()
Expand Down Expand Up @@ -33,6 +48,31 @@ def test_GraphLocal_methods():
# Test graph with more than one components
G = GraphLocal("notebooks/datasets/neuro-fmri-01.edges",file_type = "edgelist", separator = " ", header = True)

# Test drawing fuinctions
g = GraphLocal('notebooks/datasets/JohnsHopkins.graphml','graphml','\t')
ld_coord = np.loadtxt('notebooks/datasets/JohnHopkins_coord.xy', dtype = 'Float64')
idx = np.argsort(ld_coord[:,0])
coords = []
for i in range(g._num_vertices):
coords.append(ld_coord[idx[i],1:3])
coords = np.array(coords)
# Call the global spectral partitioning algorithm.
eig2 = fiedler(g)[0]

# Round the eigenvector
output_sc = sweep_cut(g,eig2)

# Extract the partition for g and store it.
eig2_rounded = output_sc[0]
ret_dict = g.draw(coords,edgealpha=0.01,nodealpha=0.5,nodeset=eig2_rounded)

N = generate_random_3Dgraph(n_nodes=200, radius=0.25, seed=1)
pos = list(nx.get_node_attributes(N,'pos').values())
G = GraphLocal()
G = G.from_networkx(N)
ret_dict = G.draw(pos,edgealpha=0.01,nodealpha=0.5,nodeset=range(100,150),groups=[range(50),range(50,100)])


def test_sweepcut_self_loop():
""" This is a regression test for sweep-cuts with self-loops """
g = GraphLocal()
Expand Down
2 changes: 1 addition & 1 deletion notebooks/examples_with_visualization.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
"version": "3.6.5"
}
},
"nbformat": 4,
Expand Down

0 comments on commit 5381008

Please sign in to comment.