rsomics_wig_to_bed/
lib.rs1use std::fs::File;
2use std::io::{BufRead, BufReader, BufWriter, Write};
3use std::path::Path;
4
5use rsomics_common::{Result, RsomicsError};
6
7pub fn wig_to_bed(input: &Path, threshold: f64, output: &mut dyn Write) -> Result<u64> {
8 let file = File::open(input)
9 .map_err(|e| RsomicsError::InvalidInput(format!("{}: {e}", input.display())))?;
10 let reader = BufReader::new(file);
11 let mut out = BufWriter::new(output);
12
13 let mut chrom = String::new();
14 let mut pos: u64 = 0;
15 let mut step: u64 = 1;
16 let mut span: u64 = 1;
17 let mut count: u64 = 0;
18
19 for line in reader.lines() {
20 let line = line.map_err(RsomicsError::Io)?;
21 let line = line.trim();
22
23 if line.is_empty() || line.starts_with('#') || line.starts_with("track") {
24 continue;
25 }
26
27 if line.starts_with("fixedStep") || line.starts_with("variableStep") {
28 for part in line.split_whitespace() {
29 if let Some(val) = part.strip_prefix("chrom=") {
30 chrom = val.to_string();
31 } else if let Some(val) = part.strip_prefix("start=") {
32 pos = val.parse().unwrap_or(1) - 1;
33 } else if let Some(val) = part.strip_prefix("step=") {
34 step = val.parse().unwrap_or(1);
35 } else if let Some(val) = part.strip_prefix("span=") {
36 span = val.parse().unwrap_or(1);
37 }
38 }
39 continue;
40 }
41
42 let parts: Vec<&str> = line.split('\t').collect();
43 if parts.len() >= 4 {
44 let c = parts[0];
45 let s: u64 = parts[1].parse().unwrap_or(0);
46 let e: u64 = parts[2].parse().unwrap_or(0);
47 let v: f64 = parts[3].parse().unwrap_or(0.0);
48 if v >= threshold {
49 writeln!(out, "{c}\t{s}\t{e}\t{v}").map_err(RsomicsError::Io)?;
50 count += 1;
51 }
52 } else if let Ok(val) = line.parse::<f64>() {
53 if val >= threshold {
54 writeln!(out, "{chrom}\t{pos}\t{}\t{val}", pos + span).map_err(RsomicsError::Io)?;
55 count += 1;
56 }
57 pos += step;
58 }
59 }
60
61 out.flush().map_err(RsomicsError::Io)?;
62 Ok(count)
63}