5050VALID_PROFILES = ["docker" , "apptainer" , "local" , "chtc_hpc" ]
5151MAX_PREVIEW_ITEMS = 5 # Max items to show before "... and N more"
5252
53+ # Help panel names for organizing --help output
54+ PANEL_CORE = "Core Options"
55+ PANEL_PREPROCESSING = "Read Preprocessing"
56+ PANEL_DATABASES = "Database Paths"
57+ PANEL_ANALYSIS = "Analysis Parameters"
58+ PANEL_SRA = "SRA Submission"
59+ PANEL_LABKEY = "LabKey Integration"
60+
5361# ============================================================================
5462# UTILITIES
5563# ============================================================================
@@ -253,6 +261,9 @@ def build_nextflow_command( # noqa: PLR0913
253261@app .command ("r" , hidden = True ) # Alias
254262def run ( # noqa: PLR0913, PLR0912, PLR0915, C901
255263 # Complexity/boolean/B008 warnings are acceptable for CLI with many options
264+ # -------------------------------------------------------------------------
265+ # Core Options
266+ # -------------------------------------------------------------------------
256267 samplesheet : Path = typer .Option (
257268 ...,
258269 "--samplesheet" ,
@@ -261,157 +272,279 @@ def run( # noqa: PLR0913, PLR0912, PLR0915, C901
261272 exists = True ,
262273 file_okay = True ,
263274 dir_okay = False ,
275+ rich_help_panel = PANEL_CORE ,
264276 ),
265277 experiment_id : str = typer .Option (
266278 ...,
267279 "--experiment-id" ,
268280 "-e" ,
269281 help = "Unique experiment identifier" ,
282+ rich_help_panel = PANEL_CORE ,
270283 ),
271284 tools : str = typer .Option (
272285 "all" ,
273286 "--tools" ,
274287 "-t" ,
275288 help = "Tools to run: stat_blast, gottcha, or all" ,
289+ rich_help_panel = PANEL_CORE ,
276290 ),
277291 results : Path | None = typer .Option (
278292 None ,
279293 "--results" ,
280294 "-r" ,
281295 help = "Results directory (default: ./results)" ,
296+ rich_help_panel = PANEL_CORE ,
282297 ),
283298 profile : str | None = typer .Option (
284299 None ,
285300 "--profile" ,
286301 "-p" ,
287302 help = "Execution profile: docker, apptainer, local (auto-detect if not set)" ,
303+ rich_help_panel = PANEL_CORE ,
288304 ),
289305 config : Path | None = typer .Option (
290306 None ,
291307 "--config" ,
292308 "-c" ,
293309 help = "Custom config file (default: ~/.nvd2/config/user.config)" ,
294310 exists = True ,
311+ rich_help_panel = PANEL_CORE ,
295312 ),
296313 resume : bool = typer .Option (
297314 False ,
298315 "--resume" ,
299316 help = "Resume from checkpoint" ,
317+ rich_help_panel = PANEL_CORE ,
300318 ),
301319 cleanup : bool = typer .Option (
302320 False ,
303321 "--cleanup" ,
304322 help = "Clean work directory after success" ,
323+ rich_help_panel = PANEL_CORE ,
305324 ),
306325 work_dir : Path | None = typer .Option (
307326 None ,
308327 "--work-dir" ,
309328 "-w" ,
310329 help = "Nextflow work directory" ,
330+ rich_help_panel = PANEL_CORE ,
311331 ),
312- # Database overrides
332+ # -------------------------------------------------------------------------
333+ # Database Paths
334+ # -------------------------------------------------------------------------
313335 gottcha2_db : Path | None = typer .Option (
314336 None ,
315337 "--gottcha2-db" ,
316338 help = "Override GOTTCHA2 database path" ,
339+ rich_help_panel = PANEL_DATABASES ,
317340 ),
318341 blast_db : Path | None = typer .Option (
319342 None ,
320343 "--blast-db" ,
321344 help = "Override BLAST database directory" ,
345+ rich_help_panel = PANEL_DATABASES ,
322346 ),
323347 blast_db_prefix : str | None = typer .Option (
324348 None ,
325349 "--blast-db-prefix" ,
326350 help = "Override BLAST database prefix" ,
351+ rich_help_panel = PANEL_DATABASES ,
327352 ),
328353 stat_index : Path | None = typer .Option (
329354 None ,
330355 "--stat-index" ,
331356 help = "Override STAT index file" ,
357+ rich_help_panel = PANEL_DATABASES ,
332358 ),
333359 stat_dbss : Path | None = typer .Option (
334360 None ,
335361 "--stat-dbss" ,
336362 help = "Override STAT dbss file" ,
363+ rich_help_panel = PANEL_DATABASES ,
337364 ),
338365 stat_annotation : Path | None = typer .Option (
339366 None ,
340367 "--stat-annotation" ,
341368 help = "Override STAT annotation file" ,
369+ rich_help_panel = PANEL_DATABASES ,
342370 ),
343371 human_virus_taxlist : Path | None = typer .Option (
344372 None ,
345373 "--human-virus-taxlist" ,
346374 help = "Override human virus taxlist file" ,
375+ rich_help_panel = PANEL_DATABASES ,
347376 ),
348- # Analysis parameters
377+ # -------------------------------------------------------------------------
378+ # Analysis Parameters
379+ # -------------------------------------------------------------------------
349380 cutoff_percent : float | None = typer .Option (
350381 None ,
351382 "--cutoff-percent" ,
352383 help = "Cutoff percentage (default: 0.001)" ,
384+ rich_help_panel = PANEL_ANALYSIS ,
353385 ),
354386 tax_stringency : float | None = typer .Option (
355387 None ,
356388 "--tax-stringency" ,
357389 help = "Taxonomy stringency (default: 0.7)" ,
390+ rich_help_panel = PANEL_ANALYSIS ,
358391 ),
359392 entropy : float | None = typer .Option (
360393 None ,
361394 "--entropy" ,
362395 help = "Entropy threshold (default: 0.9)" ,
396+ rich_help_panel = PANEL_ANALYSIS ,
363397 ),
364398 min_gottcha_reads : int | None = typer .Option (
365399 None ,
366400 "--min-gottcha-reads" ,
367401 help = "Minimum reads for GOTTCHA2 (default: 250)" ,
402+ rich_help_panel = PANEL_ANALYSIS ,
368403 ),
369404 max_blast_targets : int | None = typer .Option (
370405 None ,
371406 "--max-blast-targets" ,
372407 help = "Maximum BLAST targets (default: 100)" ,
408+ rich_help_panel = PANEL_ANALYSIS ,
373409 ),
374410 blast_retention_count : int | None = typer .Option (
375411 None ,
376412 "--blast-retention-count" ,
377413 help = "Retain top X BLAST hits (default: 5)" ,
414+ rich_help_panel = PANEL_ANALYSIS ,
378415 ),
379416 min_consecutive_bases : int | None = typer .Option (
380417 None ,
381418 "--min-consecutive-bases" ,
382419 help = "Minimum consecutive bases (default: 200)" ,
420+ rich_help_panel = PANEL_ANALYSIS ,
383421 ),
384422 qtrim : str | None = typer .Option (
385423 None ,
386424 "--qtrim" ,
387425 help = "Quality trimming mode (default: 't')" ,
426+ rich_help_panel = PANEL_ANALYSIS ,
388427 ),
389428 include_children : bool | None = typer .Option (
390429 None ,
391430 "--include-children/--no-include-children" ,
392431 help = "Include children in taxonomy (default: true)" ,
432+ rich_help_panel = PANEL_ANALYSIS ,
393433 ),
394434 max_concurrent_downloads : int | None = typer .Option (
395435 None ,
396436 "--max-concurrent-downloads" ,
397437 help = "Maximum concurrent SRA downloads (default: 3)" ,
438+ rich_help_panel = PANEL_ANALYSIS ,
439+ ),
440+ # -------------------------------------------------------------------------
441+ # Read Preprocessing
442+ # -------------------------------------------------------------------------
443+ preprocess : bool = typer .Option (
444+ False ,
445+ "--preprocess" ,
446+ help = "Enable all preprocessing steps (dedup, trim, scrub, filter)" ,
447+ rich_help_panel = PANEL_PREPROCESSING ,
448+ ),
449+ merge_pairs : bool | None = typer .Option (
450+ None ,
451+ "--merge-pairs/--no-merge-pairs" ,
452+ help = "Merge paired read mates based on overlaps" ,
453+ rich_help_panel = PANEL_PREPROCESSING ,
454+ ),
455+ dedup : bool | None = typer .Option (
456+ None ,
457+ "--dedup/--no-dedup" ,
458+ help = "Deduplicate reads (default: follows --preprocess)" ,
459+ rich_help_panel = PANEL_PREPROCESSING ,
460+ ),
461+ trim_adapters : bool | None = typer .Option (
462+ None ,
463+ "--trim-adapters/--no-trim-adapters" ,
464+ help = "Trim Illumina adapters (default: follows --preprocess)" ,
465+ rich_help_panel = PANEL_PREPROCESSING ,
466+ ),
467+ scrub_host_reads : bool | None = typer .Option (
468+ None ,
469+ "--scrub-host-reads/--no-scrub-host-reads" ,
470+ help = "Remove host reads with hostile (default: follows --preprocess)" ,
471+ rich_help_panel = PANEL_PREPROCESSING ,
472+ ),
473+ hostile_index : Path | None = typer .Option (
474+ None ,
475+ "--hostile-index" ,
476+ help = "Path to local hostile index (for offline use)" ,
477+ rich_help_panel = PANEL_PREPROCESSING ,
478+ ),
479+ hostile_index_name : str | None = typer .Option (
480+ None ,
481+ "--hostile-index-name" ,
482+ help = "Standard hostile index name (default: human-t2t-hla.rs-viral-202401_ml-phage-202401)" ,
483+ rich_help_panel = PANEL_PREPROCESSING ,
484+ ),
485+ filter_reads : bool | None = typer .Option (
486+ None ,
487+ "--filter-reads/--no-filter-reads" ,
488+ help = "Filter reads by quality/length (default: follows --preprocess)" ,
489+ rich_help_panel = PANEL_PREPROCESSING ,
490+ ),
491+ min_read_quality_illumina : int | None = typer .Option (
492+ None ,
493+ "--min-read-quality-illumina" ,
494+ help = "Minimum average quality for Illumina reads (default: 20)" ,
495+ rich_help_panel = PANEL_PREPROCESSING ,
496+ ),
497+ min_read_quality_nanopore : int | None = typer .Option (
498+ None ,
499+ "--min-read-quality-nanopore" ,
500+ help = "Minimum average quality for Nanopore reads (default: 12)" ,
501+ rich_help_panel = PANEL_PREPROCESSING ,
398502 ),
503+ min_read_length : int | None = typer .Option (
504+ None ,
505+ "--min-read-length" ,
506+ help = "Minimum read length (default: 50)" ,
507+ rich_help_panel = PANEL_PREPROCESSING ,
508+ ),
509+ max_read_length : int | None = typer .Option (
510+ None ,
511+ "--max-read-length" ,
512+ help = "Maximum read length (default: no limit)" ,
513+ rich_help_panel = PANEL_PREPROCESSING ,
514+ ),
515+ # -------------------------------------------------------------------------
516+ # SRA Submission
517+ # -------------------------------------------------------------------------
518+ sra_human_db : Path | None = typer .Option (
519+ None ,
520+ "--sra-human-db" ,
521+ help = "Path to human reads database for SRA submission scrubbing" ,
522+ rich_help_panel = PANEL_SRA ,
523+ ),
524+ # DEPRECATED: Use --sra-human-db instead
399525 human_read_scrub : Path | None = typer .Option (
400526 None ,
401527 "--human-read-scrub" ,
402- help = "Human read scrubbing file path" ,
528+ help = "[DEPRECATED] Use --sra-human-db instead" ,
529+ hidden = True ,
403530 ),
404- # LabKey
531+ # -------------------------------------------------------------------------
532+ # LabKey Integration
533+ # -------------------------------------------------------------------------
405534 labkey : bool = typer .Option (
406535 False ,
407536 "--labkey" ,
408537 help = "Enable LabKey integration" ,
538+ rich_help_panel = PANEL_LABKEY ,
409539 ),
410- # Dry run
540+ # -------------------------------------------------------------------------
541+ # Execution Control
542+ # -------------------------------------------------------------------------
411543 dry_run : bool = typer .Option (
412544 False ,
413545 "--dry-run" ,
414546 help = "Show command without executing" ,
547+ rich_help_panel = PANEL_CORE ,
415548 ),
416549) -> None :
417550 """
@@ -502,8 +635,41 @@ def run( # noqa: PLR0913, PLR0912, PLR0915, C901
502635 extra_params ["include_children" ] = "true" if include_children else "false"
503636 if max_concurrent_downloads is not None :
504637 extra_params ["max_concurrent_downloads" ] = max_concurrent_downloads
505- if human_read_scrub :
506- extra_params ["human_read_scrub" ] = human_read_scrub
638+ # Preprocessing options
639+ if preprocess :
640+ extra_params ["preprocess" ] = "true"
641+ if merge_pairs is not None :
642+ extra_params ["merge_pairs" ] = "true" if merge_pairs else "false"
643+ if dedup is not None :
644+ extra_params ["dedup" ] = "true" if dedup else "false"
645+ if trim_adapters is not None :
646+ extra_params ["trim_adapters" ] = "true" if trim_adapters else "false"
647+ if scrub_host_reads is not None :
648+ extra_params ["scrub_host_reads" ] = "true" if scrub_host_reads else "false"
649+ if hostile_index :
650+ extra_params ["hostile_index" ] = hostile_index
651+ if hostile_index_name :
652+ extra_params ["hostile_index_name" ] = hostile_index_name
653+ if filter_reads is not None :
654+ extra_params ["filter_reads" ] = "true" if filter_reads else "false"
655+ if min_read_quality_illumina is not None :
656+ extra_params ["min_read_quality_illumina" ] = min_read_quality_illumina
657+ if min_read_quality_nanopore is not None :
658+ extra_params ["min_read_quality_nanopore" ] = min_read_quality_nanopore
659+ if min_read_length is not None :
660+ extra_params ["min_read_length" ] = min_read_length
661+ if max_read_length is not None :
662+ extra_params ["max_read_length" ] = max_read_length
663+ # SRA submission options
664+ # Handle deprecated --human-read-scrub option
665+ if human_read_scrub and not sra_human_db :
666+ warning (
667+ "DEPRECATION: --human-read-scrub is deprecated. "
668+ "Please use --sra-human-db instead." ,
669+ )
670+ extra_params ["sra_human_db" ] = human_read_scrub
671+ elif sra_human_db :
672+ extra_params ["sra_human_db" ] = sra_human_db
507673 if labkey :
508674 extra_params ["labkey" ] = "true"
509675
0 commit comments