use crate::utils::Chromosome;
use flate2::read::MultiGzDecoder;
use gtars_core::utils::get_file_info;
use noodles::bam;
use std::error::Error;
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::ops::Deref;
use std::path::{Path, PathBuf};
use gtars_core::utils::parse_bedlike_file;
pub fn create_chrom_vec_default_score(combinedbedpath: &str) -> Vec<Chromosome> {
let default_score = 1; let path = Path::new(combinedbedpath);
let pathbuf = PathBuf::from(combinedbedpath);
let file_info = get_file_info(&pathbuf);
let is_gzipped = file_info.is_gzipped;
let file = File::open(path).unwrap();
let reader: Box<dyn Read> = match is_gzipped {
true => Box::new(MultiGzDecoder::new(file)),
false => Box::new(file),
};
let reader = BufReader::new(reader);
let mut chromosome = Chromosome {
chrom: "".to_string(),
starts: vec![],
ends: vec![],
};
let mut chromosome_vec: Vec<Chromosome> = Vec::new();
let mut chrom = String::new();
for line in reader.lines() {
let line_string = line.unwrap();
let s = line_string.as_str();
let (parsed_chr, parsed_start, parsed_end) = parse_bedlike_file(s).unwrap();
if chrom.is_empty() {
chromosome.chrom = String::from(parsed_chr.trim());
chrom = String::from(parsed_chr.trim());
chromosome.starts.push((parsed_start + 1, default_score)); chromosome.ends.push((parsed_end, default_score));
continue;
}
if *parsed_chr.trim() != chrom {
chromosome.starts.sort_unstable();
chromosome.ends.sort_unstable();
chromosome_vec.push(chromosome.clone());
chromosome.chrom = String::from(parsed_chr.trim());
chrom = String::from(parsed_chr.trim());
chromosome.starts = vec![];
chromosome.ends = vec![]
}
chromosome.starts.push((parsed_start + 1, default_score)); chromosome.ends.push((parsed_end, default_score));
}
chromosome.starts.sort_unstable();
chromosome.ends.sort_unstable();
chromosome_vec.push(chromosome.clone());
println!("Reading Bed file complete.");
chromosome_vec
}
pub fn create_chrom_vec_scores(combinedbedpath: &str) -> Vec<Chromosome> {
let path = Path::new(combinedbedpath);
let pathbuf = PathBuf::from(combinedbedpath);
let file_info = get_file_info(&pathbuf);
let is_gzipped = file_info.is_gzipped;
let file = File::open(path).unwrap();
let reader: Box<dyn Read> = match is_gzipped {
true => Box::new(MultiGzDecoder::new(file)),
false => Box::new(file),
};
let reader = BufReader::new(reader);
let mut npchromosome = Chromosome {
chrom: "".to_string(),
starts: vec![],
ends: vec![],
};
let mut chromosome_vec: Vec<Chromosome> = Vec::new();
let mut chrom = String::new();
for line in reader.lines() {
let line_string = line.unwrap();
let s = line_string.as_str();
let (parsed_chr, parsed_start, parsed_end, parsed_score) =
parse_bedlike_file_with_scores(s).unwrap();
if chrom.is_empty() {
npchromosome.chrom = String::from(parsed_chr.trim());
chrom = String::from(parsed_chr.trim());
npchromosome.starts.push((parsed_start + 1, parsed_score)); npchromosome.ends.push((parsed_end, parsed_score));
continue;
}
if *parsed_chr.trim() != chrom {
npchromosome.starts.sort_unstable_by(|a, b| a.0.cmp(&b.0));
npchromosome.ends.sort_unstable_by(|a, b| a.0.cmp(&b.0));
chromosome_vec.push(npchromosome.clone());
npchromosome.chrom = String::from(parsed_chr.trim());
chrom = String::from(parsed_chr.trim());
npchromosome.starts = vec![];
npchromosome.ends = vec![]
}
npchromosome.starts.push((parsed_start + 1, parsed_score)); npchromosome.ends.push((parsed_end, parsed_score));
}
npchromosome.starts.sort_unstable_by(|a, b| a.0.cmp(&b.0));
npchromosome.ends.sort_unstable_by(|a, b| a.0.cmp(&b.0));
chromosome_vec.push(npchromosome.clone());
println!("Reading narrowPeak file complete.");
chromosome_vec
}
pub fn parse_bedlike_file_with_scores(line: &str) -> Option<(String, i32, i32, i32)> {
let mut fields = line.split('\t');
let ctg = fields.next()?;
let st = fields
.next()
.and_then(|s| s.parse::<i32>().ok())
.unwrap_or(-1);
let en = fields
.next()
.and_then(|s| s.parse::<i32>().ok())
.unwrap_or(-1);
let _ = fields.next();
let narrow_peak_score = fields
.next()
.and_then(|s| s.parse::<i32>().ok())
.unwrap_or(-1);
Some((ctg.parse().unwrap(), st, en, narrow_peak_score))
}
pub fn read_chromosome_sizes(
chrom_size_path: &str,
) -> Result<std::collections::HashMap<String, u32>, Box<dyn Error>> {
let chrom_size_file = File::open(Path::new(chrom_size_path))?;
let path = Path::new(chrom_size_path);
let extension = path.extension().and_then(|ext| ext.to_str());
let mut chrom_sizes = std::collections::HashMap::new();
let reader = BufReader::new(chrom_size_file);
match extension {
Some("bed") | Some("narrowPeak") => {
for line in reader.lines() {
let line = line?; let mut iter = line.split('\t');
let chrom_name = iter.next().unwrap().to_owned();
let _ = iter.next().unwrap();
let size_str = iter.next().unwrap();
let size = size_str.parse::<u32>()?;
chrom_sizes.insert(chrom_name, size);
}
}
Some("sizes") => {
for line in reader.lines() {
let line = line?; let mut iter = line.split_whitespace();
let chrom_name = iter.next().unwrap().to_owned();
let size_str = iter.next().unwrap();
let size = size_str.parse::<u32>()?;
chrom_sizes.insert(chrom_name, size);
}
}
_ => {
panic!("Unsupported file type: {}", chrom_size_path);
}
}
Ok(chrom_sizes)
}
pub fn read_bam_header(filepath: &str) -> Vec<Chromosome> {
let mut reader = bam::io::reader::Builder.build_from_path(filepath).unwrap();
let header = reader.read_header();
let references = header.unwrap();
let references = references.reference_sequences();
let mut chromosome = Chromosome {
chrom: "".to_string(),
starts: vec![],
ends: vec![],
};
let mut chromosome_vec: Vec<Chromosome> = Vec::new();
for ref_key in references {
let chrom_name_vec = ref_key.0.deref().clone();
let chrom_name = String::from_utf8((*chrom_name_vec).to_owned()).unwrap();
chromosome.chrom = chrom_name;
chromosome.starts.push((0, 0)); chromosome.ends.push((0, 0)); chromosome_vec.push(chromosome.clone());
}
chromosome_vec
}