use regex::Regex;
use std::fmt;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::str;
pub struct Region {
pub name: String,
pub st: u64,
pub en: u64,
pub id: String,
}
impl fmt::Display for Region {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}-{}", self.name, self.st + 1, self.en)
}
}
pub fn has_overlap(rgn1: &Region, rgn2: &Region) -> bool {
if rgn1.name != rgn2.name {
return false;
}
rgn1.en > rgn2.st && rgn1.st < rgn2.en
}
pub fn parse_region(region: &str) -> Region {
let re = Regex::new(r"(.+):([0-9]+)-([0-9]+)").unwrap();
let caps = re.captures(region).expect("Failed to parse region string.");
let name = caps.get(1).unwrap().as_str().to_string();
let st = caps.get(2).unwrap().as_str().parse::<u64>().unwrap() - 1;
let en = caps.get(3).unwrap().as_str().parse().unwrap_or(4294967295); let id = caps
.get(4)
.map_or(format!("{}:{}-{}", name, st + 1, en), |m| {
m.as_str().to_string()
});
Region { name, st, en, id }
}
pub fn parse_bed_rec(region: &str) -> Region {
let re = Regex::new(r"([^\s]+)\t([0-9]+)\t([0-9]+)\t?([^\s]+)?.*").unwrap();
let caps = re.captures(region).expect("Failed to parse region string.");
let name = caps.get(1).unwrap().as_str().to_string();
let st = caps.get(2).unwrap().as_str().parse::<u64>().unwrap();
let en = caps.get(3).unwrap().as_str().parse().unwrap_or(4294967295); let id = caps
.get(4)
.map_or(format!("{}:{}-{}", name, st + 1, en), |m| {
m.as_str().to_string()
});
Region { name, st, en, id }
}
pub fn parse_bed(filename: &str) -> Vec<Region> {
let file = File::open(filename).unwrap();
let reader = BufReader::new(file);
let mut vec = Vec::new();
for (idx, line) in reader.lines().enumerate() {
eprint!("\rReading bed line: {}", idx + 1);
let line = line.unwrap(); vec.push(parse_bed_rec(&line));
}
eprintln!();
vec
}
pub fn split_region(rgn: &Region, window: u64) -> Vec<Region> {
let mut start = rgn.st;
let mut small_rgns = Vec::new();
while start < rgn.en {
let mut end = start + window;
if end > rgn.en {
end = rgn.en;
}
let tmprgn = Region {
name: rgn.name.clone(),
st: start,
en: end,
id: rgn.id.clone(),
};
small_rgns.push(tmprgn);
start = end;
}
small_rgns
}