Skip to main content

fibertools_rs/
cli.rs

1use anstyle;
2use clap::{Args, Command, CommandFactory, Parser, Subcommand};
3use clap_complete::{generate, Generator, Shell};
4use std::{fmt::Debug, io};
5
6// Reference the modules for the subcommands
7mod benchmark_opts;
8mod call_peaks_opts;
9mod center_opts;
10mod clear_kinetics_opts;
11mod convert_tags_opts;
12mod ddda_to_m6a_opts;
13mod decorator_opts;
14mod extract_opts;
15mod fiber_hmm;
16mod fire_opts;
17mod footprint_opts;
18mod mock_fire_opts;
19mod nucleosome_opts;
20mod pg_inject_opts;
21mod pg_lift_opts;
22mod pg_pansn_opts;
23mod pileup_opts;
24mod predict_opts;
25mod qc_opts;
26mod strip_basemods_opts;
27mod validate_opts;
28
29// include the subcommand modules as top level functions and structs in the cli module
30pub use benchmark_opts::*;
31pub use call_peaks_opts::*;
32pub use center_opts::*;
33pub use clear_kinetics_opts::*;
34pub use convert_tags_opts::*;
35pub use ddda_to_m6a_opts::*;
36pub use decorator_opts::*;
37pub use extract_opts::*;
38pub use fiber_hmm::*;
39pub use fire_opts::*;
40pub use footprint_opts::*;
41pub use mock_fire_opts::*;
42pub use nucleosome_opts::*;
43pub use pg_inject_opts::*;
44pub use pg_lift_opts::*;
45pub use pg_pansn_opts::*;
46pub use pileup_opts::*;
47pub use predict_opts::*;
48pub use qc_opts::*;
49pub use strip_basemods_opts::*;
50pub use validate_opts::ValidateOptions;
51
52//
53// The main CLI structure
54//
55#[derive(Parser)]
56#[clap(
57    author,
58    version,
59    about,
60    propagate_version = true,
61    subcommand_required = true,
62    infer_subcommands = true,
63    arg_required_else_help = true
64)]
65#[command(version = &**crate::FULL_VERSION)]
66#[command(styles=get_styles())]
67pub struct Cli {
68    #[clap(flatten)]
69    pub global: GlobalOpts,
70    /// Subcommands for fibertools-rs
71    #[clap(subcommand)]
72    pub command: Option<Commands>,
73}
74
75//
76// Global options available to all subcommands
77//
78#[derive(Debug, Args, PartialEq, Eq)]
79pub struct GlobalOpts {
80    /// Threads
81    #[clap(
82        global = true,
83        short,
84        long,
85        default_value_t = 8,
86        help_heading = "Global-Options"
87    )]
88    pub threads: usize,
89
90    /// Logging level [-v: Info, -vv: Debug, -vvv: Trace]
91    #[clap(
92        global = true,
93        short,
94        long,
95        action = clap::ArgAction::Count,
96        help_heading = "Debug-Options"
97    )]
98    pub verbose: u8,
99    /// Turn off all logging
100    #[clap(global = true, long, help_heading = "Debug-Options")]
101    pub quiet: bool,
102}
103
104impl std::default::Default for GlobalOpts {
105    fn default() -> Self {
106        Self {
107            threads: 8,
108            verbose: 0,
109            quiet: false,
110        }
111    }
112}
113
114//
115// This structure contains all the subcommands and their help descriptions.
116//
117#[derive(Subcommand, Debug)]
118pub enum Commands {
119    /// Predict m6A positions using HiFi kinetics data and encode the results in the MM and ML bam tags. Also adds nucleosome (nl, ns) and MTase sensitive patches (al, as).
120    #[clap(visible_aliases = &["m6A", "m6a"])]
121    PredictM6A(PredictM6AOptions),
122    /// Add nucleosomes to a bam file with m6a predictions
123    AddNucleosomes(AddNucleosomeOptions),
124    /// Add FIREs (Fiber-seq Inferred Regulatory Elements) to a bam file with m6a predictions
125    Fire(FireOptions),
126    /// Extract fiberseq data into plain text files.
127    ///
128    /// See https://fiberseq.github.io/fibertools/extracting/extract.html for a description of the outputs.
129    #[clap(visible_aliases = &["ex", "e"])]
130    Extract(ExtractOptions),
131    /// This command centers fiberseq data around given reference positions. This is useful for making aggregate m6A and CpG observations, as well as visualization of SVs.
132    ///
133    ///  See https://fiberseq.github.io/fibertools/extracting/center.html for a description of the output.
134    #[clap(visible_aliases = &["c", "ct"])]
135    Center(CenterOptions),
136    /// Infer footprints from fiberseq data
137    Footprint(FootprintOptions),
138    /// Collect QC metrics from a fiberseq bam file
139    Qc(QcOpts),
140    /// Make decorated bed files for fiberseq data
141    TrackDecorators(DecoratorOptions),
142    /// Make a pileup track of Fiber-seq features from a FIRE bam
143    Pileup(PileupOptions),
144    /// Remove HiFi kinetics tags from the input bam file
145    ClearKinetics(ClearKineticsOptions),
146    /// Convert legacy (lowercase) fiberseq tags to MA spec
147    ConvertTags(ConvertTagsOptions),
148    /// Strip out select base modifications
149    StripBasemods(StripBasemodsOptions),
150    /// Convert a DddA BAM file to pseudo m6A BAM file
151    DddaToM6a(DddaToM6aOptions),
152    /// Apply FiberHMM to a bam file
153    FiberHmm(FiberHmmOptions),
154    /// Validate a Fiber-seq BAM file for m6A, nucleosome, and optionally FIRE calls
155    Validate(ValidateOptions),
156    /// Create a mock BAM file from a reference FASTA with perfectly aligned sequences
157    #[clap(name = "pg-inject")]
158    PgInject(PgInjectOptions),
159    /// Lift annotations through a pangenome graph from source to target coordinates
160    #[clap(name = "pg-lift")]
161    PgLift(PgLiftOptions),
162    /// Add or strip panSN-spec prefixes from BAM contig names
163    #[clap(name = "pg-pansn")]
164    PgPansn(PgPansnOptions),
165    /// Call FIRE peaks using FDR-based peak calling on pileup data
166    #[clap(name = "call-peaks", visible_aliases = &["peaks", "call"])]
167    CallPeaks(CallPeaksOptions),
168    /// Create a mock BAM file with FIRE elements from a BED file.
169    /// Each interval in the BED becomes a FIRE element. The 4th column groups intervals into the same mock read.
170    #[clap(name = "mock-fire")]
171    MockFire(MockFireOptions),
172    /// Benchmark fiber iterator performance (hidden command for testing)
173    #[clap(hide = true)]
174    Benchmark(BenchmarkOptions),
175    /// Make command line completions
176    #[clap(hide = true)]
177    Completions(CompletionOptions),
178    /// Make a man page for fibertools-rs
179    ///
180    /// Writes file for `man` to stdout.
181    #[clap(hide = true)]
182    Man {},
183}
184
185//
186// CLI utility functions
187//
188
189/// This function is used to generate the styles for the CLI help messages.
190fn get_styles() -> clap::builder::Styles {
191    let cmd_color = anstyle::AnsiColor::Magenta;
192    let header_color = anstyle::AnsiColor::BrightGreen;
193    let placeholder_color = anstyle::AnsiColor::Cyan;
194    let header_style = anstyle::Style::new()
195        .bold()
196        .underline()
197        .fg_color(Some(anstyle::Color::Ansi(header_color)));
198    let cmd_style = anstyle::Style::new()
199        .bold()
200        .fg_color(Some(anstyle::Color::Ansi(cmd_color)));
201    let placeholder_style = anstyle::Style::new()
202        //.bold()
203        .fg_color(Some(anstyle::Color::Ansi(placeholder_color)));
204    clap::builder::Styles::styled()
205        .header(header_style)
206        .literal(cmd_style)
207        .usage(header_style)
208        .placeholder(placeholder_style)
209}
210
211pub fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
212    generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
213}
214
215pub fn make_cli_parse() -> Cli {
216    Cli::parse()
217}
218
219pub fn make_cli_app() -> Command {
220    Cli::command()
221}
222
223#[derive(Args, Debug, PartialEq, Eq)]
224pub struct CompletionOptions {
225    /// If provided, outputs the completion file for given shell
226    #[arg(value_enum)]
227    pub shell: Shell,
228}