Blame view

python/fibernet.py 7.3 KB
e9d3fb64   David Mayerich   added new fiber n...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
  # -*- coding: utf-8 -*-
  """
  Created on Mon Mar 19 14:45:39 2018
  
  @author: david
  """
  
  import nwt
  import matplotlib.pyplot as plt
  import numpy
  
  
  class fibernet:
      
      def __init__(self, filename):
          self.nwt(filename)
          self.buildgraph()
      
      #load a network from a NWT file
      def nwt(self, filename):
          net = nwt.NWT(filename)
          
          #first insert the points where fibers are connected
          self.P = []
          for vi in range(0, len(net.v)):                                         #store each vertex in the point list
              self.P.append( (net.v[vi].p[0], net.v[vi].p[1], net.v[vi].p[2]) )
          
          #now insert each fiber, connecting them appropriately using previously inserted points (vertices)
          self.F = []
          for ei in range(0, len(net.e)):
              f = [numpy.int(net.e[ei].v[0])]                                     #create a new fiber to store point indices, initialize with the first vertex ID
              for pi in range(1, net.e[ei].p.shape[0]):
                  self.P.append( (net.e[ei].p[pi,0], net.e[ei].p[pi,1], net.e[ei].p[pi,2]))    #append the current point to the global point list
                  f.append(len(self.P) - 1)                                       #append the current point ID
              f.append(numpy.int(net.e[ei].v[1]))                                 #append the last vertex ID
              self.F.append(f)
      
      #build a graph from the available geometry
      def buildgraph(self):
          p_to_v = numpy.ones((self.npoints()), numpy.int) * (-1)                            #create an array that maps a point ID to a vertex ID
          
          self.V = []                                                                  #create an empty vertex list
          self.E = []                                                                  #create an empty edge list
          for fi in range(0, self.nfibers()):                                     #for each fiber in the network
              if p_to_v[self.F[fi][0]] == -1:                                          #if the first point hasn't been encountered
                  p_to_v[self.F[fi][0]] = len(self.V)                                       #add it to the mapping
                  self.V.append( (self.F[fi][0], []) )                                              #add a new vertex representing this point
              if p_to_v[self.F[fi][-1]] == -1:
                  p_to_v[self.F[fi][-1]] = len(self.V)
                  self.V.append( (self.F[fi][-1], []) )
                  
              v0 = p_to_v[self.F[fi][0]]                                          #get the two vertex indices corresponding to this edge
              v1 = p_to_v[self.F[fi][-1]]
              
              self.E.append( (v0, v1) )                                                #create an edge representing this fiber and add it to the edge list
              self.V[v0][1].append(fi)                                                 #add this edge ID to the corresponding vertices to update the adjacency list
              self.V[v1][1].append(fi)
              
      #return the length of a fiber specified by fiber ID fid
      def length(self, fid):
          p = self.points(fid)                                                 #get the points corresponding to the fiber
          l = 0                                                                   #initialize the length to zero
          for pi in range(1, len(p)):                                             #for each line segment
              v = p[pi] - p[pi-1]                                                 #calculate the vector representing the line segment
              l = l + numpy.linalg.norm(numpy.array(v))                                  #add the length of the line segment
          return l                                                                #return the total length   
  
      #return a list of vertices adjacent to the vertex specified by vid
      def adjacent(self, vid):
          adj = []                                                                #initialize an empty adjacency list
          for e in self.V[vid][1]:                                                #for each edge connected to vid
              if self.E[e][0] != vid:
                  adj.append(self.E[e][0])
              else:
                  adj.append(self.E[e][1])                
          return adj
      
      #return the fiber network graph as an adjacency list
      def adjacencylist(self):
          A = []
          for vi in range(0, len(self.V)):                                                        #for each vertex in the graph
              A.append( self.adjacent(vi) )                                       #add the adjacency list for the vertex into the main adjacency list
          return A
  
      #return the fiber network graph as an adjacency matrix
      # possible values for the matrix include:
      #           binary - 1 when there is a connection, 0 otherwise
      #           edgeID - stores the edge ID corresponding to a connection, and -1 otherwise
      #           length - stores the length of the connecting fiber, and -1 if there is no connection
      def adjacencymatrix(self, value="binary"):
          if value == "binary":
              M = numpy.ones( (len(self.V), len(self.V)), numpy.bool )
          elif value == "edgeID":
              M = numpy.ones( (len(self.V), len(self.V)), numpy.int ) * -1
          elif value == "length":
              M = numpy.ones( (len(self.V), len(self.V)) ) * -1
          else:
              return []
              
          for vi in range(0, len(self.V)):                                        #for each vertex in the graph
              A = self.adjacent(vi)                                               #get the adjacency matrix
              for a in A:
                  if value == "binary":
                      M[vi,a] = M[a,vi] = 1
                  if value == "edgeID":
                      M[vi,a] = M[a,vi] = self.findedge(a, vi)
                  if value == "length":
                      M[vi,a] = M[a,vi] = self.length(self.findedge(a,vi))
          return M
      
      #find the edge ID corresponding to two vertices
      def findedge(self, v0, v1):
          
          edges = self.V[v0][1]                                                   #get the list of candidate edges connected to v0
          for e in edges:                                                         #for each edge
              if self.E[e][0] == v1 or self.E[e][1] == v1:
                  return e
          
          return -1                                                               #return -1 if the edge doesn't exist
      
      #get the points associated with a specified fiber ID fid    
      def points(self, fid):                                                   #get the points corresponding to a specified fiber index
          f = self.F[fid]                                                         #get the list of point indices
          return numpy.array(self.P)[f]
      
      #get the total number of points in the network
      def npoints(self):
          return len(self.P)
      
      #get the total number of fibers in the network
      def nfibers(self):
          return len(self.F)
      
      #plot the network as a 3D line plot
      def plot(self):
          fig = plt.figure()
          ax = fig.add_subplot(111, projection='3d')
          
          for fi in range(0, self.nfibers()):
              test = fibers.points(fi)
              ax.plot(test[:, 0], test[:, 1], test[:, 2])
          return fig