1- # -*- coding: utf-8 -*-
21"""
32Created on Wed June 5 16:00:00 2023
43
4140class Reader :
4241 """
4342 Class that reads SWC files stored in a (1) local directory, (2) local ZIP
44- archive, (3) local directory of ZIP archives or (4) GCS directory of ZIP
45- archives.
43+ archive, and (3) local directory of ZIP archives.
4644
4745 """
4846
4947 def __init__ (self , anisotropy = (1.0 , 1.0 , 1.0 ), selected_ids = None ):
5048 """
51- Initializes a Reader object that loads swc files.
49+ Initializes a Reader object that reads SWC files.
5250
5351 Parameters
5452 ----------
5553 anisotropy : Tuple[float], optional
5654 Image to world scaling factors applied to xyz coordinates to
5755 account for anisotropy of the microscope. The default is
5856 (1.0, 1.0, 1.0).
57+ selected_ids : Set[int], optional
58+ Only SWC files with an swc_id contained in this set are read.
5959
6060 Returns
6161 -------
@@ -65,8 +65,8 @@ def __init__(self, anisotropy=(1.0, 1.0, 1.0), selected_ids=None):
6565 self .anisotropy = anisotropy
6666 self .selected_ids = selected_ids or set ()
6767
68- # --- Load Data ---
69- def load (self , swc_pointer ):
68+ # --- Read Data ---
69+ def read (self , swc_pointer ):
7070 """
7171 Load SWCs files based on the type pointer provided.
7272
@@ -82,80 +82,87 @@ def load(self, swc_pointer):
8282
8383 Returns
8484 -------
85- dict
86- Dictionary whose keys are filnames of SWC files and values are the
87- corresponding graphs.
85+ Deque[dict]
86+ List of dictionaries whose keys and values are the attribute names
87+ and values from the SWC files. Each dictionary contains the
88+ following items:
89+ - "id": unique identifier of each node in an SWC file.
90+ - "pid": parent ID of each node.
91+ - "radius": radius value corresponding to each node.
92+ - "xyz": coordinate corresponding to each node.
93+ - "filename": filename of SWC file
94+ - "swc_id": name of SWC file, minus the ".swc".
8895
8996 """
9097 # List of paths to SWC files
9198 if isinstance (swc_pointer , list ):
92- return self .load_from_local_paths (swc_pointer )
99+ return self .read_from_paths (swc_pointer )
93100
94101 # Directory containing...
95102 if os .path .isdir (swc_pointer ):
96103 # ZIP archives with SWC files
97104 paths = util .list_paths (swc_pointer , extension = ".zip" )
98105 if len (paths ) > 0 :
99- return self .load_from_local_zips (swc_pointer )
106+ return self .read_from_zips (swc_pointer )
100107
101108 # SWC files
102- paths = util .list_paths (swc_pointer , extension = ".swc" )
109+ paths = util .read_paths (swc_pointer , extension = ".swc" )
103110 if len (paths ) > 0 :
104- return self .load_from_local_paths (paths )
111+ return self .read_from_paths (paths )
105112
106113 raise Exception ("Directory is invalid!" )
107114
108115 # Path to...
109116 if isinstance (swc_pointer , str ):
110117 # ZIP archive with SWC files
111118 if ".zip" in swc_pointer :
112- return self .load_from_local_zip (swc_pointer )
119+ return self .read_from_zip (swc_pointer )
113120
114121 # Path to single SWC file
115122 if ".swc" in swc_pointer :
116- return self .load_from_local_path (swc_pointer )
123+ return self .read_from_path (swc_pointer )
117124
118125 raise Exception ("Path is invalid!" )
119126
120127 raise Exception ("SWC Pointer is inValid!" )
121128
122- def load_from_local_path (self , path ):
129+ def read_from_path (self , path ):
123130 """
124- Reads a single SWC file from local machine .
131+ Reads a single SWC file.
125132
126133 Paramters
127134 ---------
128135 path : str
129- Path to SWC file stored on the local machine .
136+ Path to SWC file.
130137
131138 Returns
132139 -------
133140 dict
134- Dictionary whose keys are filnames of SWC files and values are the
135- corresponding graphs .
141+ Dictionary whose keys and values are the attribute names and
142+ values from an SWC file .
136143
137144 """
138145 content = util .read_txt (path )
139146 filename = os .path .basename (path )
140- if self .confirm_load (filename ):
147+ if self .confirm_read (filename ):
141148 return self .parse (content , filename )
142149 else :
143150 return None
144151
145- def load_from_local_paths (self , paths ):
152+ def read_from_paths (self , paths ):
146153 """
147- Reads list of SWC files stored on the local machine .
154+ Reads SWC files given a list of paths .
148155
149156 Paramters
150157 ---------
151- swc_paths : list
152- List of paths to SWC files stored on the local machine .
158+ swc_paths : List[str]
159+ Paths to SWC files.
153160
154161 Returns
155162 -------
156- dict
157- Dictionary whose keys are filnames of SWC files and values are the
158- corresponding graphs .
163+ Deque[ dict]
164+ Dictionaries whose keys and values are the attribute names and
165+ values from an SWC file .
159166
160167 """
161168 with ThreadPoolExecutor () as executor :
@@ -164,9 +171,9 @@ def load_from_local_paths(self, paths):
164171 pbar = tqdm (total = len (paths ), desc = "Read SWCs" )
165172 for path in paths :
166173 filename = os .path .basename (path )
167- if self .confirm_load (filename ):
174+ if self .confirm_read (filename ):
168175 threads .append (
169- executor .submit (self .load_from_local_path , path )
176+ executor .submit (self .read_from_path , path )
170177 )
171178
172179 # Store results
@@ -176,7 +183,22 @@ def load_from_local_paths(self, paths):
176183 pbar .update (1 )
177184 return swc_dicts
178185
179- def load_from_local_zips (self , zip_dir ):
186+ def read_from_zips (self , zip_dir ):
187+ """
188+ Processes a directory containing ZIP archives with SWC files.
189+
190+ Parameters
191+ ----------
192+ zip_dir : str
193+ Path to directory containing ZIP archives with SWC files.
194+
195+ Returns
196+ -------
197+ Deque[dict]
198+ Dictionaries whose keys and values are the attribute names and
199+ values from an SWC file.
200+
201+ """
180202 # Initializations
181203 zip_names = [f for f in os .listdir (zip_dir ) if f .endswith (".zip" )]
182204 pbar = tqdm (total = len (zip_names ), desc = "Read SWCs" )
@@ -188,7 +210,7 @@ def load_from_local_zips(self, zip_dir):
188210 for f in zip_names :
189211 zip_path = os .path .join (zip_dir , f )
190212 processes .append (
191- executor .submit (self .load_from_local_zip , zip_path )
213+ executor .submit (self .read_from_zip , zip_path )
192214 )
193215
194216 # Store results
@@ -198,34 +220,32 @@ def load_from_local_zips(self, zip_dir):
198220 pbar .update (1 )
199221 return swc_dicts
200222
201- def load_from_local_zip (self , zip_path ):
223+ def read_from_zip (self , zip_path ):
202224 """
203- Reads SWC files from zip on the local machine .
225+ Reads SWC files from a ZIP archive .
204226
205227 Paramters
206228 ---------
207- swc_paths : list or dict
208- If swc files are on local machine, list of paths to swc files where
209- each file corresponds to a neuron in the prediction. If swc files
210- are on cloud, then dict with keys "bucket_name" and "path".
229+ zip_path : str
230+ Path to ZIP archive.
211231
212232 Returns
213233 -------
214- dict
215- Dictionary whose keys are filnames of SWC files and values are the
216- corresponding graphs .
234+ Deque[ dict]
235+ Dictionaries whose keys and values are the attribute names and
236+ values from an SWC file .
217237
218238 """
219239 with ThreadPoolExecutor () as executor :
220240 # Assign threads
221241 threads = list ()
222242 zipfile = ZipFile (zip_path , "r" )
223- filesnames = [f for f in zipfile .namelist () if f .endswith (".swc" )]
224- for filename in filesnames :
225- if self .confirm_load (filename ):
243+ filenames = [f for f in zipfile .namelist () if f .endswith (".swc" )]
244+ for filename in filenames :
245+ if self .confirm_read (filename ):
226246 threads .append (
227247 executor .submit (
228- self .load_from_zipped_file , zipfile , filename
248+ self .read_from_zipped_file , zipfile , filename
229249 )
230250 )
231251
@@ -235,29 +255,44 @@ def load_from_local_zip(self, zip_path):
235255 swc_dicts .append (thread .result ())
236256 return swc_dicts
237257
238- def load_from_zipped_file (self , zipfile , path ):
258+ def read_from_zipped_file (self , zipfile , path ):
239259 """
240- Reads swc file stored at "path" which points to a file in a zip .
260+ Reads an SWC file stored in a ZIP archive .
241261
242262 Parameters
243263 ----------
244- zipfile : ZipFile
245- Zip containing swc file to be read .
264+ zip_file : ZipFile
265+ ZIP archive containing SWC files .
246266 path : str
247- Path to swc file to be read .
267+ Path to SWC file.
248268
249269 Returns
250270 -------
251271 dict
252- Dictionary whose keys are filnames of SWC files and values are the
253- corresponding graphs .
272+ Dictionary whose keys and values are the attribute names and
273+ values from an SWC file .
254274
255275 """
256276 content = util .read_zip (zipfile , path ).splitlines ()
257277 filename = os .path .basename (path )
258278 return self .parse (content , filename )
259279
260- def confirm_load (self , filename ):
280+ def confirm_read (self , filename ):
281+ """
282+ Checks whether the swc_id corresponding to the given filename is
283+ contained in the attribute "selected_ids".
284+
285+ Parameters
286+ ----------
287+ filename : str
288+ Name of SWC file to be checked.
289+
290+ Returns
291+ -------
292+ bool
293+ Indication of whether to read SWC file.
294+
295+ """
261296 if len (self .selected_ids ) > 0 :
262297 segment_id = util .get_segment_id (filename )
263298 return True if segment_id in self .selected_ids else False
@@ -268,8 +303,6 @@ def confirm_load(self, filename):
268303 def parse (self , content , filename ):
269304 """
270305 Parses an SWC file to extract the content which is stored in a dict.
271- Note that node_ids from SWC are reindex from 0 to n-1 where n is the
272- number of nodes in the SWC file.
273306
274307 Parameters
275308 ----------
@@ -279,8 +312,8 @@ def parse(self, content, filename):
279312 Returns
280313 -------
281314 dict
282- Dictionaries whose keys and values are the attribute names
283- and values from an SWC file.
315+ Dictionary whose keys and values are the attribute names and
316+ values from an SWC file.
284317
285318 """
286319 # Initializations
@@ -314,11 +347,10 @@ def process_content(self, content):
314347
315348 Returns
316349 -------
317- List[str]
318- A list of strings representing the lines of text starting from the
319- line immediately after the last commented line.
320- List[int]
321- Offset used to shift coordinates.
350+ tuple
351+ A tuple containing the following:
352+ - "content" (List[str]): lines from an SWC file after comments.
353+ - "offset" (Tuple[int]): offset used to shift coordinate.
322354
323355 """
324356 offset = (0 , 0 , 0 )
@@ -331,15 +363,14 @@ def process_content(self, content):
331363
332364 def read_voxel (self , xyz_str , offset ):
333365 """
334- Reads the coordinates from a string, then transforms them to image
335- coordinates (if applicable).
366+ Reads a coordinate from a string and converts it to voxel coordinates.
336367
337368 Parameters
338369 ----------
339370 xyz_str : str
340- Coordinate stored in a str .
371+ Coordinate stored as a string .
341372 offset : list[int]
342- Offset of coordinates in swc file.
373+ Offset of coordinates in SWC file.
343374
344375 Returns
345376 -------
0 commit comments