|
|
@@ -1,10 +1,14 @@
|
|
|
-use std::{fs, path::Path, thread};
|
|
|
+use std::{
|
|
|
+ fs::{self},
|
|
|
+ path::{Path, PathBuf},
|
|
|
+ thread,
|
|
|
+};
|
|
|
|
|
|
use anyhow::Context;
|
|
|
-use log::info;
|
|
|
+use log::{error, info, warn};
|
|
|
|
|
|
use crate::{
|
|
|
- commands::bcftools::{bcftools_keep_pass, BcftoolsConfig},
|
|
|
+ commands::bcftools::{bcftools_concat, bcftools_keep_pass, BcftoolsConfig},
|
|
|
runners::{run_wait, CommandRun, RunReport},
|
|
|
};
|
|
|
|
|
|
@@ -292,3 +296,115 @@ pub fn nanomonsv_get(
|
|
|
let res = run_wait(&mut cmd_run)?;
|
|
|
Ok(res)
|
|
|
}
|
|
|
+
|
|
|
+pub fn nanomonsv_create_pon(config: NanomonSVConfig, pon_path: &str) -> anyhow::Result<()> {
|
|
|
+ let mut passed_mrd = Vec::new();
|
|
|
+ for mrd_dir in find_nanomonsv_dirs(&PathBuf::from(&config.result_dir), "mrd", 0, 3) {
|
|
|
+ let mut passed = None;
|
|
|
+ let mut passed_csi = None;
|
|
|
+ let mut result = None;
|
|
|
+
|
|
|
+ for entry in fs::read_dir(&mrd_dir)
|
|
|
+ .with_context(|| format!("Failed to read directory: {}", mrd_dir.display()))?
|
|
|
+ {
|
|
|
+ let entry =
|
|
|
+ entry.with_context(|| format!("Failed to read entry in: {}", mrd_dir.display()))?;
|
|
|
+ let file_name = entry.file_name().to_string_lossy().to_string();
|
|
|
+ let path = entry.path();
|
|
|
+
|
|
|
+ if file_name.ends_with("_mrd_nanomonsv_PASSED.vcf.gz") {
|
|
|
+ passed = Some(path);
|
|
|
+ } else if file_name.ends_with("_mrd_nanomonsv_PASSED.vcf.gz.csi") {
|
|
|
+ passed_csi = Some(path);
|
|
|
+ } else if file_name.ends_with("_mrd.nanomonsv.result.vcf") {
|
|
|
+ result = Some(path);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ match (result, passed.clone(), passed_csi) {
|
|
|
+ (None, None, None) => error!("No result in {}", mrd_dir.display()),
|
|
|
+ (Some(p), None, None) => {
|
|
|
+ let output = replace_filename_suffix(
|
|
|
+ &p,
|
|
|
+ "_mrd.nanomonsv.result.vcf",
|
|
|
+ "_mrd_nanomonsv_PASSED.vcf.gz",
|
|
|
+ );
|
|
|
+ info!("Do pass for {} to {}", p.display(), output.display());
|
|
|
+
|
|
|
+ if let Err(r) = bcftools_keep_pass(
|
|
|
+ p.to_str().unwrap(),
|
|
|
+ output.to_str().unwrap(),
|
|
|
+ BcftoolsConfig::default(),
|
|
|
+ ) {
|
|
|
+ error!("{r}");
|
|
|
+ } else {
|
|
|
+ passed_mrd.push(output);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ (Some(_), Some(p), None) => warn!("Do csi for {}", p.display()),
|
|
|
+ (Some(_), Some(p), Some(_)) => passed_mrd.push(p),
|
|
|
+ _ => {} // All files found
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ println!("{} vcf to concat", passed_mrd.len());
|
|
|
+ bcftools_concat(
|
|
|
+ passed_mrd
|
|
|
+ .iter()
|
|
|
+ .map(|p| p.to_string_lossy().to_string())
|
|
|
+ .collect(),
|
|
|
+ pon_path,
|
|
|
+ BcftoolsConfig::default(),
|
|
|
+ )?;
|
|
|
+
|
|
|
+ Ok(())
|
|
|
+}
|
|
|
+
|
|
|
+pub fn find_nanomonsv_dirs(
|
|
|
+ root: &Path,
|
|
|
+ time_point: &str,
|
|
|
+ depth: usize,
|
|
|
+ max_depth: usize,
|
|
|
+) -> Vec<PathBuf> {
|
|
|
+ if depth >= max_depth {
|
|
|
+ return Vec::new();
|
|
|
+ }
|
|
|
+
|
|
|
+ let entries: Vec<_> = match fs::read_dir(root) {
|
|
|
+ Ok(entries) => entries.filter_map(Result::ok).collect(),
|
|
|
+ Err(_) => return Vec::new(),
|
|
|
+ };
|
|
|
+
|
|
|
+ let mut result: Vec<PathBuf> = entries
|
|
|
+ .iter()
|
|
|
+ .filter_map(|entry| {
|
|
|
+ let path = entry.path();
|
|
|
+ if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false)
|
|
|
+ && path
|
|
|
+ .to_string_lossy()
|
|
|
+ .contains(&format!("{}/nanomonsv", time_point))
|
|
|
+ {
|
|
|
+ Some(path)
|
|
|
+ } else {
|
|
|
+ None
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .collect();
|
|
|
+
|
|
|
+ result.extend(
|
|
|
+ entries
|
|
|
+ .iter()
|
|
|
+ .filter(|entry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
|
|
|
+ .flat_map(|dir| find_nanomonsv_dirs(&dir.path(), time_point, depth + 1, max_depth)),
|
|
|
+ );
|
|
|
+
|
|
|
+ result
|
|
|
+}
|
|
|
+
|
|
|
+pub fn replace_filename_suffix(path: &Path, from: &str, to: &str) -> PathBuf {
|
|
|
+ let file_name = path.file_name().and_then(|s| s.to_str()).unwrap_or("");
|
|
|
+
|
|
|
+ let new_file_name = file_name.replace(from, to);
|
|
|
+
|
|
|
+ path.with_file_name(new_file_name)
|
|
|
+}
|