@@ -227,30 +227,54 @@ def create_copick_app(root: copick.models.CopickRoot, cors_origins: Optional[Lis
227227
228228 return app
229229
230- def serve_copick (config_path : str , allowed_origins : Optional [List [str ]] = None , ** kwargs ):
230+ def serve_copick (config_path : Optional [ str ] = None , dataset_ids : Optional [ List [ int ]] = None , overlay_root : str = "/tmp/overlay_root" , allowed_origins : Optional [List [str ]] = None , ** kwargs ):
231231 """Start an HTTP server serving a Copick project.
232232
233233 Parameters
234234 ----------
235- config_path : str
235+ config_path : str, optional
236236 Path to Copick config file
237+ dataset_ids : list of int, optional
238+ Dataset IDs to include in the project
239+ overlay_root : str, optional
240+ Root URL for the overlay storage, default is "/tmp/overlay_root"
237241 allowed_origins : list of str, optional
238242 List of allowed CORS origins. Use ["*"] to allow all.
239243 **kwargs
240244 Additional arguments passed to uvicorn.run()
245+
246+ Notes
247+ -----
248+ Either config_path or dataset_ids must be provided, but not both.
241249 """
242- root = copick .from_file (config_path )
250+ if config_path and dataset_ids :
251+ raise ValueError ("Either config_path or dataset_ids must be provided, but not both." )
252+ elif config_path :
253+ root = copick .from_file (config_path )
254+ elif dataset_ids :
255+ root = copick .from_czcdp_datasets (
256+ dataset_ids = dataset_ids ,
257+ overlay_root = overlay_root ,
258+ overlay_fs_args = {"auto_mkdir" : True },
259+ )
260+ else :
261+ raise ValueError ("Either config_path or dataset_ids must be provided." )
262+
243263 app = create_copick_app (root , allowed_origins )
244264 uvicorn .run (app , ** kwargs )
245265 return app
246266
247- def serve_copick_threaded (config_path : str , allowed_origins : Optional [List [str ]] = None , ** kwargs ):
267+ def serve_copick_threaded (config_path : Optional [ str ] = None , dataset_ids : Optional [ List [ int ]] = None , overlay_root : str = "/tmp/overlay_root" , allowed_origins : Optional [List [str ]] = None , ** kwargs ):
248268 """Start an HTTP server in a background thread and return the app.
249269
250270 Parameters
251271 ----------
252- config_path : str
272+ config_path : str, optional
253273 Path to Copick config file
274+ dataset_ids : list of int, optional
275+ Dataset IDs to include in the project
276+ overlay_root : str, optional
277+ Root URL for the overlay storage, default is "/tmp/overlay_root"
254278 allowed_origins : list of str, optional
255279 List of allowed CORS origins. Use ["*"] to allow all.
256280 **kwargs
@@ -260,8 +284,24 @@ def serve_copick_threaded(config_path: str, allowed_origins: Optional[List[str]]
260284 -------
261285 app : FastAPI
262286 FastAPI application
287+
288+ Notes
289+ -----
290+ Either config_path or dataset_ids must be provided, but not both.
263291 """
264- root = copick .from_file (config_path )
292+ if config_path and dataset_ids :
293+ raise ValueError ("Either config_path or dataset_ids must be provided, but not both." )
294+ elif config_path :
295+ root = copick .from_file (config_path )
296+ elif dataset_ids :
297+ root = copick .from_czcdp_datasets (
298+ dataset_ids = dataset_ids ,
299+ overlay_root = overlay_root ,
300+ overlay_fs_args = {"auto_mkdir" : True },
301+ )
302+ else :
303+ raise ValueError ("Either config_path or dataset_ids must be provided." )
304+
265305 app = create_copick_app (root , allowed_origins )
266306
267307 # Start the server in a background thread
@@ -275,8 +315,36 @@ def serve_copick_threaded(config_path: str, allowed_origins: Optional[List[str]]
275315
276316 return app
277317
278- @click .command ()
279- @click .argument ("config" , type = click .Path (exists = True ))
318+ @click .group ()
319+ @click .pass_context
320+ def cli (ctx ):
321+ pass
322+
323+
324+ @cli .command ()
325+ @click .option (
326+ "-c" ,
327+ "--config" ,
328+ type = click .Path (exists = True ),
329+ help = "Path to the configuration file." ,
330+ required = False ,
331+ metavar = "PATH" ,
332+ )
333+ @click .option (
334+ "-ds" ,
335+ "--dataset-ids" ,
336+ type = int ,
337+ multiple = True ,
338+ help = "Dataset IDs to include in the project (multiple inputs possible)." ,
339+ metavar = "ID" ,
340+ )
341+ @click .option (
342+ "--overlay-root" ,
343+ type = str ,
344+ default = "/tmp/overlay_root" ,
345+ help = "Root URL for the overlay storage." ,
346+ show_default = True ,
347+ )
280348@click .option (
281349 "--cors" ,
282350 type = str ,
@@ -298,15 +366,30 @@ def serve_copick_threaded(config_path: str, allowed_origins: Optional[List[str]]
298366 show_default = True ,
299367)
300368@click .option ("--reload" , is_flag = True , default = False , help = "Enable auto-reload." )
301- def main (config : str , cors : Optional [str ], host : str , port : int , reload : bool ):
369+ @click .pass_context
370+ def serve (ctx , config : Optional [str ] = None , dataset_ids : Optional [tuple ] = None , overlay_root : str = "/tmp/overlay_root" , cors : Optional [str ] = None , host : str = "127.0.0.1" , port : int = 8000 , reload : bool = False ):
302371 """Serve a Copick project over HTTP."""
303- serve_copick (
304- config ,
305- allowed_origins = [cors ] if cors else None ,
306- host = host ,
307- port = port ,
308- reload = reload
309- )
372+ if config and dataset_ids :
373+ ctx .fail ("Either --config or --dataset-ids must be provided, not both." )
374+ elif not config and not dataset_ids :
375+ ctx .fail ("Either --config or --dataset-ids must be provided." )
376+
377+ try :
378+ serve_copick (
379+ config_path = config ,
380+ dataset_ids = dataset_ids if dataset_ids else None ,
381+ overlay_root = overlay_root ,
382+ allowed_origins = [cors ] if cors else None ,
383+ host = host ,
384+ port = port ,
385+ reload = reload
386+ )
387+ except Exception as e :
388+ ctx .fail (f"Error serving Copick project: { str (e )} " )
389+
390+
391+ def main ():
392+ cli ()
310393
311394if __name__ == "__main__" :
312395 main ()
0 commit comments