diff --git a/souporcell/Cargo.lock b/souporcell/Cargo.lock index 01b5476..6fb413d 100644 --- a/souporcell/Cargo.lock +++ b/souporcell/Cargo.lock @@ -1,684 +1,730 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adler32" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" [[package]] name = "ansi_term" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" [[package]] name = "arrayvec" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop", ] [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "winapi", ] [[package]] name = "autocfg" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" [[package]] name = "autocfg" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" dependencies = [ - "backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", ] [[package]] name = "backtrace-sys" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" dependencies = [ - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "bitflags" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" [[package]] name = "bitflags" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" [[package]] name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" [[package]] name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "ppv-lite86", ] [[package]] name = "cc" version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" version = "2.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags 0.9.1", + "strsim", + "textwrap", + "unicode-width", + "vec_map", + "yaml-rust", ] [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0", ] [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "crossbeam-deque" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard 1.0.0", ] [[package]] name = "crossbeam-queue" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", ] [[package]] name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "failure" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" dependencies = [ - "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "flate2" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", ] [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "getrandom" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] name = "hashbrown" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "scopeguard 0.3.3", ] [[package]] name = "indexmap" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", ] [[package]] name = "itertools" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" dependencies = [ - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "miniz_oxide" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" dependencies = [ - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", ] [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "ppv-lite86" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" [[package]] name = "proc-macro2" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "quote" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] [[package]] name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi", ] [[package]] name = "rand" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "rand_chacha 0.2.1", + "rand_core 0.5.1", + "rand_hc 0.2.0", ] [[package]] name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6", + "rand_core 0.3.1", ] [[package]] name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha", + "rand_core 0.5.1", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1", ] [[package]] name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_core 0.4.2", + "winapi", ] [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi", ] [[package]] name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6", + "rand_core 0.4.2", ] [[package]] name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rayon" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "either", + "rayon-core", ] [[package]] name = "rayon-core" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] +[[package]] +name = "ryu" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" + [[package]] name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" [[package]] name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" [[package]] name = "souporcell" version = "2.4.0" dependencies = [ - "clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "statrs 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "vcf 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "csv", + "flate2", + "hashbrown", + "itertools", + "rand 0.7.2", + "rayon", + "statrs", + "vcf", ] [[package]] name = "statrs" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a1669368b3524d9214cfcb274a1f5e3b0820b5f275c1509bfb0cc67664636" dependencies = [ - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5", ] [[package]] name = "strsim" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" [[package]] name = "syn" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] name = "synstructure" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] name = "textwrap" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "vcf" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5518338782b66cdc48148ab3cf8b31157e65aeb22200ec387946cf846219659" dependencies = [ - "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure", + "indexmap", ] [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" [[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "yaml-rust" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -"checksum backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" -"checksum backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clap 2.27.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b8c532887f1a292d17de05ae858a8fe50a301e196f9ef0ddb7ccd0d1d00f180" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" -"checksum failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" -"checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" -"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" -"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum statrs 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "835a1669368b3524d9214cfcb274a1f5e3b0820b5f275c1509bfb0cc67664636" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum vcf 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5518338782b66cdc48148ab3cf8b31157e65aeb22200ec387946cf846219659" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" +checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/souporcell/Cargo.toml b/souporcell/Cargo.toml index 3d9b3ef..ae9557a 100644 --- a/souporcell/Cargo.toml +++ b/souporcell/Cargo.toml @@ -13,3 +13,4 @@ statrs = "*" rayon = "*" vcf = "*" flate2 = "*" +csv = "1.1" diff --git a/souporcell/src/main.rs b/souporcell/src/main.rs index 5e40529..5f6b662 100644 --- a/souporcell/src/main.rs +++ b/souporcell/src/main.rs @@ -8,6 +8,19 @@ extern crate rayon; extern crate vcf; extern crate flate2; + + +//Reza +extern crate csv; +use csv::Writer; +use std::error::Error; + + + +use std::fs::OpenOptions; +use std::io::prelude::*; + + use flate2::read::GzDecoder; use flate2::read::MultiGzDecoder; use vcf::*; @@ -31,12 +44,33 @@ use std::path::Path; use hashbrown::{HashMap,HashSet}; use itertools::izip; + + + fn main() { let params = load_params(); - let cell_barcodes = load_barcodes(¶ms); - let (loci_used, total_cells, cell_data, index_to_locus, locus_to_index) = load_cell_data(¶ms); - souporcell_main(loci_used, cell_data, ¶ms, cell_barcodes, locus_to_index); + let mut cell_barcodes = load_barcodes(¶ms); + io::stdout().flush().unwrap(); + let (loci_used, total_cells, cell_data, index_to_locus, locus_to_index, list_of_loci_used, locus_cell_counts, ref_alt_counts_per_locus) = load_cell_data(¶ms); + + let (mut cell_hashing_cluster_centers,mut cell_id_to_label_map, + barcode_to_cell_id_and_hash, cell_id_to_barcode_and_hash) = initialize_cluster_centers_cell_hashing( + &list_of_loci_used, + &cell_data, + cell_barcodes.clone(), + ¶ms + ); + + cellector(ref_alt_counts_per_locus,index_to_locus, &list_of_loci_used, locus_cell_counts, loci_used, cell_data, ¶ms, cell_barcodes, locus_to_index,cell_id_to_barcode_and_hash); + + // souporcell_main(&list_of_loci_used,locus_cell_counts,cell_hashing_cluster_centers,loci_used, cell_data, ¶ms, cell_barcodes, locus_to_index, cell_id_to_barcode_and_hash); } + + + + + + struct ThreadData { best_log_probabilities: Vec>, @@ -58,7 +92,85 @@ impl ThreadData { } } -fn souporcell_main(loci_used: usize, cell_data: Vec, params: &Params, barcodes: Vec, locus_to_index: HashMap) { + + + +fn cellector( ref_alt_counts_per_locus:HashMap,index_to_locus: Vec ,list_of_loci_used: &HashSet ,loci_cell_count :HashMap , loci: usize, cell_data: Vec, params: &Params, barcodes: Vec, locus_to_index: HashMap, cell_id_to_barcode_and_hash: Vec<(String, String)>) { + + let seed = [params.seed; 32]; + let mut rng: StdRng = SeedableRng::from_seed(seed); + + let (mut beta_cluster_centers, mut locus_to_index_for_beta_centers) = init_beta_binomial_cluster_centers(ref_alt_counts_per_locus,loci, &cell_data, params,&list_of_loci_used, &mut rng, index_to_locus.clone()); + + let (log_loss, log_probabilities) = beta_EM(index_to_locus, locus_to_index_for_beta_centers,&mut beta_cluster_centers.clone() , &cell_data, params, loci); + // println!("log_loss = {}", log_loss); + // println!("log_probabilities = {:?}", log_probabilities); + + let mut Soup_Assignments = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open("assignments.tsv") + .unwrap(); + + // write header to cells_file + writeln!(Soup_Assignments, "Barcode\tCell\tSoup").unwrap(); + + let mut cell_id = 0; + + let threshold = 0.55; + + for (bc, log_probs) in barcodes.iter().zip(log_probabilities.iter()) { + + let mut best = 0; + let mut best_lp = f64::NEG_INFINITY; + for index in 0..log_probs.len() { + if log_probs[index] > best_lp { + best = index; + best_lp = log_probs[index]; + } + } + // let posterior = (best_lp - log_sum_exp(log_probs)).exp(); + let posterior = (best_lp - log_sum_exp_64(log_probs.clone())).exp(); + + writeln!(Soup_Assignments, "{}\t{}\t{}", bc, cell_id_to_barcode_and_hash[cell_id].1, best).unwrap(); + + // if posterior > threshold { + // print!("{}\t{}\t{}",bc, best, cell_id_to_barcode_and_hash[cell_id].1); + // writeln!(Soup_Assignments, "{}\t{}\t{}", bc, cell_id_to_barcode_and_hash[cell_id].1, best).unwrap(); + // } + // else { + // print!("{}\t{}\tU",bc,cell_id_to_barcode_and_hash[cell_id].1); + // writeln!(Soup_Assignments, "{}\t{}\tU", bc, cell_id_to_barcode_and_hash[cell_id].1).unwrap(); + // } + + + // print!("\n"); + + cell_id += 1; + + + } + + + + + + + // if posterior > threshold { + + // print!("{}\t{}\t{}",bc, best, cell_id_to_barcode_and_hash[cell_id].1); + // writeln!(Soup_Assignments, "{}\t{}\t{}", bc, cell_id_to_barcode_and_hash[cell_id].1, best).unwrap(); + + // } else { + + // print!("{}\tU\t{}",bc, cell_id_to_barcode_and_hash[cell_id].1); + // writeln!(Soup_Assignments, "{}\t{}\tU", bc, cell_id_to_barcode_and_hash[cell_id].1 ).unwrap(); + // } + +} + +fn souporcell_main(list_of_loci_used: &HashSet ,loci_cell_count :HashMap ,cell_hashing_assignments: Vec>, loci_used: usize, cell_data: Vec, params: &Params, barcodes: Vec, locus_to_index: HashMap, cell_id_to_barcode_and_hash: Vec<(String, String)>) { let seed = [params.seed; 32]; let mut rng: StdRng = SeedableRng::from_seed(seed); let mut threads: Vec = Vec::new(); @@ -66,16 +178,23 @@ fn souporcell_main(loci_used: usize, cell_data: Vec, params: &Params, for i in 0..params.threads { threads.push(ThreadData::from_seed(new_seed(&mut rng), solves_per_thread, i)); } + threads.par_iter_mut().for_each(|thread_data| { for iteration in 0..thread_data.solves_per_thread { + let cluster_centers: Vec> = init_cluster_centers(loci_used, &cell_data, params, &mut thread_data.rng, &locus_to_index); - let (log_loss, log_probabilities) = EM(loci_used, cluster_centers, &cell_data ,params, iteration, thread_data.thread_num); + // let cluster_centers = cell_hashing_assignments.clone(); + + let (log_loss, log_probabilities) = EM(locus_to_index.clone() ,list_of_loci_used ,loci_cell_count.clone() ,loci_used, cluster_centers, &cell_data ,params, iteration, thread_data.thread_num, cell_id_to_barcode_and_hash.clone()); + + + if log_loss > thread_data.best_total_log_probability { thread_data.best_total_log_probability = log_loss; thread_data.best_log_probabilities = log_probabilities; } - eprintln!("thread {} iteration {} done with {}, best so far {}", - thread_data.thread_num, iteration, log_loss, thread_data.best_total_log_probability); + + } }); let mut best_log_probability = f32::NEG_INFINITY; @@ -87,7 +206,26 @@ fn souporcell_main(loci_used: usize, cell_data: Vec, params: &Params, } } eprintln!("best total log probability = {}", best_log_probability); - //println!("finished with {}",best_log_probability); + + + + let mut cell_id = 0; + let mut num_unassigned = 0; + let threshold = 0.99; + + + let mut Soup_Assignments = OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open("assignments.tsv") + .unwrap(); + + // write header to cells_file + writeln!(Soup_Assignments, "Barcode\tCell\tSoup").unwrap(); + + + for (bc, log_probs) in barcodes.iter().zip(best_log_probabilities.iter()) { let mut best = 0; let mut best_lp = f32::NEG_INFINITY; @@ -95,123 +233,409 @@ fn souporcell_main(loci_used: usize, cell_data: Vec, params: &Params, if log_probs[index] > best_lp { best = index; best_lp = log_probs[index]; + } } - print!("{}\t{}\t",bc, best); + let posterior = (best_lp - log_sum_exp(log_probs)).exp(); + + + + + if posterior > threshold { + + print!("{}\t{}\t{}",bc, best, cell_id_to_barcode_and_hash[cell_id].1); + writeln!(Soup_Assignments, "{}\t{}\t{}", bc, cell_id_to_barcode_and_hash[cell_id].1, best).unwrap(); + + } else { + + print!("{}\tU\t{}",bc, cell_id_to_barcode_and_hash[cell_id].1); + writeln!(Soup_Assignments, "{}\t{}\tU", bc, cell_id_to_barcode_and_hash[cell_id].1 ).unwrap(); + } for index in 0..log_probs.len() { print!("{}",log_probs[index]); if index < log_probs.len() - 1 { print!("\t"); } + } print!("\n"); + + + cell_id += 1; + + } + +} + + + +// REZA EM function for beta binomial +fn beta_EM(index_to_locus: Vec, locus_to_index_for_beta_centers: HashMap, beta_cluster_centers: &mut Vec>, cell_data: &Vec,params: &Params, loci: usize) -> (f64, Vec>) { + + + let mut total_log_loss = f32::NEG_INFINITY; + let mut beta_loss_values: Vec = Vec::new(); + let mut iterations = 0; + let mut last_log_loss = f64::NEG_INFINITY; + let mut log_loss_change = 10000.0; + let log_loss_change_limit = 0.0001*(cell_data.len() as f64); + let mut log_beta_loss_total = 0.0; + let mut cell_cluster_probabilities: Vec> = vec![vec![0.0; 2]; cell_data.len()]; + + let mut final_log_probabilities: Vec> = Vec::new(); + for _cell in 0..cell_data.len() { + final_log_probabilities.push(Vec::new()); + } + + + + while iterations < 3 { + + log_beta_loss_total = 0.0; + for (celldex, cell) in cell_data.iter().enumerate() { + + beta_loss_values = log_beta_loss_PMF(cell, &beta_cluster_centers, celldex, params,locus_to_index_for_beta_centers.clone(),index_to_locus.clone()); + println!("beta_loss_values = {:?}", beta_loss_values); + + log_beta_loss_total += log_sum_exp_64(beta_loss_values.clone()); + + let normalize_in_log = normalize_log_probabilities2(beta_loss_values); + // println!("normalize_in_log = {:?}", normalize_in_log); + final_log_probabilities[celldex] = normalize_in_log.clone(); + // println!("final logs= {:?}", final_log_probabilities[celldex]); + } + + + update_alpha_and_beta(index_to_locus.clone(), beta_cluster_centers, cell_data, &mut cell_cluster_probabilities, loci, &final_log_probabilities, params); + println!("loss = {}", log_beta_loss_total); + log_loss_change = log_beta_loss_total - last_log_loss; + last_log_loss = log_beta_loss_total; + + + + + iterations += 1; } + + + + + + (log_beta_loss_total, final_log_probabilities) + +} + +//REZA normalization for beta +fn normalize_log_probabilities(log_probs: Vec) -> Vec { + let max_log_prob = log_probs.iter().cloned().fold(f64::NEG_INFINITY, f64::max); + let sum_exp_adjusted: f64 = log_probs + .iter() + .map(|&log_prob| (log_prob - max_log_prob).exp()) + .sum(); + let log_sum_exp_adjusted = sum_exp_adjusted.ln(); + + log_probs + .iter() + .map(|&log_prob| log_prob - (log_sum_exp_adjusted + max_log_prob)) + .collect() +} + +fn normalize_log_probabilities2(log_probs: Vec) -> Vec { + let mut normalized_probabilities: Vec = Vec::new(); + let sum = log_sum_exp_64(log_probs.clone()); + for i in 0..log_probs.len() { + normalized_probabilities.push((log_probs[i]-sum).exp()); + } + normalized_probabilities +} + + +//REZA beta update +fn update_alpha_and_beta( + index_to_locus: Vec, + cluster_centers: &mut Vec>, + cell_data: &Vec, + log_probabilities: &mut Vec>, + loci: usize, + cell_cluster_probabilities: &Vec>, + params: &Params +) { + + for cluster in 0..params.num_clusters { + + for locus_index in 0..loci { + + let locus = index_to_locus[locus_index as usize]; + let mut updated_alpha = 1.0 as f32; + let mut updated_beta = 1.0 as f32; + + // println!("locus index = {}", locus_index); + for (celldex, cell) in cell_data.iter().enumerate(){ + + if cell.loci.contains(&locus) { + let mut alt_counts = 0; + let mut ref_counts = 0; + alt_counts = cell.alt_counts[cell.loci.iter().position(|&r| r == locus).unwrap()] as usize; + ref_counts = cell.ref_counts[cell.loci.iter().position(|&r| r == locus).unwrap()] as usize; + updated_alpha += cell_cluster_probabilities[celldex][cluster] as f32 * alt_counts as f32; + updated_beta += cell_cluster_probabilities[celldex][cluster] as f32 * ref_counts as f32; + } + + } + cluster_centers[cluster][locus_index] = (updated_alpha, updated_beta); + + } + } } -fn EM(loci: usize, mut cluster_centers: Vec>, cell_data: &Vec, params: &Params, epoch: usize, thread_num: usize) -> (f32, Vec>) { + + + +fn EM(locus_to_index: HashMap ,list_of_loci_used: &HashSet ,loci_cell_count :HashMap, loci: usize, mut cluster_centers: Vec>, cell_data: &Vec, params: &Params, epoch: usize, thread_num: usize, cell_id_to_barcode_and_hash: Vec<(String, String)>) -> (f32, Vec>) { let mut sums: Vec> = Vec::new(); let mut denoms: Vec> = Vec::new(); + + for cluster in 0..params.num_clusters { sums.push(Vec::new()); denoms.push(Vec::new()); for index in 0..loci { sums[cluster].push(1.0); - denoms[cluster].push(2.0); // psuedocounts + denoms[cluster].push(2.0); // HAYNES debug, no psuedocounts } } + + + let mut file = OpenOptions::new() + .write(true) + .append(true) + .create(true) + .open("log_loss_change_with_last.txt") + .unwrap(); + + + + let mut log_binoms: Vec = Vec::new(); + let mut beta_loss_values: Vec = Vec::new(); + + + // let mut cells_file = OpenOptions::new() + // .write(true) + // .append(true) + // .create(true) + // .open("cells_contribution.tsv") + // .unwrap(); + + // // write header to cells_file + // writeln!(cells_file, "cell_id\tlocus_index\tref_counts\talt_counts\tlog_loss\tcluster").unwrap(); + + + + + let mut log_priors: Vec = Vec::new(); + for i in 0..params.num_clusters { log_priors.push((1.0/(params.num_clusters as f32)).ln()); } - let log_prior: f32 = (1.0/(params.num_clusters as f32)).ln(); - let mut change = 1000.0; let mut iterations = 0; - //let mut cell_probabilities: Vec> = Vec::new(); - //for _cell in cell_data { - // cell_probabilities.push(Vec::new()); - //} + let mut total_log_loss = f32::NEG_INFINITY; - let mut total_log_loss_binom = f32::NEG_INFINITY; + let mut final_log_probabilities = Vec::new(); for _cell in 0..cell_data.len() { final_log_probabilities.push(Vec::new()); } - let log_loss_change_limit = 0.01*(cell_data.len() as f32); - let temp_steps = 9; + let log_loss_change_limit = 0.0001*(cell_data.len() as f32); + let temp_steps = 1; // debug no deterministic annealing let mut last_log_loss = f32::NEG_INFINITY; + + + let mut last_log_loss_binom = f32::NEG_INFINITY; + let mut count_wrong_directions = 0; + + + + for temp_step in 0..temp_steps { - //eprintln!("temp step {}",temp_step); + // println!("temp_step={}", temp_step); + let mut log_loss_change = 10000.0; - //let mut cluster_cells_weighted: Vec = Vec::new(); - //for cluster in 0..params.num_clusters { cluster_cells_weighted.push(0.0); } - while (log_loss_change > log_loss_change_limit && iterations < 1000) { - //for cluster in 0..params.num_clusters { cluster_cells_weighted[cluster] = 0.0; } - //let mut log_loss = 0.0; + + let mut temp = 1.0; + + + while log_loss_change > log_loss_change_limit && iterations < 10000 { + + + + let mut log_binom_loss = 0.0; + let mut log_beta_loss_total = 0.0; + + let mut total_posteriors: Vec = Vec::new(); + for i in 0..params.num_clusters { total_posteriors.push(0.0); } + + + // let mut cells_file = OpenOptions::new() + // .write(true) + // .append(true) + // .create(true) + // .open("cells_contribution_".to_owned() + &iterations.to_string() + ".tsv") + // .unwrap(); + // writeln!(cells_file, "cell_id\tlocus_index\tref_counts\talt_counts\tlog_loss\tcluster").unwrap(); reset_sums_denoms(loci, &mut sums, &mut denoms, &cluster_centers, params.num_clusters); + + + for (celldex, cell) in cell_data.iter().enumerate() { - //let log_probabilities = sum_of_squares_loss(cell, &cluster_centers, log_prior, celldex); - let log_binoms = binomial_loss(cell, &cluster_centers, log_prior, celldex); + + + // let log_binoms = binomial_loss(&mut cells_file, cell, &cluster_centers, &log_priors, celldex); + // let log_binoms = binomial_loss(cell, &cluster_centers, &log_priors, celldex); + log_binoms = binomial_loss(cell, &cluster_centers, &log_priors, celldex); + // let log_binoms = sum_of_squares_loss(cell, &cluster_centers, log_priors[0], celldex); + + + + log_binom_loss += log_sum_exp(&log_binoms); - //eprintln!("cell {} loci {} total_alleles {}", celldex, cell.loci.len(), cell.total_alleles); - //log_loss += log_sum_exp(&log_binoms); - let mut temp = (cell.total_alleles/(20.0 * 2.0f32.powf((temp_step as f32)))).max(1.0); + temp = (cell.total_alleles/(20.0 * 2.0f32.powf(temp_step as f32))).max(1.0); if temp_step == temp_steps - 1 { temp = 1.0; } + //if temp_step > 0 { temp = 1.0; } - let probabilities = normalize_in_log_with_temp(&log_binoms, temp); - //for cluster in 0..params.num_clusters { cluster_cells_weighted[cluster] += probabilities[cluster]; } + + let mut probabilities = normalize_in_log_with_temp(&log_binoms, temp); + + for (i, prob) in probabilities.iter().enumerate() { + total_posteriors[i] += prob; // this is for later updating priors + } + update_centers_average(&mut sums, &mut denoms, cell, &probabilities); - - //println!("normalized probabilities {:?}", probabilities); - //cell_probabilities[celldex] = probabilities; - final_log_probabilities[celldex] = log_binoms;//log_probabilities; + final_log_probabilities[celldex] = log_binoms.clone();//log_probabilities; + + } + total_log_loss = log_binom_loss; log_loss_change = log_binom_loss - last_log_loss;//log_loss - last_log_loss; last_log_loss = log_binom_loss;//log_loss; + update_final(loci, &sums, &denoms, &mut cluster_centers); + let mut sum_posteriors: f32 = 0.0; + for postsum in &total_posteriors { sum_posteriors += postsum; } + for i in 0..params.num_clusters { + log_priors[i] = (total_posteriors[i]/sum_posteriors).ln(); + } + + // wtr.flush(); iterations += 1; - eprintln!("binomial\t{}\t{}\t{}\t{}\t{}\t{}", thread_num, epoch, iterations, temp_step, log_binom_loss, log_loss_change);//, cluster_cells_weighted); + + } + println!(" log_loss = {}", total_log_loss); + + + + } - //for (celldex, probabilities) in cell_probabilities.iter().enumerate() { - // println!("cell {} with {} loci, cluster probabilities {:?}", celldex, cell_data[celldex].loci.len(), probabilities); - //} - //for center in 0..cluster_centers.len() { - // for locus in 0..cluster_centers[0].len() { - // println!("cluster {} locus {} {}", center, locus, cluster_centers[center][locus]); - // } - //} - //println!("total log probability = {}",total_log_loss); (total_log_loss, final_log_probabilities) } -fn sum_of_squares_loss(cell_data: &CellData, cluster_centers: &Vec>, log_prior: f32, cellnum: usize) -> Vec { + + + +//REZA beta_loss function +fn log_beta_loss_PMF(cell_data: &CellData, cluster_centers: &Vec>, _cellnum: usize, params: &Params, locus_to_index_for_beta_centers: HashMap, index_to_locus: Vec, +) -> Vec { + + let mut probabilities: Vec = Vec::new(); + for (cluster, centers) in cluster_centers.iter().enumerate() { + + let mut log_prior: f64 = (1.0/params.num_clusters as f64).ln(); + probabilities.push(log_prior); + for (index, locus_index) in cell_data.loci.iter().enumerate() { + + let locus = index_to_locus[*locus_index]; + let mut center_index = 0; + center_index = *locus_to_index_for_beta_centers.get(&locus).unwrap(); + let center = centers[center_index]; + + let alpha = center.0; + let beta = center.1; + let coefficient = cell_data.log_binomial_coefficient[index] as f64; + let log_prob_num = log_beta_calc(cell_data.alt_counts[index] as f32 + alpha, cell_data.ref_counts[index] as f32 + beta); + let log_prob_denom = log_beta_calc(alpha, beta); + let log_prob = ( (coefficient + log_prob_num) - log_prob_denom ); + probabilities[cluster] += log_prob; + + } + } + + probabilities +} + +//REZA beta binomial calculation +fn log_beta_calc(alpha: f32, beta: f32) -> f64 { + + let log_gamma_alpha = statrs::function::gamma::ln_gamma(alpha as f64); + let log_gamma_beta = statrs::function::gamma::ln_gamma(beta as f64); + let log_gamma_alpha_beta = statrs::function::gamma::ln_gamma((alpha + beta) as f64); + + log_gamma_alpha + log_gamma_beta - log_gamma_alpha_beta +} + + + +// fn binomial_loss(cells_file: &mut File, cell_data: &CellData, cluster_centers: &Vec>, log_priors: &Vec, cellnum: usize) -> Vec { + +fn binomial_loss(cell_data: &CellData, cluster_centers: &Vec>, log_priors: &Vec, cellnum: usize) -> Vec { + let mut log_probabilities: Vec = Vec::new(); + let mut sum = 0.0; + for (cluster, center) in cluster_centers.iter().enumerate() { - log_probabilities.push(log_prior); + log_probabilities.push(log_priors[cluster]); for (locus_index, locus) in cell_data.loci.iter().enumerate() { - log_probabilities[cluster] -= (cell_data.allele_fractions[locus_index] - center[*locus]).powf(2.0); + let mut prob = cell_data.log_binomial_coefficient[locus_index] + + (cell_data.alt_counts[locus_index] as f32) * center[*locus].ln() + + (cell_data.ref_counts[locus_index] as f32) * (1.0 - center[*locus]).ln(); + log_probabilities[cluster] += prob; + // writeln!(cells_file, "{}\t{}\t{}\t{}\t{}\t{}",cellnum, cell_data.loci[locus_index], cell_data.ref_counts[locus_index], cell_data.alt_counts[locus_index], prob, cluster).unwrap(); + } + + sum += log_probabilities[cluster]; } - log_probabilities + + log_probabilities } -fn binomial_loss(cell_data: &CellData, cluster_centers: &Vec>, log_prior: f32, cellnum: usize) -> Vec { + + + + + +fn sum_of_squares_loss(cell_data: &CellData, cluster_centers: &Vec>, log_prior: f32, cellnum: usize) -> Vec { let mut log_probabilities: Vec = Vec::new(); - let mut sum = 0.0; for (cluster, center) in cluster_centers.iter().enumerate() { log_probabilities.push(log_prior); for (locus_index, locus) in cell_data.loci.iter().enumerate() { - log_probabilities[cluster] += cell_data.log_binomial_coefficient[locus_index] + - (cell_data.alt_counts[locus_index] as f32) * center[*locus].ln() + - (cell_data.ref_counts[locus_index] as f32) * (1.0 - center[*locus]).ln(); + log_probabilities[cluster] -= (cell_data.allele_fractions[locus_index] - center[*locus]).powf(2.0); } - sum += log_probabilities[cluster]; } - - log_probabilities + log_probabilities } + + +//REZA +fn log_sum_exp_64(p: Vec) -> f64{ + let max_p: f64 = p.iter().cloned().fold(f64::NEG_INFINITY, f64::max); + let sum_rst: f64 = p.iter().map(|x| (x - max_p).exp()).sum(); + max_p + sum_rst.ln() +} + + fn log_sum_exp(p: &Vec) -> f32{ let max_p: f32 = p.iter().cloned().fold(f32::NEG_INFINITY, f32::max); let sum_rst: f32 = p.iter().map(|x| (x - max_p).exp()).sum(); @@ -227,6 +651,7 @@ fn normalize_in_log(log_probs: &Vec) -> Vec { // takes in a log_probab normalized_probabilities } + fn normalize_in_log_with_temp(log_probs: &Vec, temp: f32) -> Vec { let mut normalized_probabilities: Vec = Vec::new(); let mut new_log_probs: Vec = Vec::new(); @@ -244,7 +669,7 @@ fn update_final(loci: usize, sums: &Vec>, denoms: &Vec>, clust for locus in 0..loci { for cluster in 0..sums.len() { let update = sums[cluster][locus]/denoms[cluster][locus]; - cluster_centers[cluster][locus] = update.min(0.99).max(0.01);//max(0.0001, min(0.9999, update)); + cluster_centers[cluster][locus] = update;//.min(0.99).max(0.01);//max(0.0001, min(0.9999, update)); } } } @@ -278,6 +703,122 @@ fn update_centers_average(sums: &mut Vec>, denoms: &mut Vec>, } } + + + +//REZA beta binomial cluster centers initialization +fn init_beta_binomial_cluster_centers(ref_alt_counts_per_locus:HashMap, + loci: usize, cell_data: &Vec, params: &Params, + list_of_loci_used: &HashSet, + rng: &mut StdRng, index_to_locus: Vec) -> +(Vec>, HashMap) { + + + let mut centers: Vec> = Vec::with_capacity(params.num_clusters as usize); + + // Initialize each cluster with empty vectors + for _ in 0..params.num_clusters { + centers.push(vec![(0.0, 0.0); loci]); + } + + let mut locus_to_index_for_beta_centers: HashMap = HashMap::new(); + + println!("loci = {}", loci); + for (locus_index, locus) in list_of_loci_used.iter().enumerate(){ + let mut alt_counts = 0.0 as f32; + let mut ref_counts = 0.0 as f32; + + let counts = ref_alt_counts_per_locus.get(&locus).unwrap(); // REZA -> May need to change this + // println!("counts = {:?}\t locus {}", counts, locus); + let ref_count = counts[0] as f32; + let alt_count = counts[1] as f32; + + ref_counts = ref_count; + alt_counts = alt_count; + + let x = rng.gen_range(0.0, alt_counts); + let y = rng.gen_range(0.0, ref_counts); + + let alpha_1 = 1.0 + x; + let beta_1 = 1.0 + y; + + let alpha_2 = 1.0 + (alt_counts - x); + let beta_2 = 1.0 + (ref_counts - y); + + centers[0][locus_index] = (alpha_1, beta_1); + centers[1][locus_index] = (alpha_2, beta_2); + // println!("alpha_1 = {}\t beta_1 = {}\t\t alpha_2 = {}\t beta_2 = {}", alpha_1, beta_1, alpha_2, beta_2); + locus_to_index_for_beta_centers.insert(*locus, locus_index); + } + + + + // for locus_index in 0..loci { + + + + + // let mut alt_counts = 0.0 as f32; + // let mut ref_counts = 0.0 as f32; + + // let locus = index_to_locus[locus_index as usize]; + + // locus_to_index_for_beta_centers.insert(locus_index, locus as usize); + + // let counts = ref_alt_counts_per_locus.get(&locus).unwrap(); + // // println!("counts = {:?}\t locus {}", counts, locus); + // let ref_count = counts[0] as f32; + // let alt_count = counts[1] as f32; + + // ref_counts = ref_count; + // alt_counts = alt_count; + + + // let x = rng.gen_range(0.0, alt_counts); + // let y = rng.gen_range(0.0, ref_counts); + + // let alpha_1 = 1.0 + x; + // let beta_1 = 1.0 + y; + + // let alpha_2 = 1.0 + (alt_counts - x); + // let beta_2 = 1.0 + (ref_counts - y); + + + // // let alpha_1 = rng.gen_range(1.0, 25.0); + // // let beta_1 = rng.gen_range(1.0, 25.0); + // // let alpha_2 = rng.gen_range(25.0, 56.0); + // // let beta_2 = rng.gen_range(25.0, 56.0); + + // centers[0][locus_index] = (alpha_1, beta_1); + // centers[1][locus_index] = (alpha_2, beta_2); + // // println!("alpha_1 = {}\t beta_1 = {}\t\t alpha_2 = {}\t beta_2 = {}", alpha_1, beta_1, alpha_2, beta_2); + + + + // } + + + // for loci in 0..loci { + // println!("loci = {}\t{:?}", loci, centers[0][loci]); + // println!("loci = {}\t{:?}", loci, centers[1][loci]); + // println!("\n"); + // // } + // for loci in 0..loci { + // let locus = index_to_locus[loci]; + + // let index = locus_to_index_for_beta_centers.get(&locus).unwrap(); + + // println!("locus = {}\tloci = {}\tindex = {}",locus , loci, index); + // } + + + (centers, locus_to_index_for_beta_centers) + +} + + + + fn init_cluster_centers(loci_used: usize, cell_data: &Vec, params: &Params, rng: &mut StdRng, locus_to_index: &HashMap) -> Vec> { if let Some(known_genotypes) = ¶ms.known_genotypes { return init_cluster_centers_known_genotypes(loci_used, params, rng, locus_to_index); @@ -317,6 +858,7 @@ fn init_cluster_centers_known_genotypes(loci: usize, params: &Params, rng: &mut } let mut vcf_reader = VCFReader::new(reader(params.known_genotypes.as_ref().unwrap())).unwrap(); let mut locus_id: usize = 0; + for record in vcf_reader { let record = record.unwrap(); if let Some(loci_index) = locus_to_index.get(&locus_id) { @@ -347,6 +889,11 @@ fn init_cluster_centers_kmeans_pp(loci: usize, cell_data: &Vec, params Vec::new() } + + + + + fn init_cluster_centers_uniform(loci: usize, params: &Params, rng: &mut StdRng) -> Vec> { let mut centers: Vec> = Vec::new(); for cluster in 0..params.num_clusters { @@ -386,6 +933,7 @@ fn init_cluster_centers_random_assignment(loci: usize, cell_data: &Vec } } let centers = sums; + centers } @@ -394,7 +942,7 @@ fn init_cluster_centers_middle_variance(loci: usize, cell_data: &Vec, Vec::new() } -fn load_cell_data(params: &Params) -> (usize, usize, Vec, Vec, HashMap) { +fn load_cell_data(params: &Params) -> (usize, usize, Vec, Vec, HashMap, HashSet, HashMap, HashMap) { let alt_reader = File::open(params.alt_mtx.to_string()).expect("cannot open alt mtx file"); let alt_reader = BufReader::new(alt_reader); @@ -409,6 +957,7 @@ fn load_cell_data(params: &Params) -> (usize, usize, Vec, Vec, let mut locus_cell_counts: HashMap = HashMap::new(); let mut locus_umi_counts: HashMap = HashMap::new(); let mut locus_counts: HashMap> = HashMap::new(); + let mut cell_count_per_locus: HashMap = HashMap::new(); // New hashmap Reza for (alt_line, ref_line) in izip!(alt_reader.lines(), ref_reader.lines()) { let alt_line = alt_line.expect("cannot read alt mtx"); let ref_line = ref_line.expect("cannot read ref mtx"); @@ -428,13 +977,29 @@ fn load_cell_data(params: &Params) -> (usize, usize, Vec, Vec, if alt_count > 0 { cell_counts[1] += 1; umi_counts[1] += alt_count; } let cell_counts = locus_counts.entry(locus).or_insert(HashMap::new()); cell_counts.insert(cell, [ref_count, alt_count]); + *cell_count_per_locus.entry(locus).or_insert(0) += 1; // New hashmap Reza } else if line_number == 2 { let tokens: Vec<&str> = alt_line.split_whitespace().collect(); total_loci = tokens[0].to_string().parse::().unwrap(); total_cells = tokens[1].to_string().parse::().unwrap(); } line_number += 1; + + } + + //REZA #ref & #alt per loci + let mut ref_alt_counts_per_locus: HashMap = HashMap::new(); + for (&locus, cell_counts) in &locus_counts { + let mut total_ref = 0; + let mut total_alt = 0; + for &counts in cell_counts.values() { + total_ref += counts[0]; + total_alt += counts[1]; + } + ref_alt_counts_per_locus.insert(locus, [total_ref, total_alt]); } + + let mut all_loci2: Vec = Vec::new(); for loci in all_loci { all_loci2.push(loci); @@ -450,6 +1015,7 @@ fn load_cell_data(params: &Params) -> (usize, usize, Vec, Vec, } let mut locus_index = 0; for locus in all_loci { + let cell_counts = locus_cell_counts.get(&locus).unwrap(); let umi_counts = locus_umi_counts.get(&locus).unwrap(); if cell_counts[0] >= params.min_ref && cell_counts[1] >= params.min_alt && umi_counts[0] >= params.min_ref_umis && umi_counts[1] >= params.min_alt_umis { @@ -465,23 +1031,26 @@ fn load_cell_data(params: &Params) -> (usize, usize, Vec, Vec, cell_data[*cell].log_binomial_coefficient.push( statrs::function::factorial::ln_binomial((counts[1]+counts[0]) as u64, counts[1] as u64) as f32); cell_data[*cell].total_alleles += (counts[0] + counts[1]) as f32; - //println!("cell {} locus {} alt {} ref {} fraction {}",*cell, locus_index, counts[1], counts[0], - // (counts[1] as f32)/((counts[0] + counts[1]) as f32)); + } locus_index += 1; } } eprintln!("total loci used {}",used_loci.len()); - (used_loci.len(), total_cells, cell_data, index_to_locus, locus_to_index) + + (used_loci.len(), total_cells, cell_data, index_to_locus, locus_to_index, used_loci, cell_count_per_locus, ref_alt_counts_per_locus) } + + + struct CellData { allele_fractions: Vec, log_binomial_coefficient: Vec, alt_counts: Vec, - ref_counts: Vec, - loci: Vec, + ref_counts: Vec, // + loci: Vec,// ID total_alleles: f32, } @@ -501,8 +1070,7 @@ impl CellData { fn load_barcodes(params: &Params) -> Vec { - //let reader = File::open(params.barcodes.to_string()).expect("cannot open barcode file"); - //let reader = BufReader::new(reader); + let reader = reader(¶ms.barcodes); let mut cell_barcodes: Vec = Vec::new(); for line in reader.lines() { @@ -530,6 +1098,8 @@ struct Params { initialization_strategy: ClusterInit, threads: usize, seed: u8, + cell_hashing_assignments: Option, + } #[derive(Clone)] @@ -602,6 +1172,14 @@ fn load_params() -> Params { let min_alt_umis = params.value_of("min_alt_umis").unwrap_or("0"); let min_alt_umis = min_alt_umis.to_string().parse::().unwrap(); + //reza + let cell_hashing_assignments = params.value_of("cell_hashing_assignments"); + let cell_hashing_assignments = match cell_hashing_assignments { + Some(x) => Some(x.to_string()), + None => None, + }; + //reza + Params{ ref_mtx: ref_mtx.to_string(), alt_mtx: alt_mtx.to_string(), @@ -618,6 +1196,7 @@ fn load_params() -> Params { seed: seed, min_alt_umis: min_alt_umis, min_ref_umis: min_ref_umis, + cell_hashing_assignments: cell_hashing_assignments, } } @@ -628,3 +1207,324 @@ fn new_seed(rng: &mut StdRng) -> [u8; 32] { } seed } + + + + + + +fn total_loglikelihood_cell_hashing( + cell_data: &Vec, + cluster_centers: &Vec>, + log_prior: f32, + cell_id_to_label_map: &HashMap) -> f32 { + + let mut log_binom_loss = 0.0; + let mut cell_log_loss: Vec = Vec::new(); + + for (celldex, cell) in cell_data.iter().enumerate() { + + let log_binoms = robust_binomial_loss(cell, &cluster_centers, log_prior, celldex); + let log_loss = log_sum_exp(&log_binoms); + log_binom_loss += log_loss; + cell_log_loss.push(log_loss); + } + + log_binom_loss + + +} + + + + + + +fn robust_binomial_loss(cell_data: &CellData, cluster_centers: &Vec>, log_prior: f32, cellnum: usize) -> Vec { + let mut log_probabilities: Vec = Vec::new(); + let mut sum = 0.0; + + for (cluster, center) in cluster_centers.iter().enumerate() { + log_probabilities.push(log_prior); + for (locus_index, locus) in cell_data.loci.iter().enumerate() { + let alt_term = (cell_data.alt_counts[locus_index] as f32) * safe_ln(center[*locus]); + let ref_term = (cell_data.ref_counts[locus_index] as f32) * safe_ln(1.0 - center[*locus]); + log_probabilities[cluster] += cell_data.log_binomial_coefficient[locus_index] + alt_term + ref_term; + } + + sum += log_probabilities[cluster]; + } + + log_probabilities +} + +fn safe_ln(x: f32) -> f32 { + if x > 0.0 { + x.ln() + } else { + (1e-6f32).ln() + } +} + + + + + + + +//begining of reza snippet + + +fn print_cluster_centers_column_by_column(cluster_centers: &Vec>) { + if cluster_centers.is_empty() { + return; + } + + let num_columns = cluster_centers[0].len(); + for col in 0..num_columns { + println!("Column {}:", col); + for (cluster_index, cluster) in cluster_centers.iter().enumerate() { + if let Some(value) = cluster.get(col) { + println!(" Cluster {}: {}", cluster_index, value); + } else { + println!(" Cluster {}: Out of bounds", cluster_index); + } + } + println!(); + } +} + + + +fn initialize_cluster_centers_cell_hashing(loci_used: &HashSet, + cell_data_from_sc: &Vec, barcodes: Vec, params: &Params) + -> (Vec>, HashMap, HashMap, Vec<(String, String)>) { + + let columns = loci_used.len(); + let rows = 2; + let mut cluster_centers = vec![vec![0.0; (columns)]; rows]; + + // HAYNES + let mut barcode_to_cell_id_and_hash: HashMap = HashMap::new(); + let mut cell_id_to_barcode_and_hash: Vec<(String, String)> = Vec::new(); + + let mut loci_vec: Vec = loci_used.iter().cloned().collect(); + loci_vec.sort_unstable(); + + let assignments_file = match params.cell_hashing_assignments { + Some(ref filename) => File::open(filename) + .expect("Unable to open cell_hashing_assignments.tsv"), + None => panic!("cell_hashing_assignments file not specified"), + }; + + let assignments: Vec = BufReader::new(assignments_file) + .lines() + .collect::>() + .expect("Unable to read lines from cell_hashing_assignments.tsv"); + + + + + let alt_file = File::open(¶ms.alt_mtx.to_string()).expect("Unable to open alt.mtx"); + let alt_lines: Vec = BufReader::new(alt_file).lines() + .skip(3) // Skip the first three lines + .map(|line| line.expect("Unable to read line")) + .collect(); + + let ref_file = File::open(¶ms.ref_mtx).expect("Unable to open ref.mtx"); + let ref_lines: Vec = BufReader::new(ref_file).lines() + .skip(3) // Skip the first three lines + .map(|line| line.expect("Unable to read line")) + .collect(); + + + let mut assignments_map: HashMap = HashMap::new(); + + for (id,line) in assignments.iter().enumerate() { + let parts: Vec<&str> = line.split('\t').collect(); + if parts.len() == 2 { + let barcode = parts[0].to_string(); + let assignment = parts[1].to_string(); + + // Check if the assignment ends with "C1" or "A" + if assignment.ends_with("C1") { + assignments_map.insert(barcode.to_string(), "C1".to_string()); + barcode_to_cell_id_and_hash.insert(barcode.to_string(), (id, "C1".to_string())); + cell_id_to_barcode_and_hash.push((barcode, "C1".to_string())); + } else if assignment.ends_with("A") { + assignments_map.insert(barcode.to_string(), "A".to_string()); + barcode_to_cell_id_and_hash.insert(barcode.to_string(), (id, "A".to_string())); + cell_id_to_barcode_and_hash.push((barcode, "A".to_string())); + } + } + } + + let mut cell_id_to_label_map: HashMap = HashMap::new(); + + for (index, barcode) in barcodes.iter().enumerate() { + let cell_id = index + 0; + if let Some(label) = assignments_map.get(barcode) { + // println!("barcode {} label {} cell_id {}", barcode, label, cell_id); + cell_id_to_label_map.insert(cell_id, label.clone()); + } + } + + let mut cell_to_locus_to_alt: HashMap> = HashMap::new(); + let mut locus_to_cell_id: HashMap> = HashMap::new(); + + for alt_line in alt_lines.iter() { + let tokens: Vec<&str> = alt_line.split_whitespace().collect(); + let locus = tokens[0].parse::().unwrap() - 1; + let cell = tokens[1].parse::().unwrap() - 1; + let count = tokens[2].parse::().unwrap(); + + cell_to_locus_to_alt.entry(cell) + .or_insert_with(HashMap::new) + .insert(locus , count); + + locus_to_cell_id.entry(locus) + .or_insert_with(Vec::new) + .push(cell); + + } + + let mut cell_to_locus_to_ref: HashMap> = HashMap::new(); + + for ref_line in ref_lines.iter() { + let tokens: Vec<&str> = ref_line.split_whitespace().collect(); + let locus = tokens[0].parse::().unwrap() - 1; + let cell = tokens[1].parse::().unwrap() - 1; + let count = tokens[2].parse::().unwrap(); + + cell_to_locus_to_ref.entry(cell) + .or_insert_with(HashMap::new) + .insert(locus , count); + } + + generate_cell_hashing_cluster_centers(&cell_id_to_label_map, + &cell_to_locus_to_alt, &cell_to_locus_to_ref, + &locus_to_cell_id, &loci_vec, &mut cluster_centers); + + + + // for row in cluster_centers.iter_mut() { + // for value in row.iter_mut() { + // if *value == 0.0 { + // *value = 0.0001; + // } + // } + // } + + + (cluster_centers, cell_id_to_label_map, barcode_to_cell_id_and_hash, cell_id_to_barcode_and_hash) +} + + + +fn generate_cell_hashing_cluster_centers(cell_id_to_label_map: &HashMap, + cell_to_locus_to_alt: &HashMap>, + cell_to_locus_to_ref: &HashMap>, + locus_to_cell_id: &HashMap>, loci_vec: &Vec, cluster_centers: &mut Vec>) { + + let mut A_num: usize = 0; + let mut A_denom: usize = 0; + let mut C1_denom: usize = 0; + let mut C1_num: usize = 0; + + let mut current_locus_index = 0; + let mut c1_no_counts = 0; + let mut c2_no_counts = 0; + for &temp_loci in loci_vec.iter() { + + let actual_loci = temp_loci + 0; + C1_num = 0; + C1_denom = 0; + A_num = 0; + A_denom = 0; + + + match locus_to_cell_id.get(&actual_loci) { + Some(cells) => { + //wanna print the length of cells + // println!("loci id = {}, number of cells {}", actual_loci , cells.len()); + + for &cell in cells.iter() { + + let mut label = String::new(); + + if let Some(l) = cell_id_to_label_map.get(&cell) { + label = l.clone(); + } + + if label == "C1" { + + let mut alt_count = cell_to_locus_to_alt.get(&cell).and_then(|locus_map| locus_map.get(&actual_loci)).copied(); + let mut alt_value: usize = 0; + if let Some(value) = alt_count { + C1_num += value; + alt_value = value; + } + let mut ref_count =cell_to_locus_to_ref.get(&cell).and_then(|locus_map| locus_map.get(&actual_loci)).copied(); + if let Some(value) = ref_count { + C1_denom += value + alt_value; + } + + + } + else if label == "A" { + let mut alt_count = cell_to_locus_to_alt.get(&cell).and_then(|locus_map| locus_map.get(&actual_loci)).copied(); + + let mut alt_value: usize = 0; + if let Some(value) = alt_count { + A_num += value; + alt_value = value; + } + let mut ref_count =cell_to_locus_to_ref.get(&cell).and_then(|locus_map| locus_map.get(&actual_loci)).copied(); + if let Some(value) = ref_count { + A_denom += value + alt_value; + } + } + } + + }, + None => { + println!("No cells found for locus ID {}", temp_loci); + } + + } + if C1_denom != 0 { + cluster_centers[0][current_locus_index] = C1_num as f32 / C1_denom as f32 + } else { + c1_no_counts += 1; + //eprintln!("locus {} cluster 0 has no counts",current_locus_index); + } + + if A_denom != 0 { + cluster_centers[1][current_locus_index] = A_num as f32 / A_denom as f32; + } else { + c2_no_counts += 1; + //eprintln!("locus {} cluster 1 has no counts",current_locus_index); + } + cluster_centers[0][current_locus_index] = cluster_centers[0][current_locus_index].min(0.99).max(0.01); + cluster_centers[1][current_locus_index] = cluster_centers[1][current_locus_index].min(0.99).max(0.01); + + + current_locus_index += 1; + + } + + // eprintln!("cluster 1 had {} no_counts_loci and cluster 2 had {} no_counts_loci",c1_no_counts, c2_no_counts); + +} + + + +// end of reza snippet + + + + +// this annealing schedule is totally heuristic + // this annealing schedule is based on the idea that the more data a cell has, + // the smoother we need to make the probability space to avoid near 1.0 and 0.0 probabilities + // until the search is closer to converging \ No newline at end of file diff --git a/souporcell/src/params.yml b/souporcell/src/params.yml index db70e0f..f27cc1d 100644 --- a/souporcell/src/params.yml +++ b/souporcell/src/params.yml @@ -21,6 +21,11 @@ args: takes_value: true required: true help: cell barcodes + - cell_hashing_assignments: + long: cell_hashing_assignments + short: c + takes_value: true + required: false - num_clusters: long: num_clusters short: k