Commit 8d96a467dc890b7403b00d93e52bce64c3fbbdbe

Authored by David Mayerich
1 parent e105516a

started converting NETWORK into a python class

Showing 1 changed file with 262 additions and 263 deletions   Show diff stats
@@ -39,11 +39,12 @@ class Fiber: @@ -39,11 +39,12 @@ class Fiber:
39 self.points = [] 39 self.points = []
40 self.radii = [] 40 self.radii = []
41 41
42 - def __init__ (self, p1, p2, pois, rads):  
43 - self.v0 = p1  
44 - self.v1 = p2  
45 - self.points = pois  
46 - self.radii = rads 42 + #NOTE: there is no function overloading in Python
  43 +# def __init__ (self, p1, p2, pois, rads):
  44 +# self.v0 = p1
  45 +# self.v1 = p2
  46 +# self.points = pois
  47 +# self.radii = rads
47 48
48 ''' 49 '''
49 return the length of the fiber. 50 return the length of the fiber.
@@ -76,289 +77,287 @@ class Fiber: @@ -76,289 +77,287 @@ class Fiber:
76 77
77 #print(volume) 78 #print(volume)
78 return volume 79 return volume
79 -  
80 -'''  
81 - Writes the header given and open file descripion, number of verticies and number of edges.  
82 -'''  
83 -def writeHeader(open_file, numVerts, numEdges):  
84 - txt = "nwtFileFormat fileid(14B), desc(58B), #vertices(4B), #edges(4B): bindata"  
85 - b = bytearray()  
86 - b.extend(txt.encode())  
87 - open_file.write(b)  
88 - open_file.write(struct.pack('i', numVerts))  
89 - open_file.write(struct.pack('i', numEdges))  
90 80
91 -  
92 -'''  
93 - Writes a single vertex to a file.  
94 -'''  
95 -def writeVertex(open_file, vertex):  
96 - open_file.write(struct.pack('<f',vertex.p[0]))  
97 - open_file.write(struct.pack('<f',vertex.p[1]))  
98 - open_file.write(struct.pack('<f',vertex.p[2]))  
99 - open_file.write(struct.pack('i', len(vertex.o)))  
100 - open_file.write(struct.pack('i', len(vertex.i)))  
101 - for j in range(len(vertex.o)):  
102 - open_file.write(struct.pack('i',vertex.o[j]))  
103 -  
104 - for j in range(len(vertex.i)):  
105 - open_file.write(struct.pack('i', vertex.i[j]))  
106 -  
107 - return  
108 -  
109 -'''  
110 - Writes a single fiber to a file.  
111 -'''  
112 -def writeFiber(open_file, edge):  
113 - open_file.write(struct.pack('i',edge.v0))  
114 - open_file.write(struct.pack('i',edge.v1))  
115 - open_file.write(struct.pack('i',len(edge.points)))  
116 - for j in range(len(edge.points)):  
117 - open_file.write(struct.pack('<f', edge.points[j][0]))  
118 - open_file.write(struct.pack('<f', edge.points[j][1]))  
119 - open_file.write(struct.pack('<f', edge.points[j][2]))  
120 - open_file.write(struct.pack('<f', edge.radii[j])) 81 +class NWT:
  82 +
  83 + '''
  84 + Writes the header given and open file descripion, number of verticies and number of edges.
  85 + '''
  86 + def writeHeader(self, open_file, numVerts, numEdges):
  87 + txt = "nwtFileFormat fileid(14B), desc(58B), #vertices(4B), #edges(4B): bindata"
  88 + b = bytearray()
  89 + b.extend(txt.encode())
  90 + open_file.write(b)
  91 + open_file.write(struct.pack('i', numVerts))
  92 + open_file.write(struct.pack('i', numEdges))
121 93
122 - return  
123 -  
124 -'''  
125 - Writes the entire network to a file in str given the vertices array and the edges array.  
126 -'''  
127 -def exportNWT(str, vertices, edges):  
128 - with open(str, "wb") as file:  
129 - writeHeader(file, len(vertices), len(edges))  
130 - for i in range(len(vertices)):  
131 - writeVertex(file, vertices[i]) 94 +
  95 + '''
  96 + Writes a single vertex to a file.
  97 + '''
  98 + def writeVertex(self, open_file, vertex):
  99 + open_file.write(struct.pack('<f',vertex.p[0]))
  100 + open_file.write(struct.pack('<f',vertex.p[1]))
  101 + open_file.write(struct.pack('<f',vertex.p[2]))
  102 + open_file.write(struct.pack('i', len(vertex.o)))
  103 + open_file.write(struct.pack('i', len(vertex.i)))
  104 + for j in range(len(vertex.o)):
  105 + open_file.write(struct.pack('i',vertex.o[j]))
132 106
133 - for i in range(len(edges)):  
134 - writeFiber(file, edges[i]) 107 + for j in range(len(vertex.i)):
  108 + open_file.write(struct.pack('i', vertex.i[j]))
135 109
136 - return  
137 -  
138 -  
139 -'''  
140 - Reads a single vertex from an open file and returns a node Object.  
141 -'''  
142 -def readVertex(open_file):  
143 - points = np.tile(0., 3)  
144 - bytes = open_file.read(4)  
145 - points[0] = struct.unpack('f', bytes)[0]  
146 - bytes = open_file.read(4)  
147 - points[1] = struct.unpack('f', bytes)[0]  
148 - bytes = open_file.read(4)  
149 - points[2] = struct.unpack('f', bytes)[0]  
150 - bytes = open_file.read(4) 110 + return
151 111
152 - numO = int.from_bytes(bytes, byteorder='little')  
153 - outgoing = np.tile(0, numO)  
154 - bts = open_file.read(4)  
155 - numI = int.from_bytes(bts, byteorder='little')  
156 - incoming = np.tile(0, numI)  
157 - for j in range(numO):  
158 - bytes = open_file.read(4)  
159 - outgoing[j] = int.from_bytes(bytes, byteorder='little')  
160 -  
161 - for j in range(numI):  
162 - bytes = open_file.read(4)  
163 - incoming[j] = int.from_bytes(bytes, byteorder='little')  
164 -  
165 - node = Node(points, outgoing, incoming)  
166 - return node 112 + '''
  113 + Writes a single fiber to a file.
  114 + '''
  115 + def writeFiber(self, open_file, edge):
  116 + open_file.write(struct.pack('i',edge.v0))
  117 + open_file.write(struct.pack('i',edge.v1))
  118 + open_file.write(struct.pack('i',len(edge.points)))
  119 + for j in range(len(edge.points)):
  120 + open_file.write(struct.pack('<f', edge.points[j][0]))
  121 + open_file.write(struct.pack('<f', edge.points[j][1]))
  122 + open_file.write(struct.pack('<f', edge.points[j][2]))
  123 + open_file.write(struct.pack('<f', edge.radii[j]))
  124 +
  125 + return
167 126
  127 + '''
  128 + Writes the entire network to a file in str given the vertices array and the edges array.
  129 + '''
  130 + def exportNWT(self, str, vertices, edges):
  131 + with open(str, "wb") as file:
  132 + self.writeHeader(file, len(vertices), len(edges))
  133 + for i in range(len(vertices)):
  134 + self.writeVertex(file, vertices[i])
  135 +
  136 + for i in range(len(edges)):
  137 + self.writeFiber(file, edges[i])
  138 +
  139 + return
168 140
169 -'''  
170 - Reads a single fiber from an open file and returns a Fiber object .  
171 -'''  
172 -def readFiber(open_file):  
173 - bytes = open_file.read(4)  
174 - vtx0 = int.from_bytes(bytes, byteorder = 'little')  
175 - bytes = open_file.read(4)  
176 - vtx1 = int.from_bytes(bytes, byteorder = 'little')  
177 - bytes = open_file.read(4)  
178 - numVerts = int.from_bytes(bytes, byteorder = 'little')  
179 - pts = []  
180 - rads = []  
181 141
182 - for j in range(numVerts):  
183 - point = np.tile(0., 3) 142 + '''
  143 + Reads a single vertex from an open file and returns a node Object.
  144 + '''
  145 + def readVertex(self, open_file):
  146 + points = np.tile(0., 3)
184 bytes = open_file.read(4) 147 bytes = open_file.read(4)
185 - point[0] = struct.unpack('f', bytes)[0] 148 + points[0] = struct.unpack('f', bytes)[0]
186 bytes = open_file.read(4) 149 bytes = open_file.read(4)
187 - point[1] = struct.unpack('f', bytes)[0] 150 + points[1] = struct.unpack('f', bytes)[0]
188 bytes = open_file.read(4) 151 bytes = open_file.read(4)
189 - point[2] = struct.unpack('f', bytes)[0] 152 + points[2] = struct.unpack('f', bytes)[0]
190 bytes = open_file.read(4) 153 bytes = open_file.read(4)
191 - radius = struct.unpack('f', bytes)[0]  
192 - pts.append(point)  
193 - rads.append(radius)  
194 -  
195 - F = Fiber(vtx0, vtx1, pts, rads)  
196 154
197 - return F  
198 -  
199 -'''  
200 - Imports a NWT file at location str.  
201 - Returns a list of Nodes objects and a list of Fiber objects.  
202 -'''  
203 -def importNWT(str):  
204 - with open(str, "rb") as file:  
205 - header = file.read(72)  
206 - bytes = file.read(4)  
207 - numVertex = int.from_bytes(bytes, byteorder='little')  
208 - bytes = file.read(4)  
209 - numEdges = int.from_bytes(bytes, byteorder='little')  
210 -  
211 - nodeList = []  
212 - fiberList = []  
213 - for i in range(numVertex):  
214 - node = readVertex(file)  
215 - nodeList.append(node)  
216 -  
217 - for i in range(numEdges):  
218 - edge = readFiber(file)  
219 - fiberList.append(edge) 155 + numO = int.from_bytes(bytes, byteorder='little')
  156 + outgoing = np.tile(0, numO)
  157 + bts = open_file.read(4)
  158 + numI = int.from_bytes(bts, byteorder='little')
  159 + incoming = np.tile(0, numI)
  160 + for j in range(numO):
  161 + bytes = open_file.read(4)
  162 + outgoing[j] = int.from_bytes(bytes, byteorder='little')
  163 +
  164 + for j in range(numI):
  165 + bytes = open_file.read(4)
  166 + incoming[j] = int.from_bytes(bytes, byteorder='little')
  167 +
  168 + node = Node(points, outgoing, incoming)
  169 + return node
220 170
221 - #exportNWT("/home/pavel/Documents/Python/NetLayout/from_python_seg.nwt", nodeList, fiberList)  
222 - print(str)  
223 - return nodeList, fiberList;  
224 -  
225 -'''  
226 -Creates a graph from a list of nodes and a list of edges.  
227 -Uses edge length as weight.  
228 -Returns a NetworkX Object.  
229 -'''  
230 -  
231 -def createLengthGraph(nodeList, edgeList):  
232 - G = nx.Graph()  
233 - for i in range(len(nodeList)):  
234 - G.add_node(i, p=V[i].p)  
235 - for i in range(len(edgeList)):  
236 - G.add_edge(edgeList[i].v0, edgeList[i].v1, weight = E[i].length())  
237 171
238 - return G  
239 -  
240 -'''  
241 -Creates a graph from a list of nodes and a list of edges.  
242 -Uses edge turtuosity as weight.  
243 -Returns a NetworkX Object.  
244 -'''  
245 -def createTortuosityGraph(nodeList, edgeList):  
246 - G = nx.Graph()  
247 - for i in range(len(nodeList)):  
248 - G.add_node(i, p=V[i].p)  
249 - for i in range(len(edgeList)):  
250 - G.add_edge(edgeList[i].v0, edgeList[i].v1, weight = E[i].turtuosity()) 172 + '''
  173 + Reads a single fiber from an open file and returns a Fiber object .
  174 + '''
  175 + def readFiber(self, open_file):
  176 + bytes = open_file.read(4)
  177 + vtx0 = int.from_bytes(bytes, byteorder = 'little')
  178 + bytes = open_file.read(4)
  179 + vtx1 = int.from_bytes(bytes, byteorder = 'little')
  180 + bytes = open_file.read(4)
  181 + numVerts = int.from_bytes(bytes, byteorder = 'little')
  182 + pts = []
  183 + rads = []
251 184
252 - return G  
253 - 185 + for j in range(numVerts):
  186 + point = np.tile(0., 3)
  187 + bytes = open_file.read(4)
  188 + point[0] = struct.unpack('f', bytes)[0]
  189 + bytes = open_file.read(4)
  190 + point[1] = struct.unpack('f', bytes)[0]
  191 + bytes = open_file.read(4)
  192 + point[2] = struct.unpack('f', bytes)[0]
  193 + bytes = open_file.read(4)
  194 + radius = struct.unpack('f', bytes)[0]
  195 + pts.append(point)
  196 + rads.append(radius)
  197 +
  198 + F = Fiber(vtx0, vtx1, pts, rads)
  199 +
  200 + return F
254 201
255 -'''  
256 -Creates a graph from a list of nodes and a list of edges.  
257 -Uses edge volume as weight.  
258 -Returns a NetworkX Object.  
259 -'''  
260 -def createVolumeGraph(nodeList, edgeList):  
261 - G = nx.Graph()  
262 - for i in range(len(nodeList)):  
263 - G.add_node(i, p=V[i].p)  
264 - for i in range(len(edgeList)):  
265 - G.add_edge(edgeList[i].v0, edgeList[i].v1, weight = E[i].volume())  
266 -  
267 - return G  
268 -'''  
269 -Returns the positions dictionary for the Circular layout.  
270 -'''  
271 -def getCircularLayout(graph, dim, radius):  
272 - return nx.circular_layout(graph, dim, radius)  
273 -  
274 -'''  
275 -Return the positions dictionary for the Spring layout.  
276 -'''  
277 -def getSpringLayout(graph, pos, iterations, scale):  
278 - return nx.spring_layout(graph, 2, None, pos, iterations, 'weight', scale, None)  
279 -  
280 -'''  
281 -Draws the graph.  
282 -'''  
283 -def drawGraph(graph, pos):  
284 - nx.draw(graph, pos)  
285 - return  
286 -  
287 -def aabb(nodeList, edgeList):  
288 -  
289 - lower = nodeList[0].p.copy()  
290 - upper = lower.copy()  
291 - for i in nodeList:  
292 - for c in range(len(lower)):  
293 - if lower[c] > i.p[c]:  
294 - lower[c] = i.p[c]  
295 - if upper[c] < i.p[c]:  
296 - upper[c] = i.p[c]  
297 - return lower, upper 202 + '''
  203 + Imports a NWT file at location str.
  204 + Returns a list of Nodes objects and a list of Fiber objects.
  205 + '''
298 206
299 -#calculate the distance field at a given resolution  
300 -# R (triple) resolution along each dimension  
301 -def distancefield(nodeList, edgeList, R=(100, 100, 100)): 207 +class Network:
302 208
303 - #get a list of all node positions in the network  
304 - P = []  
305 - for e in edgeList:  
306 - for p in e.points:  
307 - P.append(p) 209 + def __init__(self, str):
  210 + with open(str, "rb") as file:
  211 + header = file.read(72)
  212 + bytes = file.read(4)
  213 + numVertex = int.from_bytes(bytes, byteorder='little')
  214 + bytes = file.read(4)
  215 + numEdges = int.from_bytes(bytes, byteorder='little')
308 216
309 - #turn that list into a Numpy array so that we can create a KD tree  
310 - P = np.array(P)  
311 -  
312 - #generate a KD-Tree out of the network point array  
313 - tree = sp.spatial.cKDTree(P) 217 + self.N = []
  218 + self.F = []
  219 + for i in range(numVertex):
  220 + node = NWT.readVertex(file)
  221 + self.N.append(node)
314 222
315 - plt.scatter(P[:, 0], P[:, 1]) 223 + for i in range(numEdges):
  224 + edge = NWT.readFiber(file)
  225 + self.F.append(edge)
316 226
317 - #specify the resolution of the ouput grid  
318 - R = (200, 200, 200) 227 + '''
  228 + Creates a graph from a list of nodes and a list of edges.
  229 + Uses edge length as weight.
  230 + Returns a NetworkX Object.
  231 + '''
  232 +# def createLengthGraph(self):
  233 +# G = nx.Graph()
  234 +# for i in range(len(self.nodeList)):
  235 +# G.add_node(i, p=V[i].p)
  236 +# for i in range(len(self.edgeList)):
  237 +# G.add_edge(self.edgeList[i].v0, self.edgeList[i].v1, weight = E[i].length())
  238 +#
  239 +# return G
  240 +# '''
  241 +# Creates a graph from a list of nodes and a list of edges.
  242 +# Uses edge turtuosity as weight.
  243 +# Returns a NetworkX Object.
  244 +# '''
  245 +# def createTortuosityGraph(nodeList, edgeList):
  246 +# G = nx.Graph()
  247 +# for i in range(len(nodeList)):
  248 +# G.add_node(i, p=V[i].p)
  249 +# for i in range(len(edgeList)):
  250 +# G.add_edge(edgeList[i].v0, edgeList[i].v1, weight = E[i].turtuosity())
  251 +#
  252 +# return G
319 253
320 - #generate a meshgrid of the appropriate size and resolution to surround the network  
321 - lower, upper = aabb(nodeList, edgeList) #get the space occupied by the network  
322 - x = np.linspace(lower[0], upper[0], R[0]) #get the grid points for uniform sampling of this space  
323 - y = np.linspace(lower[1], upper[1], R[1])  
324 - z = np.linspace(lower[2], upper[2], R[2])  
325 - X, Y, Z = np.meshgrid(x, y, z)  
326 - #Z = 150 * numpy.ones(X.shape) 254 +# '''
  255 +# Creates a graph from a list of nodes and a list of edges.
  256 +# Uses edge volume as weight.
  257 +# Returns a NetworkX Object.
  258 +# '''
  259 +# def createVolumeGraph(nodeList, edgeList):
  260 +# G = nx.Graph()
  261 +# for i in range(len(nodeList)):
  262 +# G.add_node(i, p=V[i].p)
  263 +# for i in range(len(edgeList)):
  264 +# G.add_edge(edgeList[i].v0, edgeList[i].v1, weight = E[i].volume())
  265 +#
  266 +# return G
  267 +#'''
  268 +#Returns the positions dictionary for the Circular layout.
  269 +#'''
  270 +#def getCircularLayout(graph, dim, radius):
  271 +# return nx.circular_layout(graph, dim, radius)
  272 +#
  273 +#'''
  274 +#Return the positions dictionary for the Spring layout.
  275 +#'''
  276 +#def getSpringLayout(graph, pos, iterations, scale):
  277 +# return nx.spring_layout(graph, 2, None, pos, iterations, 'weight', scale, None)
  278 +#
  279 +#'''
  280 +#Draws the graph.
  281 +#'''
  282 +#def drawGraph(graph, pos):
  283 +# nx.draw(graph, pos)
  284 +# return
  285 +
  286 + def aabb(self):
327 287
  288 + lower = self.N[0].p.copy()
  289 + upper = lower.copy()
  290 + for i in self.nodeList:
  291 + for c in range(len(lower)):
  292 + if lower[c] > i.p[c]:
  293 + lower[c] = i.p[c]
  294 + if upper[c] < i.p[c]:
  295 + upper[c] = i.p[c]
  296 + return lower, upper
328 297
329 - Q = np.stack((X, Y, Z), 3) 298 + #calculate the distance field at a given resolution
  299 + # R (triple) resolution along each dimension
  300 + def distancefield(self, R=(100, 100, 100)):
  301 +
  302 + #get a list of all node positions in the network
  303 + P = []
  304 + for e in self.F:
  305 + for p in e.points:
  306 + P.append(p)
  307 +
  308 + #turn that list into a Numpy array so that we can create a KD tree
  309 + P = np.array(P)
  310 +
  311 + #generate a KD-Tree out of the network point array
  312 + tree = sp.spatial.cKDTree(P)
  313 +
  314 + plt.scatter(P[:, 0], P[:, 1])
  315 +
  316 + #specify the resolution of the ouput grid
  317 + R = (200, 200, 200)
  318 +
  319 + #generate a meshgrid of the appropriate size and resolution to surround the network
  320 + lower, upper = self.aabb(self.N, self.F) #get the space occupied by the network
  321 + x = np.linspace(lower[0], upper[0], R[0]) #get the grid points for uniform sampling of this space
  322 + y = np.linspace(lower[1], upper[1], R[1])
  323 + z = np.linspace(lower[2], upper[2], R[2])
  324 + X, Y, Z = np.meshgrid(x, y, z)
  325 + #Z = 150 * numpy.ones(X.shape)
  326 +
  327 +
  328 + Q = np.stack((X, Y, Z), 3)
  329 +
  330 +
  331 + D, I = tree.query(Q)
  332 +
  333 + return D
330 334
  335 + #returns the number of points in the network
  336 + def npoints(self):
  337 + n = 0
  338 + for f in self.F:
  339 + n = n + len(f.points) - 2
  340 + n = n + len(self.N)
  341 + return n
331 342
332 - D, I = tree.query(Q) 343 + #returns the number of linear segments in the network
  344 + def nsegments(self):
  345 + n = 0
  346 + for f in self.F:
  347 + n = n + len(f.points) - 1
  348 + return n
333 349
334 - return D  
335 -  
336 -#returns the number of points in the network  
337 -def npoints(N, F):  
338 - n = 0  
339 - for f in F:  
340 - n = n + len(f.points) - 2  
341 - n = n + len(N)  
342 - return n  
343 -  
344 -#returns the number of linear segments in the network  
345 -def nsegments(N, F):  
346 - n = 0  
347 - for f in F:  
348 - n = n + len(f.points) - 1  
349 - return n  
350 -  
351 -def vectorize(N, F):  
352 - #initialize three coordinate vectors ()  
353 - n = nsegments(N, F)  
354 - X = np.zeros((n))  
355 - Y = np.zeros((n))  
356 - Z = np.zeros((n))  
357 - idx = 0  
358 - for i in range(0, len(F)):  
359 - for j in range(0, len(F[i].points)-1):  
360 - X[idx] = F[i].points[j][0]-F[i].points[j+1][0]  
361 - Y[idx] = F[i].points[j][1]-F[i].points[j+1][1]  
362 - Z[idx] = F[i].points[j][2]-F[i].points[j+1][2]  
363 - idx = idx + 1  
364 - return X, Y, Z 350 + def vectorize(self):
  351 + #initialize three coordinate vectors ()
  352 + n = self.nsegments(self.N, self.F)
  353 + X = np.zeros((n))
  354 + Y = np.zeros((n))
  355 + Z = np.zeros((n))
  356 + idx = 0
  357 + for i in range(0, len(self.F)):
  358 + for j in range(0, len(self.F[i].points)-1):
  359 + X[idx] = self.F[i].points[j][0]-self.F[i].points[j+1][0]
  360 + Y[idx] = self.F[i].points[j][1]-self.F[i].points[j+1][1]
  361 + Z[idx] = self.F[i].points[j][2]-self.F[i].points[j+1][2]
  362 + idx = idx + 1
  363 + return X, Y, Z