diff --git a/Cargo.toml b/Cargo.toml index dad80e8..6aa5f64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimap2" -version = "0.1.20+minimap2.2.28" +version = "0.1.21+minimap2.2.28" edition = "2021" authors = ["Joseph Guhlin "] license = "MIT OR Apache-2.0" @@ -24,21 +24,17 @@ exclude = [ members = [] -exclude = [ - "minimappers2", - "fakeminimap2", - "minimap2-sys" -] +exclude = ["minimappers2", "fakeminimap2", "minimap2-sys"] [dependencies] libc = "0.2" -simdutf8 = {version = "0.1", optional = true} -needletail = { version = "0.5", optional = true, default-features = false} +simdutf8 = { version = "0.1", optional = true } +needletail = { version = "0.6", optional = true, default-features = false} # Dep for development minimap2-sys = { path = "./minimap2-sys" } # minimap2-sys = "0.1.19" -rust-htslib = { version = "0.47", default-features = false, optional = true } +rust-htslib = { version = "0.48", default-features = false, optional = true } [dev-dependencies] rayon = "1.10" diff --git a/minimap2-sys/Cargo.lock b/minimap2-sys/Cargo.lock index 2c26ee5..bd6bd6b 100644 --- a/minimap2-sys/Cargo.lock +++ b/minimap2-sys/Cargo.lock @@ -13,23 +13,20 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.4" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ "bitflags", "cexpr", "clang-sys", "itertools", - "lazy_static", - "lazycell", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn", - "which", ] [[package]] @@ -40,9 +37,12 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "cc" -version = "1.1.7" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +dependencies = [ + "shlex", +] [[package]] name = "cexpr" @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] @@ -85,57 +85,26 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys", -] - [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" -version = "0.2.155" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libloading" @@ -149,9 +118,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.18" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "cmake", @@ -160,12 +129,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - [[package]] name = "memchr" version = "2.7.4" @@ -198,41 +161,35 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -242,9 +199,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -253,9 +210,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-hash" @@ -263,19 +220,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "shlex" version = "1.3.0" @@ -284,9 +228,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -295,9 +239,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "vcpkg" @@ -305,27 +249,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-targets" version = "0.52.6" diff --git a/minimap2-sys/Cargo.toml b/minimap2-sys/Cargo.toml index 1d93468..17cf0eb 100644 --- a/minimap2-sys/Cargo.toml +++ b/minimap2-sys/Cargo.toml @@ -33,19 +33,19 @@ exclude = [ crate-type = ["cdylib", "rlib"] [dependencies] -libz-sys = { version = "1.1.17", default-features = false, features = ["libc"] } +libz-sys = { version = "1.1", default-features = false, features = ["libc"] } [build-dependencies] -pkg-config = "0.3.30" +pkg-config = "0.3" [build-dependencies.bindgen] optional = true -version = "0.69.4" +version = "0.70" default-features = false features = ["which-rustfmt", "runtime"] [build-dependencies.cc] -version = "1.1" +version = "1.2" [features] default = [] # "libz-sys/libc" diff --git a/minimap2-sys/build.rs b/minimap2-sys/build.rs index 28c274f..c4f800b 100644 --- a/minimap2-sys/build.rs +++ b/minimap2-sys/build.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; // Configure for minimap2 fn configure(mut cc: &mut cc::Build) { println!("cargo:rerun-if-changed=minimap2/*.c"); - + cc.include("minimap2"); cc.opt_level(2); @@ -28,17 +28,17 @@ fn configure(mut cc: &mut cc::Build) { if file.file_name().unwrap() == "main.c" || file.file_name().unwrap() == "example.c" { continue; } - + // Ignore all "neon" if file.file_name().unwrap().to_str().unwrap().contains("neon") { continue; } - + // Ignore all "ksw" if file.file_name().unwrap().to_str().unwrap().contains("ksw") { continue; } - + if let Some(x) = file.extension() { if x == "c" { println!("Compiling: {:?}", file); @@ -54,7 +54,6 @@ fn configure(mut cc: &mut cc::Build) { } fn target_specific(cc: &mut cc::Build) { - // let host = env::var("HOST").unwrap(); let target = env::var("TARGET").unwrap(); @@ -87,7 +86,7 @@ fn target_specific(cc: &mut cc::Build) { cc.file("minimap2/ksw2_extz2_neon.c"); cc.file("minimap2/ksw2_extd2_neon.c"); cc.file("minimap2/ksw2_exts2_neon.c"); - + cc.flag("-D_FILE_OFFSET_BITS=64"); cc.flag("-fsigned-char"); cc.flag("-Isse2neon"); @@ -125,7 +124,6 @@ fn simde(cc: &mut cc::Build) { } fn compile() { - let mut cc = cc::Build::new(); let out_path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); @@ -173,7 +171,6 @@ fn compile() { let lib = lib.to_str().unwrap(); println!("cargo:rustc-link-search=native={}", lib); println!("cargo:rustc-link-lib=static=z"); - } } @@ -216,11 +213,11 @@ fn gen_bindings() { let out_path = PathBuf::from(env::var_os("OUT_DIR").unwrap()); let mut bindgen = bindgen::Builder::default() - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .rustfmt_bindings(true); + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .rustfmt_bindings(true); let mut bindgen = bindgen.header("minimap2.h"); - + bindgen .generate_cstr(true) .generate() @@ -232,7 +229,7 @@ fn gen_bindings() { #[cfg(not(feature = "bindgen"))] fn gen_bindings() {} -fn main() { +fn main() { compile(); gen_bindings(); } diff --git a/src/lib.rs b/src/lib.rs index 012f10c..d29bb4c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ //! //! let seq = b"ACTGACTCACATCGACTACGACTACTAGACACTAGACTATCGACTACTGACATCGA"; //! let alignment = aligner -//! .map(seq, false, false, None, None) +//! .map(seq, false, false, None, None, Some("Sample Query")) //! .expect("Unable to align"); //! ``` //! @@ -40,15 +40,18 @@ //! # let seq = "CGGCACCAGGTTAAAATCTGAGTGCTGCAATAGGCGATTACAGTACAGCACCCAGCCTCCGAAATTCTTTAACGGTCGTCGTCTCGATACTGCCACTATGCCTTTATATTATTGTCTTCAGGTGATGCTGCAGATCGTGCAGACGGGTGGCTTTAGTGTTGTGGGATGCATAGCTATTGACGGATCTTTGTCAATTGACAGAAATACGGGTCTCTGGTTTGACATGAAGGTCCAACTGTAATAACTGATTTTATCTGTGGGTGATGCGTTTCTCGGACAACCACGACCGCGACCAGACTTAAGTCTGGGCGCGGTCGTGGTTGTCCGAGAAACGCATCACCCACAGATAAAATCAGTTATTACAGTTGGACCTTTATGTCAAACCAGAGACCCGTATTTC"; //! let aligner = Aligner::builder().map_ont().with_seq(seq.as_bytes()).expect("Unable to build index"); //! let query = b"CGGCACCAGGTTAAAATCTGAGTGCTGCAATAGGCGATTACAGTACAGCACCCAGCCTCCG"; -//! let hits = aligner.map(query, false, false, None, None); +//! let hits = aligner.map(query, false, false, None, None, Some("Query Name")); //! assert_eq!(hits.unwrap().len(), 1); //! ``` +use std::borrow::Cow; use std::cell::RefCell; +use std::ffi::{CStr, CString}; use std::mem::MaybeUninit; use std::num::NonZeroI32; use std::path::Path; +use std::sync::Arc; use std::os::unix::ffi::OsStrExt; @@ -198,19 +201,19 @@ pub struct Alignment { pub cigar_str: Option, pub md: Option, pub cs: Option, - pub alignment_score: Option, + pub alignment_score: Option, } /// Mapping result #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct Mapping { // The query sequence name. - pub query_name: Option, + pub query_name: Option>, pub query_len: Option, pub query_start: i32, pub query_end: i32, pub strand: Strand, - pub target_name: Option, + pub target_name: Option>, pub target_len: i32, pub target_start: i32, pub target_end: i32, @@ -349,11 +352,17 @@ impl Aligner { impl Aligner { /// Ergonomic function for Aligner. Sets the minimap2 preset to lr:hq. + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. pub fn lrhq(self) -> Self { self.preset(Preset::LrHq) } /// Ergonomic function for Aligner. Sets the minimap2 preset to splice + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().splice(); @@ -363,6 +372,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to splice:hq + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().splice_hq(); @@ -372,6 +384,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to Asm + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().asm(); @@ -381,6 +396,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to Asm5 + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().asm5(); @@ -389,6 +407,9 @@ impl Aligner { self.preset(Preset::Asm5) } /// Ergonomic function for Aligner. Sets the minimap2 preset to Asm10 + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().asm10(); @@ -397,6 +418,9 @@ impl Aligner { self.preset(Preset::Asm10) } /// Ergonomic function for Aligner. Sets the minimap2 preset to Asm20 + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().asm20(); @@ -406,6 +430,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to sr + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().sr(); @@ -415,6 +442,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to MapPb + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().map_pb(); @@ -424,6 +454,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to MapHifi + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().map_hifi(); @@ -433,6 +466,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to MapOnt. + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().map_ont(); @@ -442,6 +478,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to AvaPb + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().ava_pb(); @@ -451,6 +490,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to AvaOnt. + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().ava_ont(); @@ -460,6 +502,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to Short + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().short(); @@ -469,6 +514,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to Map10k + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().map10k(); @@ -478,6 +526,9 @@ impl Aligner { } /// Ergonomic function for Aligner. Sets the minimap2 preset to cdna + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. /// ``` /// # use minimap2::*; /// Aligner::builder().cdna(); @@ -487,19 +538,22 @@ impl Aligner { } /// Create an aligner using a preset. - pub fn preset(self, preset: Preset) -> Self { - let mut idxopt = IdxOpt::default(); - let mut mapopt = MapOpt::default(); + /// + /// Presets should be called before any other options are set, as they change multiple + /// options at once. + pub fn preset(mut self, preset: Preset) -> Self { + // let mut idxopt = IdxOpt::default(); + // let mut mapopt = MapOpt::default(); unsafe { - mm_set_opt(&0, &mut idxopt, &mut mapopt); - mm_set_opt(preset.into(), &mut idxopt, &mut mapopt) + mm_set_opt(&0, &mut self.idxopt, &mut self.mapopt); + mm_set_opt(preset.into(), &mut self.idxopt, &mut self.mapopt) }; Self { - idxopt, - mapopt, - ..Default::default() + idxopt: self.idxopt, + mapopt: self.mapopt, + ..self } } @@ -558,9 +612,7 @@ impl Aligner { // Check options pub fn check_opts(&self) -> Result<(), &'static str> { - let result = unsafe { - mm_check_opt(&self.idxopt, &self.mapopt) - }; + let result = unsafe { mm_check_opt(&self.idxopt, &self.mapopt) }; if result == 0 { Ok(()) @@ -569,7 +621,6 @@ impl Aligner { } } - /// Set index parameters for minimap2 using builder pattern /// Creates the index as well with the given number of threads (set at struct creation). /// You must set the number of threads before calling this function. @@ -671,7 +722,7 @@ impl Aligner { /// # let seq = "CGGCACCAGGTTAAAATCTGAGTGCTGCAATAGGCGATTACAGTACAGCACCCAGCCTCCGAAATTCTTTAACGGTCGTCGTCTCGATACTGCCACTATGCCTTTATATTATTGTCTTCAGGTGATGCTGCAGATCGTGCAGACGGGTGGCTTTAGTGTTGTGGGATGCATAGCTATTGACGGATCTTTGTCAATTGACAGAAATACGGGTCTCTGGTTTGACATGAAGGTCCAACTGTAATAACTGATTTTATCTGTGGGTGATGCGTTTCTCGGACAACCACGACCGCGACCAGACTTAAGTCTGGGCGCGGTCGTGGTTGTCCGAGAAACGCATCACCCACAGATAAAATCAGTTATTACAGTTGGACCTTTATGTCAAACCAGAGACCCGTATTTC"; /// let aligner = Aligner::builder().map_ont().with_seq(seq.as_bytes()).expect("Unable to build index"); /// let query = b"CGGCACCAGGTTAAAATCTGAGTGCTGCAATAGGCGATTACAGTACAGCACCCAGCCTCCG"; - /// let hits = aligner.map(query, false, false, None, None); + /// let hits = aligner.map(query, false, false, None, None, Some("Query Name")); /// assert_eq!(hits.unwrap().len(), 1); /// ``` pub fn with_seq(self, seq: &[u8]) -> Result @@ -690,9 +741,9 @@ impl Aligner { /// # let id = "seq1"; /// let aligner = Aligner::builder().map_ont().with_seq_and_id(seq.as_bytes(), id.as_bytes()).expect("Unable to build index"); /// let query = b"CGGCACCAGGTTAAAATCTGAGTGCTGCAATAGGCGATTACAGTACAGCACCCAGCCTCCG"; - /// let hits = aligner.map(query, false, false, None, None); + /// let hits = aligner.map(query, false, false, None, None, Some("Sample Query")); /// assert_eq!(hits.as_ref().unwrap().len(), 1); - /// assert_eq!(hits.as_ref().unwrap()[0].target_name.as_ref().unwrap(), id); + /// assert_eq!(hits.as_ref().unwrap()[0].target_name.as_ref().unwrap().as_str(), id); /// ``` pub fn with_seq_and_id(self, seq: &[u8], id: &[u8]) -> Result // where T: AsRef<[u8]> + std::ops::Deref, @@ -790,7 +841,7 @@ impl Aligner { md: bool, // TODO max_frag_len: Option, extra_flags: Option<&[u64]>, - query_name: Option<&[u8]>, + query_name: Option>, ) -> Result, &'static str> { // Make sure index is set if !self.has_index() { @@ -802,6 +853,24 @@ impl Aligner { return Err("Sequence is empty"); } + let mut qname_cstring = None; + + let query_name_cstr: Option<&CStr> = match query_name.as_ref() { + None => None, + Some(qname_slice) => { + if qname_slice.as_ref().last() != Some(&b'\0') { + qname_cstring = + Some(CString::new(qname_slice.as_ref()).expect("Invalid query name")); + Some(qname_cstring.as_ref().unwrap().as_c_str()) + } else { + Some( + CStr::from_bytes_with_nul(query_name.as_ref().unwrap().as_ref()) + .expect("Invalid query name"), + ) + } + } + }; + let mut mm_reg: MaybeUninit<*mut mm_reg1_t> = MaybeUninit::uninit(); // Number of results @@ -820,11 +889,11 @@ impl Aligner { } } - let qname = match query_name { + let query_name_arc = query_name_cstr.map(|x| Arc::new(x.to_owned().into_string().unwrap())); + + let qname = match query_name_cstr { None => std::ptr::null(), - Some(qname) => { - qname.as_ptr() as *const ::std::os::raw::c_char - } + Some(qname) => qname.as_ref().as_ptr() as *const ::std::os::raw::c_char, }; let mappings = BUF.with(|buf| { @@ -852,9 +921,9 @@ impl Aligner { let contig: *mut ::std::os::raw::c_char = (*((*(self.idx.unwrap())).seq.offset(reg.rid as isize))).name; - let is_primary = reg.parent == reg.id; - let is_supplementary = reg.sam_pri() == 0; - + let is_primary = reg.parent == reg.id && (reg.sam_pri() > 0); + let is_supplementary = (reg.parent == reg.id) && (reg.sam_pri() == 0); + // todo holy heck this code is ugly let alignment = if !reg.p.is_null() { let p = &*reg.p; @@ -994,23 +1063,26 @@ impl Aligner { cigar_str, md: md_str, cs: cs_str, - alignment_score: Some(p.dp_score as u32), + alignment_score: Some(p.dp_score as i32), }) } else { None }; + + let target_name_arc = Arc::new( + std::ffi::CStr::from_ptr(contig) + .to_str() + .unwrap() + .to_string(), + ); + mappings.push(Mapping { - target_name: Some( - std::ffi::CStr::from_ptr(contig) - .to_str() - .unwrap() - .to_string(), - ), + target_name: Some(Arc::clone(&target_name_arc)), target_len: (*((*(self.idx.unwrap())).seq.offset(reg.rid as isize))).len as i32, target_start: reg.rs, target_end: reg.re, - query_name: query_name.map(|q| String::from_utf8_lossy(q).to_string()), + query_name: query_name_arc.clone(), query_len: NonZeroI32::new(seq.len() as i32), query_start: reg.qs, query_end: reg.qe, @@ -1079,16 +1151,17 @@ impl Aligner { } }; - let mut seq_mappings = self.map(&record.seq(), cs, md, None, None).unwrap(); + let query_name = record.id().to_vec(); + let mut seq_mappings = self + .map(&record.seq(), cs, md, None, None, Some(&query_name)) + .unwrap(); for mapping in seq_mappings.iter_mut() { let id = record.id(); - if !id.is_empty() { - mapping.query_name = Some(from_utf8(id).unwrap().to_string()); - } else { - mapping.query_name = Some( + if id.is_empty() { + mapping.query_name = Some(Arc::new( format!("Unnamed Seq with Length: {}", record.seq().len()).to_string(), - ); + )); } } @@ -1152,15 +1225,16 @@ mod tests { false, None, None, + Some("Sample Query") ) .unwrap(); - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); let jh = thread::spawn(move || { - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); aligner }); @@ -1168,9 +1242,9 @@ mod tests { let aligner = jh.join().unwrap(); let jh = thread::spawn(move || { - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); aligner }); @@ -1198,24 +1272,25 @@ mod tests { false, None, None, + Some("Sample Query") ) .unwrap(); - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); let aligner_handle = Arc::clone(&aligner); let jh0 = thread::spawn(move || { - let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); - let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); }); let aligner_handle = Arc::clone(&aligner); let jh1 = thread::spawn(move || { - let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); - let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner_handle.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); assert!(mappings[0].query_len == Some(NonZeroI32::new(350).unwrap())); }); } @@ -1254,7 +1329,14 @@ mod tests { .par_iter() .map(|seq| { aligner - .map(seq.as_bytes(), false, false, None, None) + .map( + seq.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .unwrap() }) .collect::>(); @@ -1363,13 +1445,14 @@ mod tests { false, None, None, + Some("Sample Query") ) .unwrap(); - let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("ACGGTAGAGAGGAAGAAGAAGGAATAGCGGACTTGTGTATTTTATCGTCATTCGTGGTTATCATATAGTTTATTGATTTGAAGACTACGTAAGTAATTTGAGGACTGATTAAAATTTTCTTTTTTAGCTTAGAGTCAATTAAAGAGGGCAAAATTTTCTCAAAAGACCATGGTGCATATGACGATAGCTTTAGTAGTATGGATTGGGCTCTTCTTTCATGGATGTTATTCAGAAGGAGTGATATATCGAGGTGTTTGAAACACCAGCGACACCAGAAGGCTGTGGATGTTAAATCGTAGAACCTATAGACGAGTTCTAAAATATACTTTGGGGTTTTCAGCGATGCAAAA".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); println!("{:#?}", mappings); // This should be reverse strand - let mappings = aligner.map("TTTTGCATCGCTGAAAACCCCAAAGTATATTTTAGAACTCGTCTATAGGTTCTACGATTTAACATCCACAGCCTTCTGGTGTCGCTGGTGTTTCAAACACCTCGATATATCACTCCTTCTGAATAACATCCATGAAAGAAGAGCCCAATCCATACTACTAAAGCTATCGTCATATGCACCATGGTCTTTTGAGAAAATTTTGCCCTCTTTAATTGACTCTAAGCTAAAAAAGAAAATTTTAATCAGTCCTCAAATTACTTACGTAGTCTTCAAATCAATAAACTATATGATAACCACGAATGACGATAAAATACACAAGTCCGCTATTCCTTCTTCTTCCTCTCTACCGT".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("TTTTGCATCGCTGAAAACCCCAAAGTATATTTTAGAACTCGTCTATAGGTTCTACGATTTAACATCCACAGCCTTCTGGTGTCGCTGGTGTTTCAAACACCTCGATATATCACTCCTTCTGAATAACATCCATGAAAGAAGAGCCCAATCCATACTACTAAAGCTATCGTCATATGCACCATGGTCTTTTGAGAAAATTTTGCCCTCTTTAATTGACTCTAAGCTAAAAAAGAAAATTTTAATCAGTCCTCAAATTACTTACGTAGTCTTCAAATCAATAAACTATATGATAACCACGAATGACGATAAAATACACAAGTCCGCTATTCCTTCTTCTTCCTCTCTACCGT".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); println!("Reverse Strand\n{:#?}", mappings); assert!(mappings[0].strand == Strand::Reverse); @@ -1385,12 +1468,12 @@ mod tests { false, None, None, + Some("Sample Query"), ) .unwrap(); - let mappings = aligner.map("atCCTACACTGCATAAACTATTTTGcaccataaaaaaaagttatgtgtgGGTCTAAAATAATTTGCTGAGCAATTAATGATTTCTAAATGATGCTAAAGTGAACCATTGTAatgttatatgaaaaataaatacacaattaagATCAACACAGTGAAATAACATTGATTGGGTGATTTCAAATGGGGTCTATctgaataatgttttatttaacagtaatttttatttctatcaatttttagtaatatctacaaatattttgttttaggcTGCCAGAAGATCGGCGGTGCAAGGTCAGAGGTGAGATGTTAGGTGGTTCCACCAACTGCACGGAAGAGCTGCCCTCTGTCATTCAAAATTTGACAGGTACAAACAGactatattaaataagaaaaacaaactttttaaaggCTTGACCATTAGTGAATAGGTTATATGCTTATTATTTCCATTTAGCTTTTTGAGACTAGTATGATTAGACAAATCTGCTTAGttcattttcatataatattgaGGAACAAAATTTGTGAGATTTTGCTAAAATAACTTGCTTTGCTTGTTTATAGAGGCacagtaaatcttttttattattattataattttagattttttaatttttaaat".as_bytes(), true, false, None, None).unwrap(); + let mappings = aligner.map("atCCTACACTGCATAAACTATTTTGcaccataaaaaaaagttatgtgtgGGTCTAAAATAATTTGCTGAGCAATTAATGATTTCTAAATGATGCTAAAGTGAACCATTGTAatgttatatgaaaaataaatacacaattaagATCAACACAGTGAAATAACATTGATTGGGTGATTTCAAATGGGGTCTATctgaataatgttttatttaacagtaatttttatttctatcaatttttagtaatatctacaaatattttgttttaggcTGCCAGAAGATCGGCGGTGCAAGGTCAGAGGTGAGATGTTAGGTGGTTCCACCAACTGCACGGAAGAGCTGCCCTCTGTCATTCAAAATTTGACAGGTACAAACAGactatattaaataagaaaaacaaactttttaaaggCTTGACCATTAGTGAATAGGTTATATGCTTATTATTTCCATTTAGCTTTTTGAGACTAGTATGATTAGACAAATCTGCTTAGttcattttcatataatattgaGGAACAAAATTTGTGAGATTTTGCTAAAATAACTTGCTTTGCTTGTTTATAGAGGCacagtaaatcttttttattattattataattttagattttttaatttttaaat".as_bytes(), true, false, None, None, Some("Sample Query")).unwrap(); println!("{:#?}", mappings); - panic!(); } #[test] @@ -1401,13 +1484,11 @@ mod tests { aligner.check_opts().expect("Opts are invalid"); - aligner = aligner - .with_index("test_data/genome.fa", None) - .unwrap(); + aligner = aligner.with_index("test_data/genome.fa", None).unwrap(); let output = aligner.map( b"GAAATACGGGTCTCTGGTTTGACATAAAGGTCCAACTGTAATAACTGATTTTATCTGTGGGTGATGCGTTTCTCGGACAACCACGACCGCGCCCAGACTTAAATCGCACATACTGCGTCGTGCAATGCCGGGCGCTAACGGCTCAATATCACGCTGCGTCACTATGGCTACCCCAAAGCGGGGGGGGCATCGACGGGCTGTTTGATTTGAGCTCCATTACCCTACAATTAGAACACTGGCAACATTTGGGCGTTGAGCGGTCTTCCGTGTCGCTCGATCCGCTGGAACTTGGCAACCACACTCTAAACTACATGTGGTATGGCTCATAAGATCATGCGGATCGTGGCACTGCTTTCGGCCACGTTAGAGCCGCTGTGCTCGAAGATTGGGACCTACCAAC", - false, false, None, None).unwrap(); + false, false, None, None, Some("Sample Query")).unwrap(); println!("{:#?}", aligner.mapopt); println!("{:#?}", aligner.idxopt); @@ -1431,9 +1512,10 @@ mod tests { true, None, None, + Some("Sample Query"), ) .unwrap(); - let mappings = aligner.map("atCCTACACTGCATAAACTATTTTGcaccataaaaaaaagGGACatgtgtgGGTCTAAAATAATTTGCTGAGCAATTAATGATTTCTAAATGATGCTAAAGTGAACCATTGTAatgttatatgaaaaataaatacacaattaagATCAACACAGTGAAATAACATTGATTGGGTGATTTCAAATGGGGTCTATctgaataatgttttatttaacagtaatttttatttctatcaatttttagtaatatctacaaatattttgttttaggcTGCCAGAAGATCGGCGGTGCAAGGTCAGAGGTGAGATGTTAGGTGGTTCCACCAACTGCACGGAAGAGCTGCCCTCTGTCATTCAAAATTTGACAGGTACAAACAGactatattaaataagaaaaacaaactttttaaaggCTTGACCATTAGTGAATAGGTTATATGCTTATTATTTCCATTTAGCTTTTTGAGACTAGTATGATTAGACAAATCTGCTTAGttcattttcatataatattgaGGAACAAAATTTGTGAGATTTTGCTAAAATAACTTGCTTTGCTTGTTTATAGAGGCacagtaaatcttttttattattattataattttagattttttaatttttaaat".as_bytes(), false, false, None, None).unwrap(); + let mappings = aligner.map("atCCTACACTGCATAAACTATTTTGcaccataaaaaaaagGGACatgtgtgGGTCTAAAATAATTTGCTGAGCAATTAATGATTTCTAAATGATGCTAAAGTGAACCATTGTAatgttatatgaaaaataaatacacaattaagATCAACACAGTGAAATAACATTGATTGGGTGATTTCAAATGGGGTCTATctgaataatgttttatttaacagtaatttttatttctatcaatttttagtaatatctacaaatattttgttttaggcTGCCAGAAGATCGGCGGTGCAAGGTCAGAGGTGAGATGTTAGGTGGTTCCACCAACTGCACGGAAGAGCTGCCCTCTGTCATTCAAAATTTGACAGGTACAAACAGactatattaaataagaaaaacaaactttttaaaggCTTGACCATTAGTGAATAGGTTATATGCTTATTATTTCCATTTAGCTTTTTGAGACTAGTATGATTAGACAAATCTGCTTAGttcattttcatataatattgaGGAACAAAATTTGTGAGATTTTGCTAAAATAACTTGCTTTGCTTGTTTATAGAGGCacagtaaatcttttttattattattataattttagattttttaatttttaaat".as_bytes(), false, false, None, None, Some("Sample Query")).unwrap(); println!("{:#?}", mappings); } @@ -1448,12 +1530,15 @@ mod tests { let mut mappings = aligner.map( b"GTTTATGTAGCTTATTCTATCCAAAGCAATGCACTGAAAATGTCTCGACGGGCCCACACGCCCCATAAACAAATAGGTTTGGTCCTAGCCTTTCTATTAGCTCTTAGTGAGGTTACACATGCAAGCATCCCCGCCCCAGTGAGTCGCCCTCCAAGTCACTCTGACTAAGAGGAGCAAGCATCAAGCACGCAACAGCGCAG", - true, true, None, None).unwrap(); + true, true, None, None, Some("Sample Query")).unwrap(); assert_eq!(mappings.len(), 1); let observed = mappings.pop().unwrap(); - assert_eq!(observed.target_name, Some(String::from("MT_human"))); + assert_eq!( + observed.target_name, + Some(Arc::new(String::from("MT_human"))) + ); assert_eq!(observed.target_start, 576); assert_eq!(observed.target_end, 768); assert_eq!(observed.query_start, 0); @@ -1495,12 +1580,15 @@ mod tests { aligner = aligner.with_cigar_clipping(); let mut mappings = aligner.map( b"GTTTATGTAGCTTATTCTATCCAAAGCAATGCACTGAAAATGTCTCGACGGGCCCACACGCCCCATAAACAAATAGGTTTGGTCCTAGCCTTTCTATTAGCTCTTAGTGAGGTTACACATGCAAGCATCCCCGCCCCAGTGAGTCGCCCTCCAAGTCACTCTGACTAAGAGGAGCAAGCATCAAGCACGCAACAGCGCAG", - true, true, None, None).unwrap(); + true, true, None, None, Some("Sample Query")).unwrap(); assert_eq!(mappings.len(), 1); let observed = mappings.pop().unwrap(); - assert_eq!(observed.target_name, Some(String::from("MT_human"))); + assert_eq!( + observed.target_name, + Some(Arc::new(String::from("MT_human"))) + ); assert_eq!(observed.target_start, 576); assert_eq!(observed.target_end, 768); assert_eq!(observed.query_start, 0); @@ -1535,7 +1623,7 @@ mod tests { let mut mappings = aligner.map( b"TTTGGTCCTAGCCTTTCTATTAGCTCTTAGTGAGGTTACACATGCAAGCATCCCCGCCCCAGTGAGTCGCCCTCCAAGTCACTCTGACTAAGAGGAGCAAGCATCAAGCACGCAACAGCGCAG", - true, true, None, None).unwrap(); + true, true, None, None, Some("Sample Query")).unwrap(); assert_eq!(mappings.len(), 1); let observed = mappings.pop().unwrap(); @@ -1569,7 +1657,7 @@ mod tests { for (md, cs) in vec![(true, true), (false, false), (true, false), (false, true)].iter() { let mapping = aligner - .map(query, *cs, *md, None, None) + .map(query, *cs, *md, None, None, Some("Sample Query")) .unwrap() .pop() .unwrap(); @@ -1603,7 +1691,14 @@ mod tests { let aligner = aligner.with_seq(seq.as_bytes()).unwrap(); let alignments = aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .unwrap(); assert_eq!(alignments.len(), 2); @@ -1613,7 +1708,14 @@ mod tests { let aligner = Aligner::builder().short(); let aligner = aligner.with_seqs(&vec![seq.as_bytes().to_vec()]).unwrap(); let alignments = aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .unwrap(); assert_eq!(alignments.len(), 2); @@ -1628,7 +1730,14 @@ mod tests { ) .unwrap(); let alignments = aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .unwrap(); assert_eq!(alignments.len(), 2); @@ -1640,7 +1749,14 @@ mod tests { .with_seq_and_id(seq.as_bytes(), &id.as_bytes().to_vec()) .unwrap(); let alignments = aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .unwrap(); assert_eq!(alignments.len(), 2); @@ -1659,7 +1775,14 @@ mod tests { .unwrap(); println!("mapping..."); let alignments = aligner - .map(query.as_bytes(), true, true, None, None) + .map( + query.as_bytes(), + true, + true, + None, + None, + Some("Sample Query"), + ) .unwrap(); println!("Mapped"); assert_eq!(alignments.len(), 1); @@ -1729,7 +1852,8 @@ mod tests { Err("File does not exist") ); - if let Err("File is empty") = Aligner::builder().with_index("test_data/empty.fa", None) { + if let Err("File is empty") = Aligner::builder().with_index("test_data/empty.fa", None) + { println!("File is empty - Success"); } else { panic!("File is empty error not thrown"); @@ -1758,7 +1882,14 @@ mod tests { let aligner = Aligner::builder().short(); let aligner = std::sync::Arc::new(aligner.with_seq(seq.as_bytes()).unwrap()); let alignments = aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .unwrap(); assert_eq!(alignments.len(), 2); @@ -1776,7 +1907,14 @@ mod tests { new_send .send( new_aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .expect("Failed to map"), ) .expect("Failed to send") @@ -1784,7 +1922,14 @@ mod tests { let new_sender = std::thread::spawn(move || { send.send( aligner - .map(query.as_bytes(), false, false, None, None) + .map( + query.as_bytes(), + false, + false, + None, + None, + Some("Sample Query"), + ) .expect("Failed to map"), ) .expect("Failed to send")