| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- use std::path::{Path, PathBuf};
- use anyhow::{Ok, Result};
- use uuid::Uuid;
- use crate::{
- commands::{
- CapturedOutput, Command as JobCommand, LocalBatchRunner, LocalRunner, SbatchRunner,
- SlurmParams, SlurmRunner,
- },
- config::Config,
- run,
- };
- use super::{cosmic::Cosmic, gnomad::GnomAD};
- pub struct EchtvarJob {
- pub input_vcf: PathBuf,
- pub output_vcf: PathBuf,
- pub config: Config,
- }
- impl JobCommand for EchtvarJob {
- fn cmd(&self) -> String {
- let sources = self
- .config
- .echtvar_sources
- .iter()
- .map(|e| format!("-e {e}"))
- .collect::<Vec<String>>()
- .join(" ");
- format!(
- "{echtvar_bin} anno {sources} {input_vcf} {output_vcf}",
- echtvar_bin = self.config.echtvar_bin,
- sources = sources,
- input_vcf = self.input_vcf.display(),
- output_vcf = self.output_vcf.display()
- )
- }
- }
- impl LocalRunner for EchtvarJob {}
- impl LocalBatchRunner for EchtvarJob {}
- impl SlurmRunner for EchtvarJob {
- fn slurm_args(&self) -> Vec<String> {
- SlurmParams {
- job_name: Some(format!("echtvar_{}", Uuid::new_v4())),
- cpus_per_task: Some(1),
- mem: Some("20G".into()),
- partition: Some("shortq".into()),
- gres: None,
- }
- .to_args()
- }
- }
- impl SbatchRunner for EchtvarJob {
- fn slurm_params(&self) -> SlurmParams {
- SlurmParams {
- job_name: Some(format!("echtvar_{}", Uuid::new_v4())),
- cpus_per_task: Some(1),
- mem: Some("20G".into()),
- partition: Some("shortq".into()),
- gres: None,
- }
- }
- }
- pub fn run_echtvar(
- in_path: impl AsRef<Path>,
- output_vcf: impl AsRef<Path>,
- config: &Config,
- ) -> Result<CapturedOutput> {
- let mut job = EchtvarJob {
- input_vcf: in_path.as_ref().into(),
- output_vcf: output_vcf.as_ref().into(),
- config: config.clone(),
- };
- run!(config, &mut job)
- }
- pub fn parse_echtvar_val(s: &str) -> Result<(Option<Cosmic>, Option<GnomAD>)> {
- let mut cosmic_parts = Vec::new();
- let mut gnomad_parts = Vec::new();
- for part in s.split(';').map(str::trim).filter(|p| !p.is_empty()) {
- if part.starts_with("gnomad_") {
- gnomad_parts.push(part);
- } else {
- cosmic_parts.push(part);
- }
- }
- // COSMIC: missing if CNT is absent or CNT is -1 or MISSING
- let cosmic = {
- let cnt = cosmic_parts.iter().find(|p| p.starts_with("CNT=")).copied();
- match cnt {
- Some("CNT=-1") | Some("CNT=MISSING") | None => None,
- Some(_) => Some(cosmic_parts.join(";").parse::<Cosmic>()?),
- }
- };
- // gnomAD: your choice; this keeps your "all -1 => None" behavior
- let gnomad = if gnomad_parts.is_empty() || gnomad_parts.iter().all(|p| p.ends_with("=-1")) {
- None
- } else {
- Some(gnomad_parts.join(";").parse::<GnomAD>()?)
- };
- Ok((cosmic, gnomad))
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- use crate::{
- annotation::{Annotation, Annotations, Caller, Sample},
- helpers::test_init,
- variant::{variant_collection::ExternalAnnotation, vcf_variant::VcfVariant},
- };
- #[test]
- fn echtvar_parse() -> anyhow::Result<()> {
- test_init();
- let s = "gnomad_ac=1;gnomad_an=-1;gnomad_af=-1;gnomad_af_oth=-1;gnomad_af_ami=-1;gnomad_af_sas=-1;gnomad_af_fin=-1;gnomad_af_eas=-1;gnomad_af_amr=-1;gnomad_af_afr=-1;gnomad_af_mid=-1;gnomad_af_asj=-1;gnomad_af_nfe=-1;CNT=188";
- let (cosmic, _gnomad) = parse_echtvar_val(s)?;
- println!("{cosmic:#?}");
- Ok(())
- }
- #[test]
- fn echtvar_run() -> anyhow::Result<()> {
- test_init();
- let config = Config::default();
- let variants: Vec<VcfVariant> = vec![
- "chr12\t25116560\t.\tC\tG\t18.2\tPASS\t.\tGT:GQ:DP:AD:VAF:PL\t1/1:18:45:37,7:0.155556:18,25,0".parse()?,
- "chr1\t5619\trs1470452993\tA\tC \t.\tPASS\t.\t.\t.".parse()?
- ];
- let annotations = Annotations::default();
- let caller = Annotation::Callers(Caller::ClairS, Sample::Somatic);
- variants.iter().for_each(|v| {
- annotations.insert_update(v.hash(), std::slice::from_ref(&caller));
- });
- let ext_annot = ExternalAnnotation::init("TEST", &config)?;
- ext_annot.annotate(&variants, &annotations)?;
- println!("{annotations:#?}");
- Ok(())
- }
- }
|