pygel3d.graph
This module provides a Graph class and functionality for skeletonization using graphs.
1""" This module provides a Graph class and functionality for skeletonization using graphs. """ 2import ctypes as ct 3import numpy as np 4from pygel3d import hmesh, lib_py_gel, IntVector 5 6class Graph: 7 """ This class is for representing graphs embedded in 3D. The class does not in 8 itself come with many features: it contains methods for creating, accessing, and 9 housekeeping. When vertices are used as parameters in the functions below, we usually 10 use the parameter name n (for node). n is simply an index (i.e. an integer) that 11 refers to a node (aka vertex).""" 12 def __init__(self,orig=None): 13 if orig == None: 14 self.obj = lib_py_gel.Graph_new() 15 else: 16 self.obj = lib_py_gel.Graph_copy(orig.obj) 17 def __del__(self): 18 lib_py_gel.Graph_delete(self.obj) 19 def clear(self): 20 """ Clear the graph. """ 21 lib_py_gel.Graph_clear(self.obj) 22 def cleanup(self): 23 """ Cleanup reorders the graph nodes such that there is no 24 gap in the index range. """ 25 lib_py_gel.Graph_cleanup(self.obj) 26 def nodes(self): 27 """ Get all nodes as an iterable range """ 28 nodes = IntVector() 29 lib_py_gel.Graph_nodes(self.obj, nodes.obj) 30 return nodes 31 def neighbors(self, n, mode='n'): 32 """ Get the neighbors of node n. The final argument is either 'n' or 'e'. If it is 'n' 33 the function returns all neighboring nodes, and if it is 'e' it returns incident edges.""" 34 nbors = IntVector() 35 lib_py_gel.Graph_neighbors(self.obj, n, nbors.obj, ct.c_char(mode.encode('ascii'))) 36 return nbors 37 def positions(self): 38 """ Get the vertex positions by reference. You can assign to the 39 positions. """ 40 pos = ct.POINTER(ct.c_double)() 41 n = lib_py_gel.Graph_positions(self.obj, ct.byref(pos)) 42 return np.ctypeslib.as_array(pos,(n,3)) 43 def average_edge_length(self): 44 """ Returns the average edge length. """ 45 ael = lib_py_gel.Graph_average_edge_length(self.obj) 46 return ael 47 def add_node(self, p): 48 """ Adds node with position p to the graph and returns the 49 index of the new node. """ 50 return lib_py_gel.Graph_add_node(self.obj, np.array(p)) 51 def remove_node(self, n): 52 """ Removes the node n passed as argument. This does not change 53 any indices of other nodes, but n is then invalid. """ 54 lib_py_gel.Graph_remove_node(self.obj, n) 55 def node_in_use(self, n): 56 """ Checks if n is in_use. This function returns false both 57 if n has been removed and if n is an index outside the range of 58 indices that are used. """ 59 return lib_py_gel.Graph_node_in_use(self.obj, n) 60 def connect_nodes(self, n0, n1): 61 """ Creates a new edge connecting nodes n0 and n1. The index of 62 the new edge is returned. """ 63 return lib_py_gel.Graph_connect_nodes(self.obj, n0, n1) 64 def disconnect_nodes(self, n0, n1): 65 """ Disconect nodes n0 and n1""" 66 lib_py_gel.Graph_disconnect_nodes(self.obj, n0, n1) 67 def merge_nodes(self, n0, n1, avg_pos): 68 """ Merge nodes n0 and n1. avg_pos indicates if you want the position to be the average. """ 69 lib_py_gel.Graph_merge_nodes(self.obj, n0, n1, avg_pos) 70 71 72def from_mesh(m): 73 """ Creates a graph from a mesh. The argument, m, is the input mesh, 74 and the function returns a graph with the same vertices and edges 75 as m.""" 76 g = Graph() 77 lib_py_gel.graph_from_mesh(m.obj, g.obj) 78 return g 79 80def load(fn): 81 """ Load a graph from a file. The argument, fn, is the filename which 82 is in a special format similar to Wavefront obj. The loaded graph is 83 returned by the function - or None if loading failed. """ 84 s = ct.c_char_p(fn.encode('utf-8')) 85 g = Graph() 86 if lib_py_gel.graph_load(g.obj, s): 87 return g 88 return None 89 90def save(fn, g): 91 """ Save graph to a file. The first argument, fn, is the file name, 92 and g is the graph. This function returns True if saving happened and 93 False otherwise. """ 94 s = ct.c_char_p(fn.encode('utf-8')) 95 return lib_py_gel.graph_save(g.obj, s) 96 97def to_mesh_cyl(g, fudge=0.0): 98 """ Creates a Manifold mesh from the graph. The first argument, g, is the 99 graph we want converted, and fudge is a constant that is used to increase the radius 100 of every node. This is useful if the radii are 0. """ 101 m = hmesh.Manifold() 102 lib_py_gel.graph_to_mesh_cyl(g.obj, m.obj, fudge) 103 return m 104 105def to_mesh_iso(g, fudge=0.0, res=256): 106 """ Creates a Manifold mesh from the graph. The first argument, g, is the 107 graph we want converted, and fudge is a constant that is used to increase the radius 108 of every node. This is useful if the radii are 0. """ 109 m = hmesh.Manifold() 110 lib_py_gel.graph_to_mesh_iso(g.obj, m.obj, fudge, res) 111 return m 112 113 114def smooth(g, iter=1, alpha=1.0): 115 """ Simple Laplacian smoothing of a graph. The first argument is the Graph, g, iter 116 is the number of iterations, and alpha is the weight. If the weight is high, 117 each iteration causes a lot of smoothing, and a high number of iterations 118 ensures that the effect of smoothing diffuses throughout the graph, i.e. that the 119 effect is more global than local. """ 120 lib_py_gel.graph_smooth(g.obj, iter, alpha) 121 122def edge_contract(g, dist_thresh): 123 """ Simplifies a graph by contracting edges. The first argument, g, is the graph, 124 and only edges shorter than dist_thresh are contracted. When an edge is contracted 125 the merged vertices are moved to the average of their former positions. Thus, 126 the ordering in which contractions are carried out matters. Hence, edges are 127 contracted in the order of increasing length and edges are only considered if 128 neither end point is the result of a contraction, but the process is then repeated 129 until no more contractions are possible. Returns total number of contractions. """ 130 return lib_py_gel.graph_edge_contract(g.obj, dist_thresh) 131 132def prune(g): 133 """ Prune leaves of a graph. The graph, g, is passed as the argument. This function 134 removes leaf nodes (valency 1) whose only neighbour has valency > 2. In practice 135 such isolated leaves are frequently spurious if the graph is a skeleton. Does not 136 return a value. """ 137 lib_py_gel.graph_prune(g.obj) 138 139def saturate(g, hops=2, dist_frac=1.001, rad=1e300): 140 """ Saturate the graph with edges. This is not a complete saturation. Edges are 141 introduced between a vertex and other vertices that are reachable in hops steps, i.e. 142 hops-order neighbors. dist_frac and rad are parameters used to govern the precise 143 behaviour. Two nodes are only connected if their distance is less than rad and if 144 their distance is less than dist_frac times the length of the path along existing 145 edges in the graph. If dist_frac is at approximately 1 and rad is enormous, these 146 two parameters make no difference. """ 147 lib_py_gel.graph_saturate(g.obj, hops, dist_frac, rad) 148 149def LS_skeleton(g, sampling=True): 150 """ Skeletonize a graph using the local separators approach. The first argument, 151 g, is the graph, and, sampling indicates whether we try to use all vertices 152 (False) as starting points for finding separators or just a sampling (True). 153 The function returns a new graph which is the skeleton of the input graph. """ 154 skel = Graph() 155 mapping = IntVector() 156 lib_py_gel.graph_LS_skeleton(g.obj, skel.obj, mapping.obj, sampling) 157 return skel 158 159def LS_skeleton_and_map(g, sampling=True): 160 """ Skeletonize a graph using the local separators approach. The first argument, 161 g, is the graph, and, sampling indicates whether we try to use all vertices 162 (False) as starting points for finding separators or just a sampling (True). 163 The function returns a tuple containing a new graph which is the skeleton of 164 the input graph and a map from the graph nodes to the skeletal nodes. """ 165 skel = Graph() 166 mapping = IntVector() 167 lib_py_gel.graph_LS_skeleton(g.obj, skel.obj, mapping.obj, sampling) 168 return skel, mapping 169 170def MSLS_skeleton(g, grow_thresh=64): 171 """ Skeletonize a graph using the multi-scale local separators approach. The first argument, 172 g, is the graph, and, sampling indicates whether we try to use all vertices 173 (False) as starting points for finding separators or just a sampling (True). 174 The function returns a new graph which is the skeleton of the input graph. """ 175 skel = Graph() 176 mapping = IntVector() 177 lib_py_gel.graph_MSLS_skeleton(g.obj, skel.obj, mapping.obj, grow_thresh) 178 return skel 179 180def MSLS_skeleton_and_map(g, grow_thresh=64): 181 """ Skeletonize a graph using the multi-scale local separators approach. The first argument, 182 g, is the graph, and, sampling indicates whether we try to use all vertices 183 (False) as starting points for finding separators or just a sampling (True). 184 The function returns a tuple containing a new graph which is the skeleton of 185 the input graph and a map from the graph nodes to the skeletal nodes. """ 186 skel = Graph() 187 mapping = IntVector() 188 lib_py_gel.graph_MSLS_skeleton(g.obj, skel.obj, mapping.obj, grow_thresh) 189 return skel, mapping 190 191 192def front_skeleton_and_map(g, colors, intervals=100): 193 """ Skeletonize a graph using the front separators approach. The first argument, 194 g, is the graph, and, colors is an nD array where each column contains a sequence 195 of floating point values - one for each node. We can have as many columns as needed 196 for the front separator computation. We can think of this as a coloring 197 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 198 of the nodes or some other function that indicates something about the structure of the 199 graph. The function returns a tuple containing a new graph which is the 200 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 201 skel = Graph() 202 mapping = IntVector() 203 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 204 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 205 print("N_col:", N_col) 206 pos = g.positions() 207 lib_py_gel.graph_front_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 208 return skel, mapping 209 210def front_skeleton(g, colors, intervals=100): 211 """ Skeletonize a graph using the front separators approach. The first argument, 212 g, is the graph, and, colors is a nD array where each column contains a sequence 213 of floating point values - one for each node. We can have as many columns as needed 214 for the front separator computation. We can think of this as a coloring 215 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 216 of the nodes or some other function that indicates something about the structure of the 217 graph. The function returns a tuple containing a new graph which is the 218 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 219 skel = Graph() 220 mapping = IntVector() 221 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 222 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 223 print("N_col:", N_col) 224 pos = g.positions() 225 lib_py_gel.graph_front_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 226 return skel 227 228def combined_skeleton_and_map(g, colors, intervals=100): 229 """ Skeletonize a graph using both the front separators approach and the multi scale local separators. 230 The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence 231 of floating point values - one for each node. We can have as many columns as needed 232 for the front separator computation. We can think of this as a coloring 233 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 234 of the nodes or some other function that indicates something about the structure of the 235 graph. The function returns a tuple containing a new graph which is the 236 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 237 skel = Graph() 238 mapping = IntVector() 239 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 240 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 241 print("N_col:", N_col) 242 pos = g.positions() 243 lib_py_gel.graph_combined_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 244 return skel, mapping 245 246def combined_skeleton(g, colors, intervals=100): 247 """ Skeletonize a graph using both the front separators approach and the multi scale local separators. 248 The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence 249 of floating point values - one for each node. We can have as many columns as needed 250 for the front separator computation. We can think of this as a coloring 251 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 252 of the nodes or some other function that indicates something about the structure of the 253 graph. The function returns a new graph which is the 254 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 255 skel = Graph() 256 mapping = IntVector() 257 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 258 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 259 print("N_col:", N_col) 260 pos = g.positions() 261 lib_py_gel.graph_combined_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 262 return skel
7class Graph: 8 """ This class is for representing graphs embedded in 3D. The class does not in 9 itself come with many features: it contains methods for creating, accessing, and 10 housekeeping. When vertices are used as parameters in the functions below, we usually 11 use the parameter name n (for node). n is simply an index (i.e. an integer) that 12 refers to a node (aka vertex).""" 13 def __init__(self,orig=None): 14 if orig == None: 15 self.obj = lib_py_gel.Graph_new() 16 else: 17 self.obj = lib_py_gel.Graph_copy(orig.obj) 18 def __del__(self): 19 lib_py_gel.Graph_delete(self.obj) 20 def clear(self): 21 """ Clear the graph. """ 22 lib_py_gel.Graph_clear(self.obj) 23 def cleanup(self): 24 """ Cleanup reorders the graph nodes such that there is no 25 gap in the index range. """ 26 lib_py_gel.Graph_cleanup(self.obj) 27 def nodes(self): 28 """ Get all nodes as an iterable range """ 29 nodes = IntVector() 30 lib_py_gel.Graph_nodes(self.obj, nodes.obj) 31 return nodes 32 def neighbors(self, n, mode='n'): 33 """ Get the neighbors of node n. The final argument is either 'n' or 'e'. If it is 'n' 34 the function returns all neighboring nodes, and if it is 'e' it returns incident edges.""" 35 nbors = IntVector() 36 lib_py_gel.Graph_neighbors(self.obj, n, nbors.obj, ct.c_char(mode.encode('ascii'))) 37 return nbors 38 def positions(self): 39 """ Get the vertex positions by reference. You can assign to the 40 positions. """ 41 pos = ct.POINTER(ct.c_double)() 42 n = lib_py_gel.Graph_positions(self.obj, ct.byref(pos)) 43 return np.ctypeslib.as_array(pos,(n,3)) 44 def average_edge_length(self): 45 """ Returns the average edge length. """ 46 ael = lib_py_gel.Graph_average_edge_length(self.obj) 47 return ael 48 def add_node(self, p): 49 """ Adds node with position p to the graph and returns the 50 index of the new node. """ 51 return lib_py_gel.Graph_add_node(self.obj, np.array(p)) 52 def remove_node(self, n): 53 """ Removes the node n passed as argument. This does not change 54 any indices of other nodes, but n is then invalid. """ 55 lib_py_gel.Graph_remove_node(self.obj, n) 56 def node_in_use(self, n): 57 """ Checks if n is in_use. This function returns false both 58 if n has been removed and if n is an index outside the range of 59 indices that are used. """ 60 return lib_py_gel.Graph_node_in_use(self.obj, n) 61 def connect_nodes(self, n0, n1): 62 """ Creates a new edge connecting nodes n0 and n1. The index of 63 the new edge is returned. """ 64 return lib_py_gel.Graph_connect_nodes(self.obj, n0, n1) 65 def disconnect_nodes(self, n0, n1): 66 """ Disconect nodes n0 and n1""" 67 lib_py_gel.Graph_disconnect_nodes(self.obj, n0, n1) 68 def merge_nodes(self, n0, n1, avg_pos): 69 """ Merge nodes n0 and n1. avg_pos indicates if you want the position to be the average. """ 70 lib_py_gel.Graph_merge_nodes(self.obj, n0, n1, avg_pos)
This class is for representing graphs embedded in 3D. The class does not in itself come with many features: it contains methods for creating, accessing, and housekeeping. When vertices are used as parameters in the functions below, we usually use the parameter name n (for node). n is simply an index (i.e. an integer) that refers to a node (aka vertex).
23 def cleanup(self): 24 """ Cleanup reorders the graph nodes such that there is no 25 gap in the index range. """ 26 lib_py_gel.Graph_cleanup(self.obj)
Cleanup reorders the graph nodes such that there is no gap in the index range.
27 def nodes(self): 28 """ Get all nodes as an iterable range """ 29 nodes = IntVector() 30 lib_py_gel.Graph_nodes(self.obj, nodes.obj) 31 return nodes
Get all nodes as an iterable range
32 def neighbors(self, n, mode='n'): 33 """ Get the neighbors of node n. The final argument is either 'n' or 'e'. If it is 'n' 34 the function returns all neighboring nodes, and if it is 'e' it returns incident edges.""" 35 nbors = IntVector() 36 lib_py_gel.Graph_neighbors(self.obj, n, nbors.obj, ct.c_char(mode.encode('ascii'))) 37 return nbors
Get the neighbors of node n. The final argument is either 'n' or 'e'. If it is 'n' the function returns all neighboring nodes, and if it is 'e' it returns incident edges.
38 def positions(self): 39 """ Get the vertex positions by reference. You can assign to the 40 positions. """ 41 pos = ct.POINTER(ct.c_double)() 42 n = lib_py_gel.Graph_positions(self.obj, ct.byref(pos)) 43 return np.ctypeslib.as_array(pos,(n,3))
Get the vertex positions by reference. You can assign to the positions.
44 def average_edge_length(self): 45 """ Returns the average edge length. """ 46 ael = lib_py_gel.Graph_average_edge_length(self.obj) 47 return ael
Returns the average edge length.
48 def add_node(self, p): 49 """ Adds node with position p to the graph and returns the 50 index of the new node. """ 51 return lib_py_gel.Graph_add_node(self.obj, np.array(p))
Adds node with position p to the graph and returns the index of the new node.
52 def remove_node(self, n): 53 """ Removes the node n passed as argument. This does not change 54 any indices of other nodes, but n is then invalid. """ 55 lib_py_gel.Graph_remove_node(self.obj, n)
Removes the node n passed as argument. This does not change any indices of other nodes, but n is then invalid.
56 def node_in_use(self, n): 57 """ Checks if n is in_use. This function returns false both 58 if n has been removed and if n is an index outside the range of 59 indices that are used. """ 60 return lib_py_gel.Graph_node_in_use(self.obj, n)
Checks if n is in_use. This function returns false both if n has been removed and if n is an index outside the range of indices that are used.
61 def connect_nodes(self, n0, n1): 62 """ Creates a new edge connecting nodes n0 and n1. The index of 63 the new edge is returned. """ 64 return lib_py_gel.Graph_connect_nodes(self.obj, n0, n1)
Creates a new edge connecting nodes n0 and n1. The index of the new edge is returned.
65 def disconnect_nodes(self, n0, n1): 66 """ Disconect nodes n0 and n1""" 67 lib_py_gel.Graph_disconnect_nodes(self.obj, n0, n1)
Disconect nodes n0 and n1
68 def merge_nodes(self, n0, n1, avg_pos): 69 """ Merge nodes n0 and n1. avg_pos indicates if you want the position to be the average. """ 70 lib_py_gel.Graph_merge_nodes(self.obj, n0, n1, avg_pos)
Merge nodes n0 and n1. avg_pos indicates if you want the position to be the average.
73def from_mesh(m): 74 """ Creates a graph from a mesh. The argument, m, is the input mesh, 75 and the function returns a graph with the same vertices and edges 76 as m.""" 77 g = Graph() 78 lib_py_gel.graph_from_mesh(m.obj, g.obj) 79 return g
Creates a graph from a mesh. The argument, m, is the input mesh, and the function returns a graph with the same vertices and edges as m.
81def load(fn): 82 """ Load a graph from a file. The argument, fn, is the filename which 83 is in a special format similar to Wavefront obj. The loaded graph is 84 returned by the function - or None if loading failed. """ 85 s = ct.c_char_p(fn.encode('utf-8')) 86 g = Graph() 87 if lib_py_gel.graph_load(g.obj, s): 88 return g 89 return None
Load a graph from a file. The argument, fn, is the filename which is in a special format similar to Wavefront obj. The loaded graph is returned by the function - or None if loading failed.
91def save(fn, g): 92 """ Save graph to a file. The first argument, fn, is the file name, 93 and g is the graph. This function returns True if saving happened and 94 False otherwise. """ 95 s = ct.c_char_p(fn.encode('utf-8')) 96 return lib_py_gel.graph_save(g.obj, s)
Save graph to a file. The first argument, fn, is the file name, and g is the graph. This function returns True if saving happened and False otherwise.
98def to_mesh_cyl(g, fudge=0.0): 99 """ Creates a Manifold mesh from the graph. The first argument, g, is the 100 graph we want converted, and fudge is a constant that is used to increase the radius 101 of every node. This is useful if the radii are 0. """ 102 m = hmesh.Manifold() 103 lib_py_gel.graph_to_mesh_cyl(g.obj, m.obj, fudge) 104 return m
Creates a Manifold mesh from the graph. The first argument, g, is the graph we want converted, and fudge is a constant that is used to increase the radius of every node. This is useful if the radii are 0.
106def to_mesh_iso(g, fudge=0.0, res=256): 107 """ Creates a Manifold mesh from the graph. The first argument, g, is the 108 graph we want converted, and fudge is a constant that is used to increase the radius 109 of every node. This is useful if the radii are 0. """ 110 m = hmesh.Manifold() 111 lib_py_gel.graph_to_mesh_iso(g.obj, m.obj, fudge, res) 112 return m
Creates a Manifold mesh from the graph. The first argument, g, is the graph we want converted, and fudge is a constant that is used to increase the radius of every node. This is useful if the radii are 0.
115def smooth(g, iter=1, alpha=1.0): 116 """ Simple Laplacian smoothing of a graph. The first argument is the Graph, g, iter 117 is the number of iterations, and alpha is the weight. If the weight is high, 118 each iteration causes a lot of smoothing, and a high number of iterations 119 ensures that the effect of smoothing diffuses throughout the graph, i.e. that the 120 effect is more global than local. """ 121 lib_py_gel.graph_smooth(g.obj, iter, alpha)
Simple Laplacian smoothing of a graph. The first argument is the Graph, g, iter is the number of iterations, and alpha is the weight. If the weight is high, each iteration causes a lot of smoothing, and a high number of iterations ensures that the effect of smoothing diffuses throughout the graph, i.e. that the effect is more global than local.
123def edge_contract(g, dist_thresh): 124 """ Simplifies a graph by contracting edges. The first argument, g, is the graph, 125 and only edges shorter than dist_thresh are contracted. When an edge is contracted 126 the merged vertices are moved to the average of their former positions. Thus, 127 the ordering in which contractions are carried out matters. Hence, edges are 128 contracted in the order of increasing length and edges are only considered if 129 neither end point is the result of a contraction, but the process is then repeated 130 until no more contractions are possible. Returns total number of contractions. """ 131 return lib_py_gel.graph_edge_contract(g.obj, dist_thresh)
Simplifies a graph by contracting edges. The first argument, g, is the graph, and only edges shorter than dist_thresh are contracted. When an edge is contracted the merged vertices are moved to the average of their former positions. Thus, the ordering in which contractions are carried out matters. Hence, edges are contracted in the order of increasing length and edges are only considered if neither end point is the result of a contraction, but the process is then repeated until no more contractions are possible. Returns total number of contractions.
133def prune(g): 134 """ Prune leaves of a graph. The graph, g, is passed as the argument. This function 135 removes leaf nodes (valency 1) whose only neighbour has valency > 2. In practice 136 such isolated leaves are frequently spurious if the graph is a skeleton. Does not 137 return a value. """ 138 lib_py_gel.graph_prune(g.obj)
Prune leaves of a graph. The graph, g, is passed as the argument. This function removes leaf nodes (valency 1) whose only neighbour has valency > 2. In practice such isolated leaves are frequently spurious if the graph is a skeleton. Does not return a value.
140def saturate(g, hops=2, dist_frac=1.001, rad=1e300): 141 """ Saturate the graph with edges. This is not a complete saturation. Edges are 142 introduced between a vertex and other vertices that are reachable in hops steps, i.e. 143 hops-order neighbors. dist_frac and rad are parameters used to govern the precise 144 behaviour. Two nodes are only connected if their distance is less than rad and if 145 their distance is less than dist_frac times the length of the path along existing 146 edges in the graph. If dist_frac is at approximately 1 and rad is enormous, these 147 two parameters make no difference. """ 148 lib_py_gel.graph_saturate(g.obj, hops, dist_frac, rad)
Saturate the graph with edges. This is not a complete saturation. Edges are introduced between a vertex and other vertices that are reachable in hops steps, i.e. hops-order neighbors. dist_frac and rad are parameters used to govern the precise behaviour. Two nodes are only connected if their distance is less than rad and if their distance is less than dist_frac times the length of the path along existing edges in the graph. If dist_frac is at approximately 1 and rad is enormous, these two parameters make no difference.
150def LS_skeleton(g, sampling=True): 151 """ Skeletonize a graph using the local separators approach. The first argument, 152 g, is the graph, and, sampling indicates whether we try to use all vertices 153 (False) as starting points for finding separators or just a sampling (True). 154 The function returns a new graph which is the skeleton of the input graph. """ 155 skel = Graph() 156 mapping = IntVector() 157 lib_py_gel.graph_LS_skeleton(g.obj, skel.obj, mapping.obj, sampling) 158 return skel
Skeletonize a graph using the local separators approach. The first argument, g, is the graph, and, sampling indicates whether we try to use all vertices (False) as starting points for finding separators or just a sampling (True). The function returns a new graph which is the skeleton of the input graph.
160def LS_skeleton_and_map(g, sampling=True): 161 """ Skeletonize a graph using the local separators approach. The first argument, 162 g, is the graph, and, sampling indicates whether we try to use all vertices 163 (False) as starting points for finding separators or just a sampling (True). 164 The function returns a tuple containing a new graph which is the skeleton of 165 the input graph and a map from the graph nodes to the skeletal nodes. """ 166 skel = Graph() 167 mapping = IntVector() 168 lib_py_gel.graph_LS_skeleton(g.obj, skel.obj, mapping.obj, sampling) 169 return skel, mapping
Skeletonize a graph using the local separators approach. The first argument, g, is the graph, and, sampling indicates whether we try to use all vertices (False) as starting points for finding separators or just a sampling (True). The function returns a tuple containing a new graph which is the skeleton of the input graph and a map from the graph nodes to the skeletal nodes.
171def MSLS_skeleton(g, grow_thresh=64): 172 """ Skeletonize a graph using the multi-scale local separators approach. The first argument, 173 g, is the graph, and, sampling indicates whether we try to use all vertices 174 (False) as starting points for finding separators or just a sampling (True). 175 The function returns a new graph which is the skeleton of the input graph. """ 176 skel = Graph() 177 mapping = IntVector() 178 lib_py_gel.graph_MSLS_skeleton(g.obj, skel.obj, mapping.obj, grow_thresh) 179 return skel
Skeletonize a graph using the multi-scale local separators approach. The first argument, g, is the graph, and, sampling indicates whether we try to use all vertices (False) as starting points for finding separators or just a sampling (True). The function returns a new graph which is the skeleton of the input graph.
181def MSLS_skeleton_and_map(g, grow_thresh=64): 182 """ Skeletonize a graph using the multi-scale local separators approach. The first argument, 183 g, is the graph, and, sampling indicates whether we try to use all vertices 184 (False) as starting points for finding separators or just a sampling (True). 185 The function returns a tuple containing a new graph which is the skeleton of 186 the input graph and a map from the graph nodes to the skeletal nodes. """ 187 skel = Graph() 188 mapping = IntVector() 189 lib_py_gel.graph_MSLS_skeleton(g.obj, skel.obj, mapping.obj, grow_thresh) 190 return skel, mapping
Skeletonize a graph using the multi-scale local separators approach. The first argument, g, is the graph, and, sampling indicates whether we try to use all vertices (False) as starting points for finding separators or just a sampling (True). The function returns a tuple containing a new graph which is the skeleton of the input graph and a map from the graph nodes to the skeletal nodes.
193def front_skeleton_and_map(g, colors, intervals=100): 194 """ Skeletonize a graph using the front separators approach. The first argument, 195 g, is the graph, and, colors is an nD array where each column contains a sequence 196 of floating point values - one for each node. We can have as many columns as needed 197 for the front separator computation. We can think of this as a coloring 198 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 199 of the nodes or some other function that indicates something about the structure of the 200 graph. The function returns a tuple containing a new graph which is the 201 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 202 skel = Graph() 203 mapping = IntVector() 204 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 205 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 206 print("N_col:", N_col) 207 pos = g.positions() 208 lib_py_gel.graph_front_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 209 return skel, mapping
Skeletonize a graph using the front separators approach. The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence of floating point values - one for each node. We can have as many columns as needed for the front separator computation. We can think of this as a coloring of the nodes, hence the name. In practice, a coloring might just be the x-coordinate of the nodes or some other function that indicates something about the structure of the graph. The function returns a tuple containing a new graph which is the skeleton of the input graph and a map from the graph nodes to the skeletal nodes.
211def front_skeleton(g, colors, intervals=100): 212 """ Skeletonize a graph using the front separators approach. The first argument, 213 g, is the graph, and, colors is a nD array where each column contains a sequence 214 of floating point values - one for each node. We can have as many columns as needed 215 for the front separator computation. We can think of this as a coloring 216 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 217 of the nodes or some other function that indicates something about the structure of the 218 graph. The function returns a tuple containing a new graph which is the 219 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 220 skel = Graph() 221 mapping = IntVector() 222 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 223 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 224 print("N_col:", N_col) 225 pos = g.positions() 226 lib_py_gel.graph_front_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 227 return skel
Skeletonize a graph using the front separators approach. The first argument, g, is the graph, and, colors is a nD array where each column contains a sequence of floating point values - one for each node. We can have as many columns as needed for the front separator computation. We can think of this as a coloring of the nodes, hence the name. In practice, a coloring might just be the x-coordinate of the nodes or some other function that indicates something about the structure of the graph. The function returns a tuple containing a new graph which is the skeleton of the input graph and a map from the graph nodes to the skeletal nodes.
229def combined_skeleton_and_map(g, colors, intervals=100): 230 """ Skeletonize a graph using both the front separators approach and the multi scale local separators. 231 The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence 232 of floating point values - one for each node. We can have as many columns as needed 233 for the front separator computation. We can think of this as a coloring 234 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 235 of the nodes or some other function that indicates something about the structure of the 236 graph. The function returns a tuple containing a new graph which is the 237 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 238 skel = Graph() 239 mapping = IntVector() 240 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 241 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 242 print("N_col:", N_col) 243 pos = g.positions() 244 lib_py_gel.graph_combined_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 245 return skel, mapping
Skeletonize a graph using both the front separators approach and the multi scale local separators. The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence of floating point values - one for each node. We can have as many columns as needed for the front separator computation. We can think of this as a coloring of the nodes, hence the name. In practice, a coloring might just be the x-coordinate of the nodes or some other function that indicates something about the structure of the graph. The function returns a tuple containing a new graph which is the skeleton of the input graph and a map from the graph nodes to the skeletal nodes.
247def combined_skeleton(g, colors, intervals=100): 248 """ Skeletonize a graph using both the front separators approach and the multi scale local separators. 249 The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence 250 of floating point values - one for each node. We can have as many columns as needed 251 for the front separator computation. We can think of this as a coloring 252 of the nodes, hence the name. In practice, a coloring might just be the x-coordinate 253 of the nodes or some other function that indicates something about the structure of the 254 graph. The function returns a new graph which is the 255 skeleton of the input graph and a map from the graph nodes to the skeletal nodes. """ 256 skel = Graph() 257 mapping = IntVector() 258 colors_flat = np.asarray(colors, dtype=ct.c_double, order='C') 259 N_col = 1 if len(colors_flat.shape)==1 else colors_flat.shape[1] 260 print("N_col:", N_col) 261 pos = g.positions() 262 lib_py_gel.graph_combined_skeleton(g.obj, skel.obj, mapping.obj, N_col, colors_flat.ctypes.data_as(ct.POINTER(ct.c_double)), intervals) 263 return skel
Skeletonize a graph using both the front separators approach and the multi scale local separators. The first argument, g, is the graph, and, colors is an nD array where each column contains a sequence of floating point values - one for each node. We can have as many columns as needed for the front separator computation. We can think of this as a coloring of the nodes, hence the name. In practice, a coloring might just be the x-coordinate of the nodes or some other function that indicates something about the structure of the graph. The function returns a new graph which is the skeleton of the input graph and a map from the graph nodes to the skeletal nodes.