@@ -86,41 +86,45 @@ def read(self, swc_pointer):
8686 - "filename": filename of SWC file
8787 - "swc_id": name of SWC file, minus the ".swc".
8888 """
89- # Dictionary with GCS specs
90- if isinstance (swc_pointer , dict ):
91- return self .read_from_gcs (swc_pointer )
92-
93- # List of paths to SWC files
89+ # List of local paths to SWC files
9490 if isinstance (swc_pointer , list ):
9591 return self .read_from_paths (swc_pointer )
9692
9793 # Directory containing...
9894 if os .path .isdir (swc_pointer ):
99- # ZIP archives with SWC files
95+ # Local ZIP archives with SWC files
10096 paths = util .list_paths (swc_pointer , extension = ".zip" )
10197 if len (paths ) > 0 :
10298 return self .read_from_zips (swc_pointer )
10399
104- # SWC files
100+ # Local SWC files
105101 paths = util .read_paths (swc_pointer , extension = ".swc" )
106102 if len (paths ) > 0 :
107103 return self .read_from_paths (paths )
108104
109- raise Exception ("Directory is invalid !" )
105+ raise Exception ("Directory is Invalid !" )
110106
111107 # Path to...
112108 if isinstance (swc_pointer , str ):
113- # ZIP archive with SWC files
109+ # Cloud GCS storage
110+ if util .is_gcs_path (swc_pointer ):
111+ return self .read_from_gcs (swc_pointer )
112+
113+ # Cloud S3 storage
114+ if util .is_s3_path (swc_pointer ):
115+ return self .read_from_s3 (swc_pointer )
116+
117+ # Local ZIP archive with SWC files
114118 if swc_pointer .endswith (".zip" ):
115119 return self .read_from_zip (swc_pointer )
116120
117- # Path to single SWC file
121+ # Local path to single SWC file
118122 if swc_pointer .endswith (".swc" ):
119123 return self .read_from_path (swc_pointer )
120124
121- raise Exception ("Path is invalid !" )
125+ raise Exception ("Path is Invalid !" )
122126
123- raise Exception ("SWC Pointer is inValid !" )
127+ raise Exception ("SWC Pointer is Invalid !" )
124128
125129 def read_from_path (self , path ):
126130 """
@@ -268,15 +272,17 @@ def read_from_zipped_file(self, zipfile, path):
268272 filename = os .path .basename (path )
269273 return self .parse (content , filename )
270274
271- def read_from_gcs (self , gcs_dict ):
275+ def read_from_gcs (self , gcs_path ):
272276 """
273277 Reads SWC files stored in a GCS bucket.
274278
275279 Parameters
276280 ----------
277- gcs_dict : dict
278- Dictionary with the keys "bucket_name" and "path" that specify
279- where the SWC files are located in a GCS bucket.
281+ gcs_path : str
282+ Path to location in a GCS bucket that the SWC files are stored.
283+ The path must be in the format "gs://{bucket_name}/{prefix}",
284+ where "prefix" is a path to a directory containing SWC files or
285+ ZIP archives containing SWC files
280286
281287 Returns
282288 -------
@@ -285,17 +291,18 @@ def read_from_gcs(self, gcs_dict):
285291 names and values from an SWC file.
286292 """
287293 # List filenames
288- swc_paths = util .list_gcs_filenames (gcs_dict , ".swc" )
289- zip_paths = util .list_gcs_filenames (gcs_dict , ".zip" )
294+ bucket_name , prefix = parse_cloud_path (gcs_path )
295+ swc_paths = util .list_gcs_filenames (bucket_name , prefix , ".swc" )
296+ zip_paths = util .list_gcs_filenames (bucket_name , prefix , ".zip" )
290297
291298 # Call reader
292299 if len (swc_paths ) > 0 :
293- return self .read_from_gcs_swcs (gcs_dict [ " bucket_name" ] , swc_paths )
300+ return self .read_from_gcs_swcs (bucket_name , swc_paths )
294301 if len (zip_paths ) > 0 :
295- return self .read_from_gcs_zips (gcs_dict [ " bucket_name" ] , zip_paths )
302+ return self .read_from_gcs_zips (bucket_name , zip_paths )
296303
297304 # Error
298- raise Exception (f"GCS Pointer is invalid -{ gcs_dict } -" )
305+ raise Exception (f"GCS Pointer is invalid -{ gcs_path } -" )
299306
300307 def read_from_gcs_swcs (self , bucket_name , swc_paths ):
301308 """
@@ -419,6 +426,17 @@ def read_from_gcs_zip(self, bucket_name, path):
419426 swc_dicts .append (result )
420427 return swc_dicts
421428
429+ def read_from_s3_swcs (self , s3_path ):
430+ # List filenames
431+ bucket_name , prefix = parse_cloud_path (s3_path )
432+ swc_paths = util .list_s3_paths (bucket_name , prefix , extension = ".swc" )
433+
434+ # Parse SWC files
435+ swc_dicts = deque ()
436+ for path in swc_paths :
437+ contents = util .read_txt_from_s3 (bucket_name , path )
438+ return swc_dicts
439+
422440 def confirm_read (self , filename ):
423441 """
424442 Checks whether the swc_id corresponding to the given filename is
@@ -523,7 +541,38 @@ def read_voxel(self, xyz_str, offset):
523541 return img_util .to_voxels (xyz , self .anisotropy )
524542
525543
526- # --- Write ---
544+ # --- Helpers ---
545+ def parse_cloud_path (path ):
546+ """
547+ Parses a cloud storage path into its bucket name and key/prefix. Supports
548+ paths of the form: "{scheme}://bucket_name/prefix" or without a scheme.
549+
550+ Parameters
551+ ----------
552+ path : str
553+ Path to be parsed.
554+
555+ Returns
556+ -------
557+ bucket_name : str
558+ Name of the bucket.
559+ prefix : str
560+ Cloud prefix.
561+ """
562+ # Remove s3:// if present
563+ if path .startswith ("s3://" ):
564+ path = path [len ("s3://" ):]
565+
566+ # Remove gs:// if present
567+ if path .startswith ("gs://" ):
568+ path = path [len ("gs://" ):]
569+
570+ parts = path .split ("/" , 1 )
571+ bucket_name = parts [0 ]
572+ prefix = parts [1 ] if len (parts ) > 1 else ""
573+ return bucket_name , prefix
574+
575+
527576def to_zipped_point (zip_writer , filename , xyz ):
528577 """
529578 Writes a point to an SWC file format, which is then stored in a ZIP
0 commit comments