use clap::Parser;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[clap(
name = "gxf2bed",
version = env!("CARGO_PKG_VERSION"),
author = "Alejandro Gonzales-Irribarren <alejandrxgzi@gmail.com>",
about = "Fastest GTF/GFF-to-BED converter chilling around"
)]
pub struct Args {
#[clap(
short = 'i',
long = "input",
help = "Path to GTF/GFF file",
value_name = "GXF",
required = true
)]
pub gxf: PathBuf,
#[clap(
short = 'o',
long = "output",
help = "Path to output BED file",
value_name = "BED",
required = true
)]
pub output: PathBuf,
#[clap(
short = 'T',
long,
help = "Number of threads",
value_name = "THREADS",
default_value_t = num_cpus::get()
)]
pub threads: usize,
#[clap(
short = 'F',
long = "parent-feature",
help = "Parent feature",
value_name = "PARENT"
)]
pub parent_feature: Option<String>,
#[clap(
short = 'f',
long = "child-features",
help = "Child features",
value_name = "CHILDS",
value_delimiter = ',',
num_args = 1..,
)]
pub child_features: Option<Vec<String>>,
#[clap(
short = 'A',
long = "parent-attribute",
help = "Feature to extract",
value_name = "FEATURE"
)]
pub parent_attribute: Option<String>,
#[clap(
short = 'a',
long = "child-attribute",
help = "Child feature to extract",
value_name = "CHILD"
)]
pub child_attribute: Option<String>,
#[clap(
short = 't',
long = "type",
help = "BED type format",
value_name = "BED_TYPE",
default_value_t = BedType::Bed12
)]
pub bed_type: BedType,
#[clap(
short = 'd',
long = "additional-fields",
help = "BED additional fields",
value_name = "ADDITIONAL",
value_delimiter = ',',
num_args = 1..,
)]
pub additional_fields: Option<Vec<String>>,
#[clap(
short = 'c',
long = "chunks",
help = "Chunk size for parallel processing",
value_name = "CHUNKS",
default_value_t = 15000
)]
pub chunks: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BedType {
Bed3,
Bed4,
Bed5,
Bed6,
Bed9,
Bed12,
}
impl Default for BedType {
fn default() -> Self {
BedType::Bed12
}
}
impl std::str::FromStr for BedType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"3" => Ok(BedType::Bed3),
"4" => Ok(BedType::Bed4),
"5" => Ok(BedType::Bed5),
"6" => Ok(BedType::Bed6),
"9" => Ok(BedType::Bed9),
"12" => Ok(BedType::Bed12),
_ => Err(format!("Invalid BED type: {}", s)),
}
}
}
impl std::fmt::Display for BedType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
BedType::Bed3 => write!(f, "3"),
BedType::Bed4 => write!(f, "4"),
BedType::Bed5 => write!(f, "5"),
BedType::Bed6 => write!(f, "6"),
BedType::Bed9 => write!(f, "9"),
BedType::Bed12 => write!(f, "12"),
}
}
}