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
python/network.py
... ... @@ -39,11 +39,12 @@ class Fiber:
39 39 self.points = []
40 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 50 return the length of the fiber.
... ... @@ -76,289 +77,287 @@ class Fiber:
76 77  
77 78 #print(volume)
78 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 147 bytes = open_file.read(4)
185   - point[0] = struct.unpack('f', bytes)[0]
  148 + points[0] = struct.unpack('f', bytes)[0]
186 149 bytes = open_file.read(4)
187   - point[1] = struct.unpack('f', bytes)[0]
  150 + points[1] = struct.unpack('f', bytes)[0]
188 151 bytes = open_file.read(4)
189   - point[2] = struct.unpack('f', bytes)[0]
  152 + points[2] = struct.unpack('f', bytes)[0]
190 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
... ...