2020
2121class SkeletonGraph (nx .Graph ):
2222 """
23- A subclass of the NetworkX.Graph that represents a skeleton graph with
24- additional functionality for handling labels and voxel coordinates
25- corresponding to the nodes. Note that node IDs directly index into the
26- "labels" and "voxels" attributes.
23+ A subclass of the NetworkX.Graph designed for graphs built from SWC files.
24+ This class extends the functionality of the standard Graph by adding
25+ support for handling node labels and voxel coordinates. In this subclass,
26+ node IDs serve as direct indices for accessing the labels and voxels
27+ attributes.
2728
2829 Attributes
2930 ----------
30- anisotropy : ArrayLike
31+ anisotropy : np.ndarray
3132 Image to physical coordinates scaling factors to account for the
3233 anisotropy of the microscope.
3334 run_length : float
3435 Physical path length of the graph.
3536 labels : numpy.ndarray
3637 A 1D array that contains a label value associated with each node.
3738 voxels : numpy.ndarray
38- A 3D array that contains a voxel coordinate of each node.
39+ A 3D array that contains a voxel coordinate for each node.
3940
4041 """
4142
4243 def __init__ (self , anisotropy = (1.0 , 1.0 , 1.0 )):
4344 """
4445 Initializes a SkeletonGraph, including setting the anisotropy and
45- initializing the run length attribute .
46+ initializing the run length attributes .
4647
4748 Parameters
4849 ----------
@@ -78,6 +79,8 @@ def init_labels(self):
7879 None
7980
8081 """
82+ error_msg = "Graph must have nodes to initialize labels!"
83+ assert self .number_of_nodes () > 0 , error_msg
8184 self .labels = np .zeros ((self .number_of_nodes ()), dtype = int )
8285
8386 def init_voxels (self , voxels ):
@@ -86,7 +89,8 @@ def init_voxels(self, voxels):
8689
8790 Parameters
8891 ----------
89- None
92+ voxels : ArrayLike
93+ Voxel coordinates for each node in the graph.
9094
9195 Returns
9296 -------
@@ -112,21 +116,20 @@ def set_filename(self, filename):
112116 """
113117 self .filename = filename
114118
115- def set_nodes (self ):
119+ def set_nodes (self , num_nodes ):
116120 """
117- Adds nodes to the graph. The nodes are assigned indices from 0 to the
118- total number of voxels in the image .
121+ Adds nodes to the graph. The nodes are assigned indices from 0 to
122+ "num_nodes" .
119123
120124 Parameters
121125 ----------
122- None
126+ num_nodes
123127
124128 Returns
125129 -------
126130 None
127131
128132 """
129- num_nodes = len (self .voxels )
130133 self .add_nodes_from (np .arange (num_nodes ))
131134
132135 # --- Getters ---
@@ -140,9 +143,8 @@ def get_labels(self):
140143
141144 Returns
142145 -------
143- numpy.ndarray
144- A 1D array of unique non-zero labels assigned to nodes in the
145- graph.
146+ Set[int]
147+ Unique non-zero label values assigned to nodes in the graph.
146148
147149 """
148150 labels = set (np .unique (self .labels ))
@@ -202,7 +204,8 @@ def physical_dist(self, i, j):
202204 Returns
203205 -------
204206 float
205- Euclidea distance between physical coordinates of the given nodes.
207+ Euclidean distance between physical coordinates of the given
208+ nodes.
206209
207210 """
208211 xyz_i = self .voxels [i ] * self .anisotropy
@@ -211,13 +214,13 @@ def physical_dist(self, i, j):
211214
212215 def get_bbox (self , nodes ):
213216 """
214- Calculates the bounding box that contains the voxel coordinates for a
215- given collection of nodes.
217+ Calculates the minimal bounding box containing the voxel coordinates
218+ for a given collection of nodes.
216219
217220 Parameters
218221 ----------
219222 nodes : Container
220- A collection of node indices for which to compute the bounding box.
223+ Node indices for which to compute the bounding box.
221224
222225 Returns
223226 -------
@@ -281,8 +284,8 @@ def run_length_from(self, root):
281284
282285 Parameters
283286 ----------
284- graph : networkx.Graph
285- Graph to be parsed .
287+ root : int
288+ Node contained in connected component to compute run length of .
286289
287290 Returns
288291 -------
@@ -297,14 +300,14 @@ def run_length_from(self, root):
297300
298301 def upd_labels (self , nodes , label ):
299302 """
300- Updates the label of each node in " nodes" with " label" .
303+ Updates the label of the given nodes with a specified label.
301304
302305 Parameters
303306 ----------
304307 nodes : List[int]
305308 Nodes to be updated.
306309 label : int
307- Updated label.
310+ New label of nodes .
308311
309312 Returns
310313 -------
@@ -316,14 +319,16 @@ def upd_labels(self, nodes, label):
316319
317320 def to_zipped_swc (self , zip_writer , color = None ):
318321 """
319- Writes a graph to an SWC file that is to be stored in a zip.
322+ Writes the graph to an SWC file format, which is then stored in a ZIP
323+ archive.
320324
321325 Parameters
322326 ----------
323327 zip_writer : zipfile.ZipFile
324- .. .
328+ A ZipFile object that will store the generated SWC file .
325329 color : str, optional
326- ...
330+ A string representing the color (e.g., "[1.0 0.0 0.0]") of the SWC
331+ file. The default is None.
327332
328333 Returns
329334 -------
@@ -336,24 +341,21 @@ def to_zipped_swc(self, zip_writer, color=None):
336341 text_buffer .write ("# id, type, z, y, x, r, pid" )
337342
338343 # Write entries
339- n_entries = 0
340344 node_to_idx = dict ()
341- r = 5 if color else 3
345+ r = 6 if color else 3
342346 for i , j in nx .dfs_edges (self ):
343347 # Special Case: Root
344348 x , y , z = tuple (self .voxels [i ] * self .anisotropy )
345349 if len (node_to_idx ) == 0 :
346350 parent = - 1
347351 node_to_idx [i ] = 1
348352 text_buffer .write ("\n " + f"1 2 { x } { y } { z } { r } { parent } " )
349- n_entries += 1
350353
351354 # General Case
352- node = n_entries + 1
355+ node = len ( node_to_idx ) + 1
353356 parent = node_to_idx [i ]
354- node_to_idx [j ] = n_entries + 1
357+ node_to_idx [j ] = node
355358 text_buffer .write ("\n " + f"{ node } 2 { x } { y } { z } { r } { parent } " )
356- n_entries += 1
357359
358360 # Finish
359361 zip_writer .writestr (self .filename , text_buffer .getvalue ())
0 commit comments