fibertools_rs/
lib.rs

1/// Data structure for fiberseq data
2pub mod fiber;
3pub mod m6a_burn;
4/// subcommands of fibertools-rs
5pub mod subcommands;
6pub mod utils;
7
8#[cfg(feature = "cli")]
9/// Command line interface for fibertools-rs.
10pub mod cli;
11
12use crate::utils::bio_io::*;
13use anyhow::Result;
14use itertools::Itertools;
15use lazy_static::lazy_static;
16use rust_htslib::bam::FetchDefinition;
17use rust_htslib::{bam, bam::Read};
18use std::env;
19use std::io::Write;
20
21pub const VERSION: &str = env!("CARGO_PKG_VERSION");
22lazy_static! {
23    pub static ref FULL_VERSION: String = format!(
24        "v{}\tgit-details {}",
25        env!("CARGO_PKG_VERSION"),
26        env!("VERGEN_GIT_DESCRIBE")
27    );
28}
29// if this string (bar)gets too long it displays weird when writing to stdout
30const PROGRESS_STYLE: &str =
31    "[{elapsed_precise:.yellow}] {bar:>35.cyan/blue} {human_pos:>5.cyan}/{human_len:.blue} {percent:>3.green}% {per_sec:<10.cyan}";
32
33/// COLORS
34pub const NUC_COLOR: &str = "169,169,169";
35pub const M6A_COLOR: &str = "128,0,128";
36pub const CPG_COLOR: &str = "139,69,19";
37pub const LINKER_COLOR: &str = "147,112,219";
38pub const FIRE_COLORS: [(f32, &str); 9] = [
39    (1.0, "139,0,0"),
40    (2.0, "175,0,0"),
41    (3.0, "200,0,0"),
42    (4.0, "225,0,0"),
43    (5.0, "255,0,0"),
44    (10.0, "255,140,0"),
45    (25.0, "225,225,0"),
46    (100.0, LINKER_COLOR),
47    (200.0, NUC_COLOR),
48];
49
50/// unzip a vector of tuples
51pub fn unzip_to_vectors<T, U>(vec: Vec<(T, U)>) -> (Vec<T>, Vec<U>) {
52    vec.into_iter().unzip()
53}
54
55/// join a vector with commas
56pub fn join_by_str<'a, I, Z>(vals: I, sep: &str) -> String
57where
58    I: IntoIterator<Item = Z>,
59    Z: ToString + 'a,
60{
61    vals.into_iter().map(|v| v.to_string() + sep).collect()
62}
63
64/// join a vector with commas
65pub fn join_by_str_option(vals: &[Option<i64>], sep: &str) -> String {
66    vals.iter()
67        .map(|v| match v {
68            Some(v) => v.to_string(),
69            None => String::from("NA"),
70        })
71        .map(|v| v + sep)
72        .collect()
73}
74
75/// join a vector with commas
76pub fn join_by_str_option_can_skip(vals: &[Option<i64>], sep: &str, skip_none: bool) -> String {
77    vals.iter()
78        .map(|v| match v {
79            Some(v) => v.to_string(),
80            None => {
81                if skip_none {
82                    String::from("")
83                } else {
84                    String::from("NA")
85                }
86            }
87        })
88        .filter(|v| !v.is_empty())
89        .map(|v| v + sep)
90        .collect()
91}
92
93pub fn region_parser(rgn: &str) -> (FetchDefinition<'_>, String) {
94    if rgn.contains(':') {
95        let (chrom, rest) = rgn.split(':').collect_tuple().unwrap();
96        let (start, end) = rest.split('-').collect_tuple().unwrap();
97        let st: i64 = start
98            .replace(',', "")
99            .parse()
100            .unwrap_or_else(|_| panic!("Could not parse start of region: {start}"));
101        (
102            FetchDefinition::RegionString(
103                chrom.as_bytes(),
104                st,
105                end.replace(',', "")
106                    .parse()
107                    .unwrap_or_else(|_| panic!("Could not parse end of region: {end}")),
108            ),
109            chrom.to_string(),
110        )
111    } else {
112        (FetchDefinition::String(rgn.as_bytes()), rgn.to_string())
113    }
114}