diff --git a/.gitignore b/.gitignore index a75b2f4c86..874da0a370 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ target enclone_exec/test/inputs/version14/85679/outs/raw_feature_bc_matrix/matrix.bin enclone_exec/testx/outputs enclone-data -enclone_visual/outputs -enclone_visual/unofficial_images stamps/data_version_in_use stamps/last_sweep stamps/last_linktest diff --git a/Cargo.lock b/Cargo.lock index ef5ea38e7f..50c205b165 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,22 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "ab_glyph" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" - [[package]] name = "addr2line" version = "0.21.0" @@ -39,17 +23,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - [[package]] name = "aho-corasick" version = "0.7.18" @@ -62,7 +35,7 @@ dependencies = [ [[package]] name = "align_tools" version = "0.1.12" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "bio_edit", "debruijn", @@ -74,7 +47,7 @@ dependencies = [ [[package]] name = "amino" version = "0.1.7" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "debruijn", "string_utils", @@ -83,7 +56,7 @@ dependencies = [ [[package]] name = "ansi_escape" version = "0.1.3" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "string_utils", "vector_utils", @@ -104,26 +77,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arboard" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6045ca509e4abacde2b884ac4618a51d0c017b5d85a3ee84a7226eb33b3154a9" -dependencies = [ - "clipboard-win 4.4.1", - "core-graphics 0.22.3", - "image", - "log", - "objc", - "objc-foundation", - "objc_id", - "once_cell", - "parking_lot 0.12.0", - "thiserror", - "winapi", - "x11rb 0.9.0", -] - [[package]] name = "arrayref" version = "0.3.6" @@ -148,182 +101,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109" -[[package]] -name = "ash" -version = "0.34.0+1.2.203" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df" -dependencies = [ - "libloading", -] - -[[package]] -name = "async-channel" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c290043c9a95b05d45e952fb6383c67bcb61471f60cfa21e890dba6654234f43" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-mutex", - "blocking", - "futures-lite", - "num_cpus", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" -dependencies = [ - "concurrent-queue", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi", -] - -[[package]] -name = "async-lock" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" -dependencies = [ - "async-io", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi", -] - -[[package]] -name = "async-std" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52580991739c5cdb36cde8b2a516371c0a3b70dda36d916cc08b82372916808c" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" -dependencies = [ - "async-stream-impl", - "futures-core", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-task" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" - -[[package]] -name = "async-trait" -version = "0.1.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6aa3524a2dfcf9fe180c51eae2b58738348d819517ceadf95789c51fff7600" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "attohttpc" version = "0.18.0" @@ -370,7 +147,7 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide 0.7.1", "object", @@ -386,7 +163,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "binary_vec_io" version = "0.1.12" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "itertools", ] @@ -425,7 +202,7 @@ dependencies = [ "newtype_derive", "num-integer", "num-traits", - "ordered-float 1.1.1", + "ordered-float", "petgraph", "rand", "regex", @@ -455,7 +232,7 @@ dependencies = [ [[package]] name = "bio_edit" version = "0.1.1" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "bio-types", "bit-set", @@ -488,12 +265,6 @@ version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - [[package]] name = "block-buffer" version = "0.10.2" @@ -503,20 +274,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - [[package]] name = "boomphf" version = "0.5.9" @@ -569,20 +326,6 @@ name = "bytemuck" version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "byteorder" @@ -617,22 +360,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "cache-padded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" - -[[package]] -name = "calloop" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82" -dependencies = [ - "log", - "nix 0.22.3", -] - [[package]] name = "cc" version = "1.0.73" @@ -642,24 +369,12 @@ dependencies = [ "jobserver", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "chrono" version = "0.4.19" @@ -673,408 +388,139 @@ dependencies = [ ] [[package]] -name = "clipboard" -version = "0.5.0" +name = "cmake" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7" +checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" dependencies = [ - "clipboard-win 2.2.0", - "objc", - "objc-foundation", - "objc_id", - "x11-clipboard", + "cc", ] [[package]] -name = "clipboard-win" -version = "2.2.0" +name = "cpp_demangle" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" dependencies = [ - "winapi", + "cfg-if", ] [[package]] -name = "clipboard-win" -version = "4.4.1" +name = "cpufeatures" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3e1238132dc01f081e1cbb9dace14e5ef4c3a51ee244bd982275fb514605db" +checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" dependencies = [ - "error-code", - "str-buf", - "winapi", + "libc", ] [[package]] -name = "clipboard_macos" -version = "0.1.0" +name = "crc" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" +checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" dependencies = [ - "objc", - "objc-foundation", - "objc_id", + "crc-catalog", ] [[package]] -name = "clipboard_wayland" -version = "0.2.0" +name = "crc-catalog" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6364a9f7a66f2ac1a1a098aa1c7f6b686f2496c6ac5e5c0d773445df912747" -dependencies = [ - "smithay-clipboard", -] +checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" [[package]] -name = "clipboard_x11" -version = "0.3.1" +name = "crc32fast" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64240d63f1883d87e5637bfcaf9d77e5c8bd24e30fd440ea2dff5c48c0bf0b7a" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "thiserror", - "x11rb 0.8.1", + "cfg-if", ] [[package]] -name = "cmake" -version = "0.1.48" +name = "crossbeam-channel" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ - "cc", + "cfg-if", + "crossbeam-utils", ] [[package]] -name = "cocoa" -version = "0.24.0" +name = "crossbeam-deque" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation 0.9.3", - "core-graphics 0.22.3", - "foreign-types", - "libc", - "objc", + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "cocoa-foundation" -version = "0.1.0" +name = "crossbeam-epoch" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation 0.9.3", - "core-graphics-types", - "foreign-types", - "libc", - "objc", + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", ] [[package]] -name = "codespan-reporting" -version = "0.11.1" +name = "crossbeam-utils" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ - "termcolor", - "unicode-width", + "cfg-if", + "lazy_static", ] [[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "concurrent-queue" -version = "1.2.2" +name = "crypto-common" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ - "cache-padded", + "generic-array", + "typenum", ] [[package]] -name = "copyless" -version = "0.1.5" +name = "csv" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] [[package]] -name = "core-foundation" -version = "0.7.0" +name = "csv-core" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" dependencies = [ - "core-foundation-sys 0.7.0", - "libc", + "memchr", ] -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys 0.8.3", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - -[[package]] -name = "core-foundation-sys" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" - -[[package]] -name = "core-graphics" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.7.0", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.3", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.3", - "foreign-types", - "libc", -] - -[[package]] -name = "core-video-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" -dependencies = [ - "cfg-if 0.1.10", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "libc", - "objc", -] - -[[package]] -name = "cpp_demangle" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "cpufeatures" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] - -[[package]] -name = "crypto-common" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "csv" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctor" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - [[package]] name = "custom_derive" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" -[[package]] -name = "d3d12" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" -dependencies = [ - "bitflags 1.3.2", - "libloading", - "winapi", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core", - "quote", - "syn", -] - [[package]] name = "data-url" version = "0.1.1" @@ -1110,16 +556,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - [[package]] name = "deflate" version = "1.0.0" @@ -1170,31 +606,10 @@ dependencies = [ "winapi", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading", -] - [[package]] name = "dna" version = "0.1.3" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" [[package]] name = "edit-distance" @@ -1211,7 +626,7 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "enclone" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "amino", "ansi_escape", @@ -1238,7 +653,7 @@ dependencies = [ [[package]] name = "enclone_args" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "debruijn", "enclone_core", @@ -1248,7 +663,6 @@ dependencies = [ "hdf5", "io_utils", "itertools", - "mirror_sparse_matrix", "rand", "rayon", "regex", @@ -1272,7 +686,7 @@ dependencies = [ [[package]] name = "enclone_core" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "amino", "ansi_escape", @@ -1285,7 +699,6 @@ dependencies = [ "io_utils", "itertools", "lazy_static", - "mirror_sparse_matrix", "perf_stats", "qd", "rayon", @@ -1347,7 +760,6 @@ dependencies = [ "enclone_testlist", "enclone_tools", "enclone_vars", - "enclone_visual", "flate2", "fs_extra", "home", @@ -1439,7 +851,7 @@ dependencies = [ [[package]] name = "enclone_print" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "amino", "ansi_escape", @@ -1471,11 +883,11 @@ dependencies = [ [[package]] name = "enclone_proto" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "bio_edit", "byteorder", - "prost 0.9.0", + "prost", "serde", "thiserror", "vdj_ann", @@ -1484,7 +896,7 @@ dependencies = [ [[package]] name = "enclone_ranger" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "enclone", "enclone_args", @@ -1500,7 +912,7 @@ dependencies = [ [[package]] name = "enclone_stuff" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "amino", "debruijn", @@ -1546,7 +958,6 @@ dependencies = [ "io_utils", "itertools", "lazy_static", - "mirror_sparse_matrix", "ndarray", "palette", "perf_stats", @@ -1599,7 +1010,6 @@ dependencies = [ "io_utils", "itertools", "lz4", - "mirror_sparse_matrix", "pager", "perf_stats", "pretty_trace", @@ -1619,7 +1029,7 @@ dependencies = [ [[package]] name = "enclone_vars" version = "0.5.219" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "io_utils", "itertools", @@ -1636,61 +1046,6 @@ dependencies = [ "string_utils", ] -[[package]] -name = "enclone_visual" -version = "0.5.219" -dependencies = [ - "anyhow", - "arboard", - "base64", - "chrono", - "clipboard", - "cocoa", - "core-foundation 0.9.3", - "core-graphics 0.22.3", - "crc", - "dirs", - "enclone_build", - "enclone_core", - "enclone_main", - "enclone_stuff", - "enclone_tail", - "enclone_version", - "flate2", - "fs_extra", - "home", - "iced", - "iced_native", - "image", - "include_dir", - "io_utils", - "itertools", - "jpeg-decoder 0.2.5", - "lazy_static", - "libc", - "log", - "mach", - "nix 0.27.1", - "num-traits", - "objc", - "perf_stats", - "png-decoder", - "pretty_trace", - "procfs", - "prost 0.9.0", - "rayon", - "serde_json", - "string_utils", - "tables", - "tokio", - "tokio-stream", - "tonic", - "tonic-build", - "users", - "vector_utils", - "whoami", -] - [[package]] name = "enum-map" version = "1.1.1" @@ -1714,7 +1069,7 @@ dependencies = [ [[package]] name = "equiv" version = "0.1.3" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" [[package]] name = "errno" @@ -1737,41 +1092,16 @@ dependencies = [ "libc", ] -[[package]] -name = "error-code" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" -dependencies = [ - "libc", - "str-buf", -] - -[[package]] -name = "euclid" -version = "0.22.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b52c2ef4a78da0ba68fbe1fd920627411096d2ac478f7f4c9f3a54ba6705bade" -dependencies = [ - "num-traits", -] - [[package]] name = "evalexpr" version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d4fd7bd9e32c1205549decf6f36772d7b606a579b26afaffa335ae148151a5d" -[[package]] -name = "event-listener" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" - [[package]] name = "exons" version = "0.1.5" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "io_utils", "string_utils", @@ -1781,7 +1111,7 @@ dependencies = [ [[package]] name = "expr_tools" version = "0.1.3" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "evalexpr", "statrs", @@ -1792,7 +1122,7 @@ dependencies = [ [[package]] name = "fasta_tools" version = "0.1.8" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "debruijn", "flate2", @@ -1821,7 +1151,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "winapi", @@ -1860,7 +1190,7 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crc32fast", "libc", "miniz_oxide 0.5.1", @@ -1878,15 +1208,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" -[[package]] -name = "float_next_after" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632" -dependencies = [ - "num-traits", -] - [[package]] name = "fnv" version = "1.0.7" @@ -1900,25 +1221,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01b07f5c05414a0d8caba4c17eef8dc8b5c8955fc7c68d324191c7a56d3f3449" dependencies = [ "log", - "memmap2 0.5.3", - "ttf-parser 0.12.3", + "memmap2", + "ttf-parser", ] -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.0.1" @@ -1935,111 +1241,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" -[[package]] -name = "futures" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" - -[[package]] -name = "futures-executor" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" - -[[package]] -name = "futures-task" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" - -[[package]] -name = "futures-util" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - [[package]] name = "fxhash" version = "0.2.1" @@ -2059,25 +1260,15 @@ dependencies = [ "version_check", ] -[[package]] -name = "gethostname" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "getrandom" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -2092,185 +1283,26 @@ dependencies = [ "syn", ] -[[package]] -name = "gif" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b" -dependencies = [ - "color_quant", - "weezl", -] - [[package]] name = "gimli" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" -[[package]] -name = "glam" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579160312273c954cc51bd440f059dde741029ac8daf8c84fece76cb77f62c15" -dependencies = [ - "version_check", -] - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "gloo-timers" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "glow" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21932fbf719272848eec4583740d978203c6e7da4c4e203358f5b95946c97409" -dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "log", - "ordered-float 2.10.0", - "rustc-hash", - "twox-hash", -] - -[[package]] -name = "glyph_brush_draw_cache" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6010675390f6889e09a21e2c8b575b3ee25667ea8237a8d59423f73cb8c28610" -dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" -dependencies = [ - "ab_glyph", - "approx", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" -dependencies = [ - "bitflags 1.3.2", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" -dependencies = [ - "bitflags 1.3.2", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "graph_simple" version = "0.1.5" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "petgraph", "vector_utils", ] -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "h2" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util 0.7.1", - "tracing", -] - [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] [[package]] name = "hdf5" @@ -2278,14 +1310,14 @@ version = "0.8.1" source = "git+https://github.com/10XGenomics/hdf5-rust.git?branch=conda_nov2021#2d4a40b7ef75de530bc53fd2eb0fe75047e083ad" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "hdf5-derive", "hdf5-sys", "hdf5-types", "lazy_static", "libc", "ndarray", - "parking_lot 0.12.0", + "parking_lot", "paste", ] @@ -2305,7 +1337,7 @@ name = "hdf5-sys" version = "0.8.1" source = "git+https://github.com/10XGenomics/hdf5-rust.git?branch=conda_nov2021#2d4a40b7ef75de530bc53fd2eb0fe75047e083ad" dependencies = [ - "attohttpc 0.19.1", + "attohttpc 0.18.0", "bzip2", "libc", "libloading", @@ -2324,7 +1356,7 @@ version = "0.8.1" source = "git+https://github.com/10XGenomics/hdf5-rust.git?branch=conda_nov2021#2d4a40b7ef75de530bc53fd2eb0fe75047e083ad" dependencies = [ "ascii", - "cfg-if 1.0.0", + "cfg-if", "hdf5-sys", "libc", ] @@ -2353,18 +1385,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - [[package]] name = "home" version = "0.5.3" @@ -2385,69 +1405,10 @@ dependencies = [ "itoa 1.0.1", ] -[[package]] -name = "http-body" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "hyper" -version = "0.14.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.1", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - [[package]] name = "hyperbase" version = "0.1.8" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "debruijn", "equiv", @@ -2457,118 +1418,6 @@ dependencies = [ "vector_utils", ] -[[package]] -name = "iced" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "iced_core", - "iced_futures", - "iced_graphics", - "iced_native", - "iced_wgpu", - "iced_winit", - "thiserror", -] - -[[package]] -name = "iced_core" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "bitflags 1.3.2", - "wasm-timer", -] - -[[package]] -name = "iced_futures" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "async-std", - "futures", - "log", - "wasm-bindgen-futures", - "wasm-timer", -] - -[[package]] -name = "iced_graphics" -version = "0.2.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "bytemuck", - "glam", - "iced_native", - "iced_style", - "lyon", - "raw-window-handle 0.4.3", - "thiserror", -] - -[[package]] -name = "iced_native" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "iced_core", - "iced_futures", - "iced_style", - "num-traits", - "twox-hash", - "unicode-segmentation", -] - -[[package]] -name = "iced_style" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "iced_core", -] - -[[package]] -name = "iced_wgpu" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "futures", - "glyph_brush", - "guillotiere", - "iced_graphics", - "iced_native", - "image", - "kamadak-exif", - "log", - "raw-window-handle 0.4.3", - "wgpu", - "wgpu_glyph", -] - -[[package]] -name = "iced_winit" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=3042fa2cb63c651ebed2abe6f4054e61f70b0331#3042fa2cb63c651ebed2abe6f4054e61f70b0331" -dependencies = [ - "iced_futures", - "iced_graphics", - "iced_native", - "log", - "thiserror", - "web-sys", - "winapi", - "window_clipboard", - "winit", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.2.3" @@ -2580,48 +1429,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "image" -version = "0.23.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "gif", - "jpeg-decoder 0.1.22", - "num-iter", - "num-rational 0.3.2", - "num-traits", - "png 0.16.8", - "tiff", -] - -[[package]] -name = "include_dir" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b56e147e6187d61e9d0f039f10e070d0c0a887e24fe0bb9ca3f29bfde62cab" -dependencies = [ - "glob", - "include_dir_impl", - "proc-macro-hack", -] - -[[package]] -name = "include_dir_impl" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0c890c85da4bab7bce4204c707396bbd3c6c8a681716a51c8814cfc2b682df" -dependencies = [ - "anyhow", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "indexmap" version = "1.8.1" @@ -2632,28 +1439,19 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "inplace_it" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" - [[package]] name = "instant" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", + "cfg-if", ] [[package]] name = "io_utils" version = "0.3.2" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "bincode", "flate2", @@ -2692,12 +1490,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - [[package]] name = "jobserver" version = "0.1.24" @@ -2712,18 +1504,6 @@ name = "jpeg-decoder" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" -dependencies = [ - "rayon", -] - -[[package]] -name = "jpeg-decoder" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be7ef4b99870f0c9f2fc2f20dbef72707e2bcca675bb9196734cf433e999b0c5" -dependencies = [ - "rayon", -] [[package]] name = "js-sys" @@ -2734,29 +1514,10 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kamadak-exif" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70494964492bf8e491eb3951c5d70c9627eb7100ede6cc56d748b9a3f302cfb6" -dependencies = [ - "mutate_once", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading", -] - [[package]] name = "kmer_lookup" version = "0.1.5" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "debruijn", "rayon", @@ -2772,15 +1533,6 @@ dependencies = [ "arrayvec 0.7.2", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -2799,7 +1551,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "winapi", ] @@ -2831,58 +1583,7 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", - "value-bag", -] - -[[package]] -name = "lyon" -version = "0.17.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf0510ed5e3e2fb80f3db2061ef5ca92d87bfda1a624bb1eacf3bd50226e4cbb" -dependencies = [ - "lyon_algorithms", - "lyon_tessellation", -] - -[[package]] -name = "lyon_algorithms" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8037f716541ba0d84d3de05c0069f8068baf73990d55980558b84d944c8a244a" -dependencies = [ - "lyon_path", - "sid", -] - -[[package]] -name = "lyon_geom" -version = "0.17.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce99ce77c22bfd8f39a95b9c749dffbfc3e2491ea30c874764c801a8b1485489" -dependencies = [ - "arrayvec 0.5.2", - "euclid", - "num-traits", -] - -[[package]] -name = "lyon_path" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0" -dependencies = [ - "lyon_geom", -] - -[[package]] -name = "lyon_tessellation" -version = "0.17.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760" -dependencies = [ - "float_next_after", - "lyon_path", + "cfg-if", ] [[package]] @@ -2905,24 +1606,6 @@ dependencies = [ "libc", ] -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - [[package]] name = "matches" version = "0.1.9" @@ -2944,15 +1627,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "memmap2" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357" -dependencies = [ - "libc", -] - [[package]] name = "memmap2" version = "0.5.3" @@ -2971,92 +1645,22 @@ dependencies = [ "autocfg", ] -[[package]] -name = "metal" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - -[[package]] -name = "miniz_oxide" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" -dependencies = [ - "adler", - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" -dependencies = [ - "adler", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" -dependencies = [ - "libc", - "log", - "miow", - "ntapi", - "wasi 0.11.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ - "winapi", + "adler", ] [[package]] -name = "mirror_sparse_matrix" -version = "0.1.17" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ - "binary_vec_io", + "adler", ] [[package]] @@ -3068,30 +1672,6 @@ dependencies = [ "serde", ] -[[package]] -name = "mutate_once" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" - -[[package]] -name = "naga" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705" -dependencies = [ - "bit-set", - "bitflags 1.3.2", - "codespan-reporting", - "hexf-parse", - "indexmap", - "log", - "num-traits", - "rustc-hash", - "spirv", - "thiserror", -] - [[package]] name = "nalgebra" version = "0.27.1" @@ -3102,7 +1682,7 @@ dependencies = [ "matrixmultiply", "nalgebra-macros", "num-complex", - "num-rational 0.4.0", + "num-rational", "num-traits", "rand", "rand_distr", @@ -3134,59 +1714,6 @@ dependencies = [ "rawpointer", ] -[[package]] -name = "ndk" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-glue" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71bee8ea72d685477e28bd004cfe1bf99c754d688cd78cad139eae4089484d4" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-macro", - "ndk-sys", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" - [[package]] name = "newtype_derive" version = "0.1.6" @@ -3196,31 +1723,6 @@ dependencies = [ "rustc_version", ] -[[package]] -name = "nix" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 1.0.0", - "libc", -] - -[[package]] -name = "nix" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 1.0.0", - "libc", - "memoffset", -] - [[package]] name = "nix" version = "0.24.2" @@ -3228,7 +1730,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset", ] @@ -3240,29 +1742,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ "bitflags 2.4.2", - "cfg-if 1.0.0", + "cfg-if", "libc", ] -[[package]] -name = "nom" -version = "7.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "ntapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" -dependencies = [ - "winapi", -] - [[package]] name = "num-complex" version = "0.4.1" @@ -3282,28 +1765,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.0" @@ -3335,66 +1796,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - [[package]] name = "object" version = "0.32.1" @@ -3419,24 +1820,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1e509cfe7a12db2a90bfa057dfcdbc55a347f5da677c506b53dd099cfec9d" -dependencies = [ - "ttf-parser 0.15.0", -] - [[package]] name = "pager" version = "0.16.0" @@ -3471,23 +1854,6 @@ dependencies = [ "syn", ] -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.5", -] - [[package]] name = "parking_lot" version = "0.12.0" @@ -3495,21 +1861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ "lock_api", - "parking_lot_core 0.9.3", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -3518,7 +1870,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall", "smallvec", @@ -3540,7 +1892,7 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "perf_stats" version = "0.1.8" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "io_utils", "libc", @@ -3613,38 +1965,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" -[[package]] -name = "pin-project" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "pkg-config" version = "0.3.25" @@ -3679,18 +2005,6 @@ dependencies = [ "plotters-backend", ] -[[package]] -name = "png" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "deflate 0.8.6", - "miniz_oxide 0.3.7", -] - [[package]] name = "png" version = "0.17.5" @@ -3699,34 +2013,10 @@ checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" dependencies = [ "bitflags 1.3.2", "crc32fast", - "deflate 1.0.0", + "deflate", "miniz_oxide 0.5.1", ] -[[package]] -name = "png-decoder" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824d20c14cc90cb36ff9e6f70587825806f6f20f3c608723096595ed7054e002" -dependencies = [ - "crc32fast", - "miniz_oxide 0.4.4", - "num_enum", -] - -[[package]] -name = "polling" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "log", - "wepoll-ffi", - "winapi", -] - [[package]] name = "pprof" version = "0.9.1" @@ -3734,16 +2024,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97149c0eacaa6b8f8cedea99f68bb3a0517fa20f8de8d8c24c1a810f38d235d" dependencies = [ "backtrace", - "cfg-if 1.0.0", + "cfg-if", "findshlibs", "libc", "log", "nix 0.24.2", "once_cell", - "parking_lot 0.12.0", - "prost 0.10.4", - "prost-build 0.10.4", - "prost-derive 0.10.1", + "parking_lot", + "prost", + "prost-build", + "prost-derive", "smallvec", "symbolic-demangle", "tempfile", @@ -3759,7 +2049,7 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_trace" version = "0.5.24" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "backtrace", "io_utils", @@ -3773,16 +2063,6 @@ dependencies = [ "vector_utils", ] -[[package]] -name = "proc-macro-crate" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" -dependencies = [ - "thiserror", - "toml", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3814,41 +2094,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] -name = "proc-macro2" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "procfs" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0941606b9934e2d98a3677759a971756eb821f75764d0e0d26946d08e74d9104" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "hex", - "lazy_static", - "libc", -] - -[[package]] -name = "profiling" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987" - -[[package]] -name = "prost" -version = "0.9.0" +name = "proc-macro2" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" dependencies = [ - "bytes", - "prost-derive 0.9.0", + "unicode-xid", ] [[package]] @@ -3858,27 +2109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ "bytes", - "prost-derive 0.10.1", -] - -[[package]] -name = "prost-build" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" -dependencies = [ - "bytes", - "heck 0.3.3", - "itertools", - "lazy_static", - "log", - "multimap", - "petgraph", - "prost 0.9.0", - "prost-types 0.9.0", - "regex", - "tempfile", - "which", + "prost-derive", ] [[package]] @@ -3888,7 +2119,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ae5a4388762d5815a9fc0dea33c56b021cdc8dde0c55e0c9ca57197254b0cab" dependencies = [ "bytes", - "cfg-if 1.0.0", + "cfg-if", "cmake", "heck 0.4.0", "itertools", @@ -3896,26 +2127,13 @@ dependencies = [ "log", "multimap", "petgraph", - "prost 0.10.4", - "prost-types 0.10.1", + "prost", + "prost-types", "regex", "tempfile", "which", ] -[[package]] -name = "prost-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "prost-derive" version = "0.10.1" @@ -3929,16 +2147,6 @@ dependencies = [ "syn", ] -[[package]] -name = "prost-types" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a" -dependencies = [ - "bytes", - "prost 0.9.0", -] - [[package]] name = "prost-types" version = "0.10.1" @@ -3946,7 +2154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", - "prost 0.10.4", + "prost", ] [[package]] @@ -4003,31 +2211,6 @@ dependencies = [ "rand", ] -[[package]] -name = "range-alloc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" - -[[package]] -name = "raw-window-handle" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28f55143d0548dad60bb4fbdc835a3d7ac6acc3324506450c5fdd6e42903a76" -dependencies = [ - "libc", - "raw-window-handle 0.4.3", -] - -[[package]] -name = "raw-window-handle" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41" -dependencies = [ - "cty", -] - [[package]] name = "rawpointer" version = "0.2.1" @@ -4116,22 +2299,16 @@ dependencies = [ "winapi", ] -[[package]] -name = "renderdoc-sys" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" - [[package]] name = "resvg" version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "256cc9203115db152290219f35f3362e729301b59e2a391fb2721fe3fa155352" dependencies = [ - "jpeg-decoder 0.1.22", + "jpeg-decoder", "log", "pico-args", - "png 0.17.5", + "png", "rgb", "tiny-skia", "usvg", @@ -4176,12 +2353,6 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc_version" version = "0.1.7" @@ -4218,7 +2389,7 @@ dependencies = [ "bitflags 1.3.2", "bytemuck", "smallvec", - "ttf-parser 0.12.3", + "ttf-parser", "unicode-bidi-mirroring", "unicode-ccc", "unicode-general-category", @@ -4240,12 +2411,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - [[package]] name = "scopeguard" version = "1.1.0" @@ -4305,39 +2470,11 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", ] -[[package]] -name = "sid" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb" -dependencies = [ - "num-traits", -] - -[[package]] -name = "signal-hook" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - [[package]] name = "simba" version = "0.5.1" @@ -4365,94 +2502,24 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" -[[package]] -name = "slab" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" - -[[package]] -name = "slotmap" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check", -] - [[package]] name = "smallvec" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" -[[package]] -name = "smithay-client-toolkit" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3" -dependencies = [ - "bitflags 1.3.2", - "calloop", - "dlib", - "lazy_static", - "log", - "memmap2 0.3.1", - "nix 0.22.3", - "pkg-config", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-clipboard" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610b551bd25378bfd2b8e7a0fcbd83d427e8f2f6a40c47ae0f70688e9949dd55" -dependencies = [ - "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "socket2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags 1.3.2", - "num-traits", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "statrs" version = "0.15.0" @@ -4469,28 +2536,16 @@ dependencies = [ [[package]] name = "stats_utils" version = "0.1.3" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" - -[[package]] -name = "str-buf" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" [[package]] name = "string_utils" version = "0.1.4" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "vector_utils", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strum" version = "0.23.0" @@ -4516,12 +2571,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" -[[package]] -name = "svg_fmt" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" - [[package]] name = "svgtypes" version = "0.8.0" @@ -4538,7 +2587,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f551f902d5642e58039aee6a9021a61037926af96e071816361644983966f540" dependencies = [ "debugid", - "memmap2 0.5.3", + "memmap2", "stable_deref_trait", "uuid", ] @@ -4568,7 +2617,7 @@ dependencies = [ [[package]] name = "tables" version = "0.1.5" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "io_utils", "itertools", @@ -4592,7 +2641,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "libc", "redox_syscall", @@ -4600,15 +2649,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "termcolor" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.31" @@ -4629,17 +2669,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tiff" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" -dependencies = [ - "jpeg-decoder 0.1.22", - "miniz_oxide 0.4.4", - "weezl", -] - [[package]] name = "tilde-expand" version = "0.1.1" @@ -4658,8 +2687,8 @@ dependencies = [ "arrayref", "arrayvec 0.5.2", "bytemuck", - "cfg-if 1.0.0", - "png 0.17.5", + "cfg-if", + "png", "safe_arch", ] @@ -4685,24 +2714,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e050c618355082ae5a89ec63bbf897225d5ffe84c7c4e036874e4d185a5044e" dependencies = [ "bytes", - "libc", "memchr", - "mio", "num_cpus", "pin-project-lite", - "socket2", "tokio-macros", - "winapi", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", ] [[package]] @@ -4716,170 +2731,13 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-stream" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - [[package]] name = "toml" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ - "serde", -] - -[[package]] -name = "tonic" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08f4649d10a70ffa3522ca559031285d8e421d727ac85c60825761818f5d0a" -dependencies = [ - "async-stream", - "async-trait", - "base64", - "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost 0.9.0", - "prost-derive 0.9.0", - "tokio", - "tokio-stream", - "tokio-util 0.6.9", - "tower", - "tower-layer", - "tower-service", - "tracing", - "tracing-futures", -] - -[[package]] -name = "tonic-build" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757" -dependencies = [ - "proc-macro2", - "prost-build 0.9.0", - "quote", - "syn", -] - -[[package]] -name = "tower" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89fd63ad6adf737582df5db40d286574513c69a11dac5214dc3b5603d6713e" -dependencies = [ - "futures-core", - "futures-util", - "indexmap", - "pin-project", - "pin-project-lite", - "rand", - "slab", - "tokio", - "tokio-util 0.7.1", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" - -[[package]] -name = "tower-service" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" - -[[package]] -name = "tracing" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" -dependencies = [ - "cfg-if 1.0.0", - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", + "serde", ] [[package]] @@ -4888,35 +2746,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22048bc95dfb2ffd05b1ff9a756290a009224b60b2f0e7525faeee7603851e63" -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - [[package]] name = "ttf-parser" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ae2f58a822f08abdaf668897e96a5656fe72f5a9ce66422423e8849384872e6" -[[package]] -name = "ttf-parser" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c74c96594835e10fa545e2a51e8709f30b173a092bfd6036ef2cec53376244f3" - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if 1.0.0", - "rand", - "static_assertions", -] - [[package]] name = "typenum" version = "1.15.0" @@ -4974,12 +2809,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" -[[package]] -name = "unicode-width" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" - [[package]] name = "unicode-xid" version = "0.2.3" @@ -5004,16 +2833,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "users" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" -dependencies = [ - "libc", - "log", -] - [[package]] name = "usvg" version = "0.19.0" @@ -5034,7 +2853,7 @@ dependencies = [ "simplecss", "siphasher", "svgtypes", - "ttf-parser 0.12.3", + "ttf-parser", "unicode-bidi", "unicode-script", "unicode-vo", @@ -5047,20 +2866,10 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -[[package]] -name = "value-bag" -version = "1.0.0-alpha.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" -dependencies = [ - "ctor", - "version_check", -] - [[package]] name = "vdj_ann" version = "0.4.4" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "align_tools", "amino", @@ -5082,7 +2891,7 @@ dependencies = [ [[package]] name = "vdj_ann_ref" version = "0.2.1" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "debruijn", "exons", @@ -5100,7 +2909,7 @@ dependencies = [ [[package]] name = "vdj_types" version = "0.2.0" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "serde", ] @@ -5117,7 +2926,7 @@ dependencies = [ [[package]] name = "vector_utils" version = "0.1.5" -source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#181a050785953877c55a3b5df441ff04919ed7cd" +source = "git+https://github.com/10XGenomics/enclone_ranger?branch=main#cdda245c3574d017161932bc2cf554dbb34c3c41" dependencies = [ "permutation", "superslice", @@ -5129,41 +2938,19 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "wasm-bindgen" version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen-macro", ] @@ -5182,18 +2969,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.80" @@ -5223,94 +2998,6 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wayland-client" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f" -dependencies = [ - "bitflags 1.3.2", - "downcast-rs", - "libc", - "nix 0.22.3", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e" -dependencies = [ - "nix 0.22.3", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd" -dependencies = [ - "nix 0.22.3", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741" -dependencies = [ - "bitflags 1.3.2", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.29.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - [[package]] name = "web-sys" version = "0.3.57" @@ -5340,124 +3027,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "weezl" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4" - -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - -[[package]] -name = "wgpu" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97cd781ff044d6d697b632a2e212032c2e957d1afaa21dbf58069cbb8f78567" -dependencies = [ - "arrayvec 0.7.2", - "js-sys", - "log", - "naga", - "parking_lot 0.11.2", - "raw-window-handle 0.4.3", - "smallvec", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d" -dependencies = [ - "arrayvec 0.7.2", - "bitflags 1.3.2", - "cfg_aliases", - "codespan-reporting", - "copyless", - "fxhash", - "log", - "naga", - "parking_lot 0.11.2", - "profiling", - "raw-window-handle 0.4.3", - "smallvec", - "thiserror", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d684ea6a34974a2fc19f1dfd183d11a62e22d75c4f187a574bb1224df8e056c2" -dependencies = [ - "arrayvec 0.7.2", - "ash", - "bit-set", - "bitflags 1.3.2", - "block", - "core-graphics-types", - "d3d12", - "foreign-types", - "fxhash", - "glow", - "gpu-alloc", - "gpu-descriptor", - "inplace_it", - "js-sys", - "khronos-egl", - "libloading", - "log", - "metal", - "naga", - "objc", - "parking_lot 0.11.2", - "profiling", - "range-alloc", - "raw-window-handle 0.4.3", - "renderdoc-sys", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-types" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "wgpu_glyph" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8134edb15ae465caf308125646c9e98bdef7398cdefc69227ac77a5eb795e7fe" -dependencies = [ - "bytemuck", - "glyph_brush", - "log", - "wgpu", -] - [[package]] name = "which" version = "4.2.5" @@ -5469,16 +3038,6 @@ dependencies = [ "libc", ] -[[package]] -name = "whoami" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8" -dependencies = [ - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wildmatch" version = "2.1.0" @@ -5501,44 +3060,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi", -] - [[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 = "window_clipboard" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "086ed826cc4468377b6b995300d5f7f852a2fe1eb02e6cd1ccd4a574deb9d310" -dependencies = [ - "clipboard-win 4.4.1", - "clipboard_macos", - "clipboard_wayland", - "clipboard_x11", - "raw-window-handle 0.3.4", - "thiserror", -] - [[package]] name = "windows-sys" version = "0.36.1" @@ -5582,38 +3109,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" -[[package]] -name = "winit" -version = "0.26.0" -source = "git+https://github.com/iced-rs/winit?rev=02a12380960cec2f351c09a33d6a7cc2789d96a6#02a12380960cec2f351c09a33d6a7cc2789d96a6" -dependencies = [ - "bitflags 1.3.2", - "cocoa", - "core-foundation 0.9.3", - "core-graphics 0.22.3", - "core-video-sys", - "dispatch", - "instant", - "lazy_static", - "libc", - "log", - "mio", - "ndk", - "ndk-glue", - "ndk-sys", - "objc", - "parking_lot 0.11.2", - "percent-encoding", - "raw-window-handle 0.4.3", - "smithay-client-toolkit", - "wasm-bindgen", - "wayland-client", - "wayland-protocols", - "web-sys", - "winapi", - "x11-dl", -] - [[package]] name = "winreg" version = "0.10.1" @@ -5633,50 +3128,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "x11-clipboard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89bd49c06c9eb5d98e6ba6536cf64ac9f7ee3a009b2f53996d405b3944f6bcea" -dependencies = [ - "xcb", -] - -[[package]] -name = "x11-dl" -version = "2.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" -dependencies = [ - "lazy_static", - "libc", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffb080b3f2f616242a4eb8e7d325035312127901025b0052bc3154a282d0f19" -dependencies = [ - "gethostname", - "nix 0.20.0", - "winapi", - "winapi-wsapoll", -] - -[[package]] -name = "x11rb" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e99be55648b3ae2a52342f9a870c0e138709a3493261ce9b469afe6e4df6d8a" -dependencies = [ - "gethostname", - "nix 0.22.3", - "winapi", - "winapi-wsapoll", -] - [[package]] name = "xattr" version = "0.2.3" @@ -5686,37 +3137,6 @@ dependencies = [ "libc", ] -[[package]] -name = "xcb" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de" -dependencies = [ - "libc", - "log", -] - -[[package]] -name = "xcursor" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463705a63313cd4301184381c5e8042f0a7e9b4bb63653f216311d4ae74690b7" -dependencies = [ - "nom", -] - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" - [[package]] name = "xmlparser" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 2f04b4c83e..96ada4421d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,19 +9,10 @@ members = [ "enclone_tail", "enclone_tools", "enclone_version", - "enclone_visual", "enclone_build", "enclone_testlist", ] -exclude = [ - "bugs/button_text_update_issue", - "bugs/canvas_in_scrollable", - # excluding because it's a nuisance to support this - # to restore, add back svg to features for iced - "scroll_crash", -] - resolver = "2" # ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ diff --git a/GUIDE b/GUIDE index 5ad63754be..57d8879d17 100644 --- a/GUIDE +++ b/GUIDE @@ -10,7 +10,6 @@ enclone_paper calculations for enclone paper enclone_tail last part of the code enclone_tools miscellaneous binaries enclone_version determine current version string -enclone_visual experimental GUI client credits credits fonts DejaVuSansMono, in case not otherwise available diff --git a/bugs/button_text_update_issue/.gitignore b/bugs/button_text_update_issue/.gitignore deleted file mode 100644 index eb5a316cbd..0000000000 --- a/bugs/button_text_update_issue/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/bugs/button_text_update_issue/Cargo.lock b/bugs/button_text_update_issue/Cargo.lock deleted file mode 100644 index ca4e7cadc8..0000000000 --- a/bugs/button_text_update_issue/Cargo.lock +++ /dev/null @@ -1,2998 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0ac006645f86f20f6c6fa4dcaef920bf803df819123626f9440e35835e7d80" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser 0.12.0", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" - -[[package]] -name = "ahash" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" - -[[package]] -name = "andrew" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" -dependencies = [ - "bitflags", - "rusttype", - "walkdir", - "xdg", - "xml-rs", -] - -[[package]] -name = "approx" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "ash" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112" -dependencies = [ - "libloading 0.7.0", -] - -[[package]] -name = "async-channel" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-mutex", - "blocking", - "futures-lite", - "num_cpus", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b" -dependencies = [ - "concurrent-queue", - "fastrand", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi 0.3.9", -] - -[[package]] -name = "async-lock" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f38756dd9ac84671c428afbf7c9f7495feff9ec5b0710f17100098e5b354ac" -dependencies = [ - "async-io", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi 0.3.9", -] - -[[package]] -name = "async-std" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bit-set" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "blocking" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - -[[package]] -name = "bumpalo" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" - -[[package]] -name = "bumpalo" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" - -[[package]] -name = "button_text_update_issue" -version = "0.0.1" -dependencies = [ - "iced", - "iced_native", -] - -[[package]] -name = "bytemuck" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cache-padded" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" - -[[package]] -name = "calloop" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" -dependencies = [ - "log", - "nix 0.18.0", -] - -[[package]] -name = "cc" -version = "1.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "clipboard-win" -version = "4.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ea1881992efc993e4dc50a324cdbd03216e41bdc8385720ff47efc9bd2ca8" -dependencies = [ - "error-code", - "str-buf", - "winapi 0.3.9", -] - -[[package]] -name = "clipboard_macos" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" -dependencies = [ - "objc", - "objc-foundation", - "objc_id", -] - -[[package]] -name = "clipboard_wayland" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6364a9f7a66f2ac1a1a098aa1c7f6b686f2496c6ac5e5c0d773445df912747" -dependencies = [ - "smithay-clipboard", -] - -[[package]] -name = "clipboard_x11" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64240d63f1883d87e5637bfcaf9d77e5c8bd24e30fd440ea2dff5c48c0bf0b7a" -dependencies = [ - "thiserror", - "x11rb", -] - -[[package]] -name = "cmake" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" -dependencies = [ - "cc", -] - -[[package]] -name = "cocoa" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.1", - "core-graphics-types", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys 0.7.0", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" -dependencies = [ - "core-foundation-sys 0.8.2", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - -[[package]] -name = "core-foundation-sys" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" - -[[package]] -name = "core-graphics" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" -dependencies = [ - "bitflags", - "core-foundation 0.7.0", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86" -dependencies = [ - "bitflags", - "core-foundation 0.9.1", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation 0.9.1", - "foreign-types", - "libc", -] - -[[package]] -name = "core-text" -version = "19.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" -dependencies = [ - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "foreign-types", - "libc", -] - -[[package]] -name = "core-video-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" -dependencies = [ - "cfg-if 0.1.10", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "libc", - "objc", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "ctor" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "d3d12" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091ed1b25fe47c7ff129fc440c23650b6114f36aa00bc7212cc8041879294428" -dependencies = [ - "bitflags", - "libloading 0.7.0", - "winapi 0.3.9", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" -dependencies = [ - "libloading 0.6.7", -] - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading 0.7.0", -] - -[[package]] -name = "dodrio" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7593dfc68e57dc1d058ada0f151ba07f4b05183c4da4c4df8ff651a81ef0fab" -dependencies = [ - "bumpalo 2.6.0", - "cfg-if 0.1.10", - "fxhash", - "js-sys", - "longest-increasing-subsequence", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "winapi 0.3.9", - "wio", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "error-code" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff" -dependencies = [ - "libc", - "str-buf", -] - -[[package]] -name = "euclid" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80" -dependencies = [ - "num-traits", -] - -[[package]] -name = "event-listener" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" - -[[package]] -name = "expat-sys" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] - -[[package]] -name = "fastrand" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" -dependencies = [ - "instant", -] - -[[package]] -name = "fixedbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" - -[[package]] -name = "float-ord" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "font-kit" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28" -dependencies = [ - "bitflags", - "byteorder", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "core-text", - "dirs-next", - "dwrote", - "float-ord", - "freetype", - "lazy_static", - "libc", - "log", - "pathfinder_geometry", - "pathfinder_simd", - "servo-fontconfig", - "walkdir", - "winapi 0.3.9", -] - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", -] - -[[package]] -name = "freetype" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" -dependencies = [ - "freetype-sys", - "libc", -] - -[[package]] -name = "freetype-sys" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" -dependencies = [ - "cmake", - "libc", - "pkg-config", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" - -[[package]] -name = "futures-executor" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" -dependencies = [ - "autocfg", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" - -[[package]] -name = "futures-task" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" - -[[package]] -name = "futures-util" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" -dependencies = [ - "autocfg", - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "proc-macro-hack", - "proc-macro-nested", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gethostname" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "gfx-auxil" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccf8711c9994dfa34337466bee3ae1462e172874c432ce4eb120ab2e98d39cf" -dependencies = [ - "fxhash", - "gfx-hal", - "spirv_cross", -] - -[[package]] -name = "gfx-backend-dx11" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f839f27f8c8a6dc553ccca7f5b35a42009432bc25db9688bba7061cd394161f" -dependencies = [ - "arrayvec", - "bitflags", - "gfx-auxil", - "gfx-hal", - "libloading 0.7.0", - "log", - "parking_lot", - "range-alloc", - "raw-window-handle", - "smallvec", - "spirv_cross", - "thunderdome", - "winapi 0.3.9", - "wio", -] - -[[package]] -name = "gfx-backend-dx12" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3937738b0da5839bba4e33980d29f9a06dbce184d04a3a08c9a949e7953700e3" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags", - "d3d12", - "gfx-auxil", - "gfx-hal", - "log", - "parking_lot", - "range-alloc", - "raw-window-handle", - "smallvec", - "spirv_cross", - "thunderdome", - "winapi 0.3.9", -] - -[[package]] -name = "gfx-backend-empty" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac55ada4bfcd35479b3421eea324d36d7da5f724e2f66ecb36d4efdb7041a5e" -dependencies = [ - "gfx-hal", - "log", - "raw-window-handle", -] - -[[package]] -name = "gfx-backend-gl" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0caa03d6e0b7b4f202aea1f20c3f3288cfa06d92d24cea9d69c9a7627967244a" -dependencies = [ - "arrayvec", - "bitflags", - "fxhash", - "gfx-hal", - "glow", - "js-sys", - "khronos-egl", - "libloading 0.7.0", - "log", - "naga", - "parking_lot", - "raw-window-handle", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "gfx-backend-metal" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340895ad544ba46433acb3bdabece0ef16f2dbedc030adbd7c9eaf2839fbed41" -dependencies = [ - "arrayvec", - "bitflags", - "block", - "cocoa-foundation", - "copyless", - "foreign-types", - "fxhash", - "gfx-hal", - "log", - "metal", - "naga", - "objc", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "storage-map", -] - -[[package]] -name = "gfx-backend-vulkan" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a353fc6fdb42ec646de49bbb74e4870e37a7e680caf33f3ac0615c30b1146d94" -dependencies = [ - "arrayvec", - "ash", - "byteorder", - "core-graphics-types", - "gfx-hal", - "inplace_it", - "log", - "naga", - "objc", - "parking_lot", - "raw-window-handle", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "gfx-hal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d285bfd566f6b9134af908446ca350c0a1047495dfb9bbd826e701e8ee1d259" -dependencies = [ - "bitflags", - "naga", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "glam" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579160312273c954cc51bd440f059dde741029ac8daf8c84fece76cb77f62c15" -dependencies = [ - "version_check", -] - -[[package]] -name = "gloo-timers" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glow" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b80b98efaa8a34fce11d60dd2ce2760d5d83c373cbcc73bb87c2a3a84a54108" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e3f00b8574a76fb6c50890c48da03946ca50e4372a2778737922666a2238221" -dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "log", - "ordered-float", - "rustc-hash", - "twox-hash", -] - -[[package]] -name = "glyph_brush_draw_cache" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2c82074cafb68b9e459c50c655f7eedcb92d6ee7166813802934bc6fc29fa3" -dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15cf18cf985bd942f05e14552b63c9d08f7d0ed1ec79a977eb9747c9e065f497" -dependencies = [ - "ab_glyph", - "approx", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc1b6ca374e81862526786d9cb42357ce03706ed1b8761730caafd02ab91f3a" -dependencies = [ - "bitflags", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags", -] - -[[package]] -name = "gpu-descriptor" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a70f1e87a3840ed6a3e99e02c2b861e4dbdf26f0d07e38f42ea5aff46cfce2" -dependencies = [ - "bitflags", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags", -] - -[[package]] -name = "guillotiere" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9253eedea82720b2bc91fe831c9ce3a31299955ed5eb19b9ed600a625b686212" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" -dependencies = [ - "ahash", -] - -[[package]] -name = "hermit-abi" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" -dependencies = [ - "libc", -] - -[[package]] -name = "iced" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "iced_core", - "iced_futures", - "iced_web", - "iced_wgpu", - "iced_winit", - "thiserror", -] - -[[package]] -name = "iced_core" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" - -[[package]] -name = "iced_futures" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "async-std", - "futures", - "log", - "tokio", - "wasm-bindgen-futures", -] - -[[package]] -name = "iced_graphics" -version = "0.2.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "bytemuck", - "font-kit", - "glam", - "iced_native", - "iced_style", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "iced_native" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "iced_core", - "iced_futures", - "num-traits", - "twox-hash", - "unicode-segmentation", -] - -[[package]] -name = "iced_style" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "iced_core", -] - -[[package]] -name = "iced_web" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "dodrio", - "iced_core", - "iced_futures", - "iced_style", - "num-traits", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "iced_wgpu" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "bytemuck", - "futures", - "glyph_brush", - "guillotiere", - "iced_graphics", - "iced_native", - "log", - "raw-window-handle", - "wgpu", - "wgpu_glyph", -] - -[[package]] -name = "iced_winit" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=0e70b11e00e4d8517419a5f09490c9502827d35b#0e70b11e00e4d8517419a5f09490c9502827d35b" -dependencies = [ - "iced_futures", - "iced_graphics", - "iced_native", - "log", - "thiserror", - "winapi 0.3.9", - "window_clipboard", - "winit", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inplace_it" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" - -[[package]] -name = "instant" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading 0.7.0", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[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.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" - -[[package]] -name = "libloading" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - -[[package]] -name = "libloading" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "lock_api" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", - "value-bag", -] - -[[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "memchr" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" - -[[package]] -name = "memmap2" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c12e48c737ee9a55e8bb2352bcde588f79ae308d3529ee888f7cc0f469b5777" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "naga" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d74f2c7ace793a760165ac0679d6830809ad4e85f6886f72e4f8c4aa4291c5" -dependencies = [ - "bit-set", - "bitflags", - "codespan-reporting", - "fxhash", - "log", - "num-traits", - "petgraph", - "spirv_headers", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" -dependencies = [ - "jni-sys", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-glue" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk", - "ndk-macro", - "ndk-sys", -] - -[[package]] -name = "ndk-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" - -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "nix" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" -dependencies = [ - "bitflags", - "cc", - "cfg-if 0.1.10", - "libc", -] - -[[package]] -name = "nix" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", -] - -[[package]] -name = "nom" -version = "6.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" -dependencies = [ - "derivative", - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "once_cell" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" - -[[package]] -name = "ordered-float" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f100fcfb41e5385e0991f74981732049f9b896821542a219420491046baafdc2" -dependencies = [ - "num-traits", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" -dependencies = [ - "ttf-parser 0.6.2", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3c7a20e3f122223e68eef6ca58e39bc1ea8a1d83418ba4c2c1ba189d2ee355" -dependencies = [ - "ttf-parser 0.12.1", -] - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "petgraph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" - -[[package]] -name = "polling" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc12d774e799ee9ebae13f4076ca003b40d18a11ac0f3641e6f899618580b7b" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "log", - "wepoll-sys", - "winapi 0.3.9", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - -[[package]] -name = "proc-macro2" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "profiling" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a66d5e88679f2720126c11ee29da07a08f094eac52306b066edd7d393752d6" - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "range-alloc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" - -[[package]] -name = "raw-window-handle" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" -dependencies = [ - "libc", -] - -[[package]] -name = "rayon" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom 0.2.3", - "redox_syscall", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver", -] - -[[package]] -name = "rusttype" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser 0.6.0", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" - -[[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - -[[package]] -name = "signal-hook" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" - -[[package]] -name = "slotmap" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c46a3482db8f247956e464d783693ece164ca056e6e67563ee5505bdb86452cd" - -[[package]] -name = "smallvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" - -[[package]] -name = "smithay-client-toolkit" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" -dependencies = [ - "andrew", - "bitflags", - "calloop", - "dlib 0.4.2", - "lazy_static", - "log", - "memmap2", - "nix 0.18.0", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-clipboard" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06384dfaf645908220d976ae24ed39f6cf92efecb0225ea0a948e403014de527" -dependencies = [ - "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "socket2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "spirv_cross" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60647fadbf83c4a72f0d7ea67a7ca3a81835cf442b8deae5c134c3e0055b2e14" -dependencies = [ - "cc", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "spirv_headers" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f5b132530b1ac069df335577e3581765995cba5a13995cdbbdbc8fb057c532c" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "storage-map" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418bb14643aa55a7841d5303f72cf512cfb323b8cc221d51580500a1ca75206c" -dependencies = [ - "lock_api", -] - -[[package]] -name = "str-buf" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "svg_fmt" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" - -[[package]] -name = "syn" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thunderdome" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b4947742c93ece24a0032141d9caa3d853752e694a57e35029dd2bd08673e0" - -[[package]] -name = "tinyvec" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" -dependencies = [ - "num_cpus", - "once_cell", - "pin-project-lite", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "ttf-parser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" - -[[package]] -name = "ttf-parser" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc71742ead70703a55d184f82087302f2f9ffa3793e64db46a78bf75dd723f4" - -[[package]] -name = "twox-hash" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" -dependencies = [ - "cfg-if 0.1.10", - "rand", - "static_assertions", -] - -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] -name = "unicode-bidi" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" - -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "url" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", -] - -[[package]] -name = "value-bag" -version = "1.0.0-alpha.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd320e1520f94261153e96f7534476ad869c14022aee1e59af7c778075d840ae" -dependencies = [ - "ctor", - "version_check", -] - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" -dependencies = [ - "bumpalo 3.7.0", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" - -[[package]] -name = "wayland-client" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ca44d86554b85cf449f1557edc6cc7da935cc748c8e4bf1c507cbd43bae02c" -dependencies = [ - "bitflags", - "downcast-rs", - "libc", - "nix 0.20.0", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd75ae380325dbcff2707f0cd9869827ea1d2d6d534cff076858d3f0460fd5a" -dependencies = [ - "nix 0.20.0", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37e5455ec72f5de555ec39b5c3704036ac07c2ecd50d0bffe02d5fe2d4e65ab" -dependencies = [ - "nix 0.20.0", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95df3317872bcf9eec096c864b69aa4769a1d5d6291a5b513f8ba0af0efbd52c" -dependencies = [ - "bitflags", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389d680d7bd67512dc9c37f39560224327038deb0f0e8d33f870900441b68720" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2907bd297eef464a95ba9349ea771611771aa285b932526c633dc94d5400a8e2" -dependencies = [ - "dlib 0.5.0", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wepoll-sys" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" -dependencies = [ - "cc", -] - -[[package]] -name = "wgpu" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "215fd50e66f794bd16683e7e0e0b9b53be265eb10fdf02276caf5de3e5743fcf" -dependencies = [ - "arrayvec", - "js-sys", - "log", - "naga", - "parking_lot", - "raw-window-handle", - "smallvec", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56c368fc0e6f3927c711d2b55a51ad4321218efc0239c4acf69e456ab70399" -dependencies = [ - "arrayvec", - "bitflags", - "cfg_aliases", - "copyless", - "fxhash", - "gfx-backend-dx11", - "gfx-backend-dx12", - "gfx-backend-empty", - "gfx-backend-gl", - "gfx-backend-metal", - "gfx-backend-vulkan", - "gfx-hal", - "gpu-alloc", - "gpu-descriptor", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "thiserror", - "wgpu-types", -] - -[[package]] -name = "wgpu-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa248d90c8e6832269b8955bf800e8241f942c25e18a235b7752226804d21556" -dependencies = [ - "bitflags", -] - -[[package]] -name = "wgpu_glyph" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634570b440f4c24c2e6049ed01ec832c23d338dea3eca654d5760838017a1c8b" -dependencies = [ - "bytemuck", - "glyph_brush", - "log", - "wgpu", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[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-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi 0.3.9", -] - -[[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 = "window_clipboard" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a4518b538a45ad39d138a8c3bea8f6b4452174aeb38143d1dd643a3a838ccc" -dependencies = [ - "clipboard-win", - "clipboard_macos", - "clipboard_wayland", - "clipboard_x11", - "raw-window-handle", -] - -[[package]] -name = "winit" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4eda6fce0eb84bd0a33e3c8794eb902e1033d0a1d5a31bc4f19b1b4bbff597" -dependencies = [ - "bitflags", - "cocoa", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "core-video-sys", - "dispatch", - "instant", - "lazy_static", - "libc", - "log", - "mio", - "mio-extras", - "ndk", - "ndk-glue", - "ndk-sys", - "objc", - "parking_lot", - "percent-encoding", - "raw-window-handle", - "smithay-client-toolkit", - "wayland-client", - "winapi 0.3.9", - "x11-dl", -] - -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "x11-dl" -version = "2.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8" -dependencies = [ - "lazy_static", - "libc", - "maybe-uninit", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffb080b3f2f616242a4eb8e7d325035312127901025b0052bc3154a282d0f19" -dependencies = [ - "gethostname", - "nix 0.20.0", - "winapi 0.3.9", - "winapi-wsapoll", -] - -[[package]] -name = "xcursor" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" -dependencies = [ - "nom", -] - -[[package]] -name = "xdg" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" diff --git a/bugs/button_text_update_issue/Cargo.toml b/bugs/button_text_update_issue/Cargo.toml deleted file mode 100644 index 963550347f..0000000000 --- a/bugs/button_text_update_issue/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "button_text_update_issue" -version = "0.0.1" -authors = ["David Jaffe "] -edition = "2018" - -[dependencies] -iced = { git = "https://github.com/hecrj/iced", rev = "0e70b11e00e4d8517419a5f09490c9502827d35b", features = ["tokio", "wgpu", "default_system_font", "default", "async-std"] } -iced_native = { git = "https://github.com/hecrj/iced", rev = "0e70b11e00e4d8517419a5f09490c9502827d35b" } - -[profile.dev] -debug = 1 -opt-level = 3 - -[[bin]] -name = "button_text_update_issue" -path = "src/main.rs" diff --git a/bugs/button_text_update_issue/README b/bugs/button_text_update_issue/README deleted file mode 100644 index dedbe93844..0000000000 --- a/bugs/button_text_update_issue/README +++ /dev/null @@ -1,25 +0,0 @@ -This crate appears to exhibit a bug wherein text is not properly updated in a GUI. -It was manifested on a MacBook Pro (16-inch, 2019) running macOS 10.15.7. Possibly it is -only manifested in connection with trackpad use. - -The bug could be in this code or in a Rust crate that it uses. - -Instructions: -1. cargo b -2. target/debug/button_text_update_issue - - a GUI window will open up -3. move the cursor to over the "Submit" button and tap on the trackpad; do not push to click - - you will see "pushed" printed in the originating terminal window - - you may or may not see the button text change briefly to "thinking" - - the "correct" behavior is to change to "thinking" for three seconds, then revert to "Submit" - - buggy behavior: this only happens some of the time - - repeatedly closing the GUI window and restarting may help exhibit the problem - -This was exhibited on a MacBook Pro (16-inch, 2019) running macOS 10.15.7. - -It appears to be possible to eliminate the buggy behavior by adding the single line - - std::thread::sleep(std::time::Duration::from_millis(10)); - -after the line - self.compute_state = Thinking; diff --git a/bugs/button_text_update_issue/src/main.rs b/bugs/button_text_update_issue/src/main.rs deleted file mode 100644 index a73461fe33..0000000000 --- a/bugs/button_text_update_issue/src/main.rs +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use iced::{ - button, Application, Button, Clipboard, Column, Command, Container, Element, Length, Row, - Settings, Subscription, Text, -}; -use iced_native::{window, Event}; - -fn main() -> iced::Result { - StrangeThing::run(Settings::default()) -} - -#[derive(PartialEq)] -enum ComputeState { - WaitingForRequest, - Thinking, -} - -impl Default for ComputeState { - fn default() -> ComputeState { - WaitingForRequest - } -} - -use ComputeState::*; - -#[derive(Default)] -struct StrangeThing { - button: button::State, - should_exit: bool, - compute_state: ComputeState, -} - -#[derive(Debug, Clone)] -enum Message { - ButtonPressed, - ComputationDone(Result<(), String>), - EventOccurred(iced_native::Event), -} - -impl Application for StrangeThing { - type Executor = iced::executor::Default; - type Message = Message; - type Flags = (); - - fn new(_flags: ()) -> (StrangeThing, Command) { - let mut x = StrangeThing::default(); - x.compute_state = WaitingForRequest; - (x, Command::none()) - } - - fn title(&self) -> String { - String::from("crazy") - } - - fn update(&mut self, message: Message, _clipboard: &mut Clipboard) -> Command { - match message { - Message::ButtonPressed => { - println!("pushed"); - if self.compute_state == WaitingForRequest { - self.compute_state = Thinking; - Command::perform(compute(), Message::ComputationDone) - } else { - Command::none() - } - } - Message::ComputationDone(_) => { - self.compute_state = WaitingForRequest; - Command::none() - } - Message::EventOccurred(ref event) => { - if let Event::Window(window::Event::CloseRequested) = event { - self.should_exit = true; - } - Command::none() - } - } - } - - fn should_exit(&self) -> bool { - self.should_exit - } - - fn subscription(&self) -> Subscription { - iced_native::subscription::events().map(Message::EventOccurred) - } - - fn view(&mut self) -> Element { - let button = Button::new( - &mut self.button, - Text::new(if self.compute_state == WaitingForRequest { - "Submit" - } else { - "thinking" - }), - ) - .on_press(Message::ButtonPressed); - let content = Column::new().push(Row::new().spacing(10).push(button)); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() - } -} - -async fn compute() -> Result<(), String> { - std::thread::sleep(std::time::Duration::from_millis(3000)); - Ok(()) -} diff --git a/bugs/canvas_in_scrollable/Cargo.lock b/bugs/canvas_in_scrollable/Cargo.lock deleted file mode 100644 index a28dcfcc84..0000000000 --- a/bugs/canvas_in_scrollable/Cargo.lock +++ /dev/null @@ -1,3060 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0ac006645f86f20f6c6fa4dcaef920bf803df819123626f9440e35835e7d80" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser 0.12.0", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fe5e32de01730eb1f6b7f5b51c17e03e2325bf40a74f754f04f130043affff" - -[[package]] -name = "ahash" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" - -[[package]] -name = "andrew" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c4afb09dd642feec8408e33f92f3ffc4052946f6b20f32fb99c1f58cd4fa7cf" -dependencies = [ - "bitflags", - "rusttype", - "walkdir", - "xdg", - "xml-rs", -] - -[[package]] -name = "approx" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "072df7202e63b127ab55acfe16ce97013d5b97bf160489336d3f1840fd78e99e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - -[[package]] -name = "ash" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112" -dependencies = [ - "libloading 0.7.0", -] - -[[package]] -name = "async-channel" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "once_cell", - "slab", -] - -[[package]] -name = "async-global-executor" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" -dependencies = [ - "async-channel", - "async-executor", - "async-io", - "async-mutex", - "blocking", - "futures-lite", - "num_cpus", - "once_cell", -] - -[[package]] -name = "async-io" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bbfd5cf2794b1e908ea8457e6c45f8f8f1f6ec5f74617bf4662623f47503c3b" -dependencies = [ - "concurrent-queue", - "fastrand", - "futures-lite", - "libc", - "log", - "once_cell", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "winapi 0.3.9", -] - -[[package]] -name = "async-lock" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6a8ea61bf9947a1007c5cada31e647dbc77b103c679858150003ba697ea798b" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-mutex" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-process" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f38756dd9ac84671c428afbf7c9f7495feff9ec5b0710f17100098e5b354ac" -dependencies = [ - "async-io", - "blocking", - "cfg-if 1.0.0", - "event-listener", - "futures-lite", - "libc", - "once_cell", - "signal-hook", - "winapi 0.3.9", -] - -[[package]] -name = "async-std" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" -dependencies = [ - "async-channel", - "async-global-executor", - "async-io", - "async-lock", - "async-process", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "gloo-timers", - "kv-log-macro", - "log", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" - -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bit-set" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "blocking" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" -dependencies = [ - "async-channel", - "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "once_cell", -] - -[[package]] -name = "bumpalo" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" - -[[package]] -name = "bumpalo" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" - -[[package]] -name = "bytemuck" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9966d2ab714d0f785dbac0a0396251a35280aeb42413281617d0209ab4898435" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e215f8c2f9f79cb53c8335e687ffd07d5bfcb6fe5fc80723762d0be46e7cc54" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cache-padded" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" - -[[package]] -name = "calloop" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b036167e76041694579972c28cf4877b4f92da222560ddb49008937b6a6727c" -dependencies = [ - "log", - "nix 0.18.0", -] - -[[package]] -name = "canvas_in_scrollable" -version = "0.0.1" -dependencies = [ - "iced", - "iced_native", -] - -[[package]] -name = "cc" -version = "1.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "clipboard-win" -version = "4.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4ea1881992efc993e4dc50a324cdbd03216e41bdc8385720ff47efc9bd2ca8" -dependencies = [ - "error-code", - "str-buf", - "winapi 0.3.9", -] - -[[package]] -name = "clipboard_macos" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" -dependencies = [ - "objc", - "objc-foundation", - "objc_id", -] - -[[package]] -name = "clipboard_wayland" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6364a9f7a66f2ac1a1a098aa1c7f6b686f2496c6ac5e5c0d773445df912747" -dependencies = [ - "smithay-clipboard", -] - -[[package]] -name = "clipboard_x11" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64240d63f1883d87e5637bfcaf9d77e5c8bd24e30fd440ea2dff5c48c0bf0b7a" -dependencies = [ - "thiserror", - "x11rb", -] - -[[package]] -name = "cmake" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" -dependencies = [ - "cc", -] - -[[package]] -name = "cocoa" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" -dependencies = [ - "bitflags", - "block", - "core-foundation 0.9.1", - "core-graphics-types", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - -[[package]] -name = "core-foundation" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -dependencies = [ - "core-foundation-sys 0.7.0", - "libc", -] - -[[package]] -name = "core-foundation" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" -dependencies = [ - "core-foundation-sys 0.8.2", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" - -[[package]] -name = "core-foundation-sys" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" - -[[package]] -name = "core-graphics" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" -dependencies = [ - "bitflags", - "core-foundation 0.7.0", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.22.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86" -dependencies = [ - "bitflags", - "core-foundation 0.9.1", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" -dependencies = [ - "bitflags", - "core-foundation 0.9.1", - "foreign-types", - "libc", -] - -[[package]] -name = "core-text" -version = "19.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25" -dependencies = [ - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "foreign-types", - "libc", -] - -[[package]] -name = "core-video-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" -dependencies = [ - "cfg-if 0.1.10", - "core-foundation-sys 0.7.0", - "core-graphics 0.19.2", - "libc", - "objc", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] - -[[package]] -name = "ctor" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" -dependencies = [ - "quote", - "syn", -] - -[[package]] -name = "d3d12" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "091ed1b25fe47c7ff129fc440c23650b6114f36aa00bc7212cc8041879294428" -dependencies = [ - "bitflags", - "libloading 0.7.0", - "winapi 0.3.9", -] - -[[package]] -name = "darling" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi 0.3.9", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11f15d1e3268f140f68d390637d5e76d849782d971ae7063e0da69fe9709a76" -dependencies = [ - "libloading 0.6.7", -] - -[[package]] -name = "dlib" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1b7517328c04c2aa68422fc60a41b92208182142ed04a25879c26c8f878794" -dependencies = [ - "libloading 0.7.0", -] - -[[package]] -name = "dodrio" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7593dfc68e57dc1d058ada0f151ba07f4b05183c4da4c4df8ff651a81ef0fab" -dependencies = [ - "bumpalo 2.6.0", - "cfg-if 0.1.10", - "fxhash", - "js-sys", - "longest-increasing-subsequence", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "dwrote" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" -dependencies = [ - "lazy_static", - "libc", - "winapi 0.3.9", - "wio", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "error-code" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5115567ac25674e0043e472be13d14e537f37ea8aa4bdc4aef0c89add1db1ff" -dependencies = [ - "libc", - "str-buf", -] - -[[package]] -name = "euclid" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80" -dependencies = [ - "num-traits", -] - -[[package]] -name = "event-listener" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" - -[[package]] -name = "expat-sys" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] - -[[package]] -name = "fastrand" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b705829d1e87f762c2df6da140b26af5839e1033aa84aa5f56bb688e4e1bdb" -dependencies = [ - "instant", -] - -[[package]] -name = "fixedbitset" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" - -[[package]] -name = "float-ord" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "font-kit" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c9a156ec38864999bc9c4156e5f3b50224d4a5578028a64e5a3875caa9ee28" -dependencies = [ - "bitflags", - "byteorder", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "core-text", - "dirs-next", - "dwrote", - "float-ord", - "freetype", - "lazy_static", - "libc", - "log", - "pathfinder_geometry", - "pathfinder_simd", - "servo-fontconfig", - "walkdir", - "winapi 0.3.9", -] - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" -dependencies = [ - "matches", - "percent-encoding", -] - -[[package]] -name = "freetype" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" -dependencies = [ - "freetype-sys", - "libc", -] - -[[package]] -name = "freetype-sys" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" -dependencies = [ - "cmake", - "libc", - "pkg-config", -] - -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" - -[[package]] -name = "futures-executor" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-macro" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" -dependencies = [ - "autocfg", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" - -[[package]] -name = "futures-task" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" - -[[package]] -name = "futures-util" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" -dependencies = [ - "autocfg", - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "proc-macro-hack", - "proc-macro-nested", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gethostname" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.10.2+wasi-snapshot-preview1", -] - -[[package]] -name = "gfx-auxil" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccf8711c9994dfa34337466bee3ae1462e172874c432ce4eb120ab2e98d39cf" -dependencies = [ - "fxhash", - "gfx-hal", - "spirv_cross", -] - -[[package]] -name = "gfx-backend-dx11" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f839f27f8c8a6dc553ccca7f5b35a42009432bc25db9688bba7061cd394161f" -dependencies = [ - "arrayvec", - "bitflags", - "gfx-auxil", - "gfx-hal", - "libloading 0.7.0", - "log", - "parking_lot", - "range-alloc", - "raw-window-handle", - "smallvec", - "spirv_cross", - "thunderdome", - "winapi 0.3.9", - "wio", -] - -[[package]] -name = "gfx-backend-dx12" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3937738b0da5839bba4e33980d29f9a06dbce184d04a3a08c9a949e7953700e3" -dependencies = [ - "arrayvec", - "bit-set", - "bitflags", - "d3d12", - "gfx-auxil", - "gfx-hal", - "log", - "parking_lot", - "range-alloc", - "raw-window-handle", - "smallvec", - "spirv_cross", - "thunderdome", - "winapi 0.3.9", -] - -[[package]] -name = "gfx-backend-empty" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac55ada4bfcd35479b3421eea324d36d7da5f724e2f66ecb36d4efdb7041a5e" -dependencies = [ - "gfx-hal", - "log", - "raw-window-handle", -] - -[[package]] -name = "gfx-backend-gl" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0caa03d6e0b7b4f202aea1f20c3f3288cfa06d92d24cea9d69c9a7627967244a" -dependencies = [ - "arrayvec", - "bitflags", - "fxhash", - "gfx-hal", - "glow", - "js-sys", - "khronos-egl", - "libloading 0.7.0", - "log", - "naga", - "parking_lot", - "raw-window-handle", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "gfx-backend-metal" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340895ad544ba46433acb3bdabece0ef16f2dbedc030adbd7c9eaf2839fbed41" -dependencies = [ - "arrayvec", - "bitflags", - "block", - "cocoa-foundation", - "copyless", - "foreign-types", - "fxhash", - "gfx-hal", - "log", - "metal", - "naga", - "objc", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "storage-map", -] - -[[package]] -name = "gfx-backend-vulkan" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a353fc6fdb42ec646de49bbb74e4870e37a7e680caf33f3ac0615c30b1146d94" -dependencies = [ - "arrayvec", - "ash", - "byteorder", - "core-graphics-types", - "gfx-hal", - "inplace_it", - "log", - "naga", - "objc", - "parking_lot", - "raw-window-handle", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "gfx-hal" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d285bfd566f6b9134af908446ca350c0a1047495dfb9bbd826e701e8ee1d259" -dependencies = [ - "bitflags", - "naga", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "glam" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579160312273c954cc51bd440f059dde741029ac8daf8c84fece76cb77f62c15" -dependencies = [ - "version_check", -] - -[[package]] -name = "gloo-timers" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glow" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b80b98efaa8a34fce11d60dd2ce2760d5d83c373cbcc73bb87c2a3a84a54108" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e3f00b8574a76fb6c50890c48da03946ca50e4372a2778737922666a2238221" -dependencies = [ - "glyph_brush_draw_cache", - "glyph_brush_layout", - "log", - "ordered-float", - "rustc-hash", - "twox-hash", -] - -[[package]] -name = "glyph_brush_draw_cache" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2c82074cafb68b9e459c50c655f7eedcb92d6ee7166813802934bc6fc29fa3" -dependencies = [ - "ab_glyph", - "crossbeam-channel", - "crossbeam-deque", - "linked-hash-map", - "rayon", - "rustc-hash", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15cf18cf985bd942f05e14552b63c9d08f7d0ed1ec79a977eb9747c9e065f497" -dependencies = [ - "ab_glyph", - "approx", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc1b6ca374e81862526786d9cb42357ce03706ed1b8761730caafd02ab91f3a" -dependencies = [ - "bitflags", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags", -] - -[[package]] -name = "gpu-descriptor" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a70f1e87a3840ed6a3e99e02c2b861e4dbdf26f0d07e38f42ea5aff46cfce2" -dependencies = [ - "bitflags", - "gpu-descriptor-types", - "hashbrown", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" -dependencies = [ - "bitflags", -] - -[[package]] -name = "guillotiere" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9253eedea82720b2bc91fe831c9ce3a31299955ed5eb19b9ed600a625b686212" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" -dependencies = [ - "ahash", -] - -[[package]] -name = "hermit-abi" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" -dependencies = [ - "libc", -] - -[[package]] -name = "iced" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "iced_core", - "iced_futures", - "iced_web", - "iced_wgpu", - "iced_winit", - "thiserror", -] - -[[package]] -name = "iced_core" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" - -[[package]] -name = "iced_futures" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "async-std", - "futures", - "log", - "tokio", - "wasm-bindgen-futures", -] - -[[package]] -name = "iced_graphics" -version = "0.2.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "bytemuck", - "font-kit", - "glam", - "iced_native", - "iced_style", - "lyon", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "iced_native" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "iced_core", - "iced_futures", - "num-traits", - "twox-hash", - "unicode-segmentation", -] - -[[package]] -name = "iced_style" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "iced_core", -] - -[[package]] -name = "iced_web" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "dodrio", - "iced_core", - "iced_futures", - "iced_style", - "num-traits", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "iced_wgpu" -version = "0.4.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "bytemuck", - "futures", - "glyph_brush", - "guillotiere", - "iced_graphics", - "iced_native", - "log", - "raw-window-handle", - "wgpu", - "wgpu_glyph", -] - -[[package]] -name = "iced_winit" -version = "0.3.0" -source = "git+https://github.com/hecrj/iced?rev=e68da229b384fbe78514dab0b13c8eb4637f4f5d#e68da229b384fbe78514dab0b13c8eb4637f4f5d" -dependencies = [ - "iced_futures", - "iced_graphics", - "iced_native", - "log", - "thiserror", - "winapi 0.3.9", - "window_clipboard", - "winit", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inplace_it" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" - -[[package]] -name = "instant" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading 0.7.0", -] - -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[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.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" - -[[package]] -name = "libloading" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - -[[package]] -name = "libloading" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" -dependencies = [ - "cfg-if 1.0.0", - "winapi 0.3.9", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" - -[[package]] -name = "lock_api" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", - "value-bag", -] - -[[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" - -[[package]] -name = "lyon" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d083e12e9e22298eec27751ec4a0975abac5873a3b0dcdbbecc608d333f0e9" -dependencies = [ - "lyon_algorithms", - "lyon_tessellation", -] - -[[package]] -name = "lyon_algorithms" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11033936a5e9d7bf35b7ba71a19f8b6bc838f3206304175dc5b3524ca16672a8" -dependencies = [ - "lyon_path", - "sid", -] - -[[package]] -name = "lyon_geom" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce4e12203c428a58200b8cf1c0a3aad1cda907008ea11310bb3729593e5f933" -dependencies = [ - "arrayvec", - "euclid", - "num-traits", -] - -[[package]] -name = "lyon_path" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243c71fff16677ecde2d38794a0253a8f0417cebaacc6390677c30733831d8cb" -dependencies = [ - "lyon_geom", -] - -[[package]] -name = "lyon_tessellation" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ecf3d769bec66396957d7c5cb91f998c4182e53fdc96cc435b6ebcd46a63cd9" -dependencies = [ - "arrayvec", - "lyon_path", - "sid", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - -[[package]] -name = "memchr" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" - -[[package]] -name = "memmap2" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c12e48c737ee9a55e8bb2352bcde588f79ae308d3529ee888f7cc0f469b5777" -dependencies = [ - "bitflags", - "block", - "cocoa-foundation", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "naga" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d74f2c7ace793a760165ac0679d6830809ad4e85f6886f72e4f8c4aa4291c5" -dependencies = [ - "bit-set", - "bitflags", - "codespan-reporting", - "fxhash", - "log", - "num-traits", - "petgraph", - "spirv_headers", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb167c1febed0a496639034d0c76b3b74263636045db5489eee52143c246e73" -dependencies = [ - "jni-sys", - "ndk-sys", - "num_enum", - "thiserror", -] - -[[package]] -name = "ndk-glue" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf399b8b7a39c6fb153c4ec32c72fd5fe789df24a647f229c239aa7adb15241" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk", - "ndk-macro", - "ndk-sys", -] - -[[package]] -name = "ndk-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d1c6307dc424d0f65b9b06e94f88248e6305726b14729fd67a5e47b2dc481d" -dependencies = [ - "darling", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "ndk-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44922cb3dbb1c70b5e5f443d63b64363a898564d739ba5198e3a9138442868d" - -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "nix" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83450fe6a6142ddd95fb064b746083fc4ef1705fe81f64a64e1d4b39f54a1055" -dependencies = [ - "bitflags", - "cc", - "cfg-if 0.1.10", - "libc", -] - -[[package]] -name = "nix" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" -dependencies = [ - "bitflags", - "cc", - "cfg-if 1.0.0", - "libc", -] - -[[package]] -name = "nom" -version = "6.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2" -dependencies = [ - "memchr", - "version_check", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" -dependencies = [ - "derivative", - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "once_cell" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" - -[[package]] -name = "ordered-float" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f100fcfb41e5385e0991f74981732049f9b896821542a219420491046baafdc2" -dependencies = [ - "num-traits", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3" -dependencies = [ - "ttf-parser 0.6.2", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3c7a20e3f122223e68eef6ca58e39bc1ea8a1d83418ba4c2c1ba189d2ee355" -dependencies = [ - "ttf-parser 0.12.2", -] - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi 0.3.9", -] - -[[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39fe46acc5503595e5949c17b818714d26fdf9b4920eacf3b2947f0199f4a6ff" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "percent-encoding" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" - -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "petgraph" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" - -[[package]] -name = "polling" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "log", - "wepoll-ffi", - "winapi 0.3.9", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - -[[package]] -name = "proc-macro2" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "profiling" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7c000c0ce9d9bb94c0fbacdf20e5087fbe652c556ffb2c9387d980e17d51fb" - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "range-alloc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" - -[[package]] -name = "raw-window-handle" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211" -dependencies = [ - "libc", -] - -[[package]] -name = "rayon" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "lazy_static", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom 0.2.3", - "redox_syscall", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver", -] - -[[package]] -name = "rusttype" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser 0.6.0", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - -[[package]] -name = "serde" -version = "1.0.126" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" - -[[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - -[[package]] -name = "sid" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb" -dependencies = [ - "num-traits", -] - -[[package]] -name = "signal-hook" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" - -[[package]] -name = "slotmap" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c46a3482db8f247956e464d783693ece164ca056e6e67563ee5505bdb86452cd" - -[[package]] -name = "smallvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" - -[[package]] -name = "smithay-client-toolkit" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4750c76fd5d3ac95fa3ed80fe667d6a3d8590a960e5b575b98eea93339a80b80" -dependencies = [ - "andrew", - "bitflags", - "calloop", - "dlib 0.4.2", - "lazy_static", - "log", - "memmap2", - "nix 0.18.0", - "wayland-client", - "wayland-cursor", - "wayland-protocols", -] - -[[package]] -name = "smithay-clipboard" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06384dfaf645908220d976ae24ed39f6cf92efecb0225ea0a948e403014de527" -dependencies = [ - "smithay-client-toolkit", - "wayland-client", -] - -[[package]] -name = "socket2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "spirv_cross" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60647fadbf83c4a72f0d7ea67a7ca3a81835cf442b8deae5c134c3e0055b2e14" -dependencies = [ - "cc", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "spirv_headers" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f5b132530b1ac069df335577e3581765995cba5a13995cdbbdbc8fb057c532c" -dependencies = [ - "bitflags", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "storage-map" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418bb14643aa55a7841d5303f72cf512cfb323b8cc221d51580500a1ca75206c" -dependencies = [ - "lock_api", -] - -[[package]] -name = "str-buf" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a" - -[[package]] -name = "strsim" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" - -[[package]] -name = "svg_fmt" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" - -[[package]] -name = "syn" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thunderdome" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b4947742c93ece24a0032141d9caa3d853752e694a57e35029dd2bd08673e0" - -[[package]] -name = "tinyvec" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "tokio" -version = "1.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" -dependencies = [ - "num_cpus", - "once_cell", - "pin-project-lite", -] - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "ttf-parser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" - -[[package]] -name = "ttf-parser" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c56097738aec26a3f347edf99f5c84d9d4e3a4b8ce5513ebca85cb621fc7c50" - -[[package]] -name = "twox-hash" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" -dependencies = [ - "cfg-if 0.1.10", - "rand", - "static_assertions", -] - -[[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] -name = "unicode-bidi" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" - -[[package]] -name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "url" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" -dependencies = [ - "form_urlencoded", - "idna", - "matches", - "percent-encoding", -] - -[[package]] -name = "value-bag" -version = "1.0.0-alpha.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd320e1520f94261153e96f7534476ad869c14022aee1e59af7c778075d840ae" -dependencies = [ - "ctor", - "version_check", -] - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi 0.3.9", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "wasm-bindgen" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" -dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" -dependencies = [ - "bumpalo 3.7.0", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fba7978c679d53ce2d0ac80c8c175840feb849a161664365d1287b41f2e67f1" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" - -[[package]] -name = "wayland-client" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ca44d86554b85cf449f1557edc6cc7da935cc748c8e4bf1c507cbd43bae02c" -dependencies = [ - "bitflags", - "downcast-rs", - "libc", - "nix 0.20.0", - "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys", -] - -[[package]] -name = "wayland-commons" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd75ae380325dbcff2707f0cd9869827ea1d2d6d534cff076858d3f0460fd5a" -dependencies = [ - "nix 0.20.0", - "once_cell", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-cursor" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b37e5455ec72f5de555ec39b5c3704036ac07c2ecd50d0bffe02d5fe2d4e65ab" -dependencies = [ - "nix 0.20.0", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95df3317872bcf9eec096c864b69aa4769a1d5d6291a5b513f8ba0af0efbd52c" -dependencies = [ - "bitflags", - "wayland-client", - "wayland-commons", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389d680d7bd67512dc9c37f39560224327038deb0f0e8d33f870900441b68720" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-sys" -version = "0.28.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2907bd297eef464a95ba9349ea771611771aa285b932526c633dc94d5400a8e2" -dependencies = [ - "dlib 0.5.0", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - -[[package]] -name = "wgpu" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "215fd50e66f794bd16683e7e0e0b9b53be265eb10fdf02276caf5de3e5743fcf" -dependencies = [ - "arrayvec", - "js-sys", - "log", - "naga", - "parking_lot", - "raw-window-handle", - "smallvec", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56c368fc0e6f3927c711d2b55a51ad4321218efc0239c4acf69e456ab70399" -dependencies = [ - "arrayvec", - "bitflags", - "cfg_aliases", - "copyless", - "fxhash", - "gfx-backend-dx11", - "gfx-backend-dx12", - "gfx-backend-empty", - "gfx-backend-gl", - "gfx-backend-metal", - "gfx-backend-vulkan", - "gfx-hal", - "gpu-alloc", - "gpu-descriptor", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "thiserror", - "wgpu-types", -] - -[[package]] -name = "wgpu-types" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa248d90c8e6832269b8955bf800e8241f942c25e18a235b7752226804d21556" -dependencies = [ - "bitflags", -] - -[[package]] -name = "wgpu_glyph" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634570b440f4c24c2e6049ed01ec832c23d338dea3eca654d5760838017a1c8b" -dependencies = [ - "bytemuck", - "glyph_brush", - "log", - "wgpu", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[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-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi 0.3.9", -] - -[[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 = "window_clipboard" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a4518b538a45ad39d138a8c3bea8f6b4452174aeb38143d1dd643a3a838ccc" -dependencies = [ - "clipboard-win", - "clipboard_macos", - "clipboard_wayland", - "clipboard_x11", - "raw-window-handle", -] - -[[package]] -name = "winit" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4eda6fce0eb84bd0a33e3c8794eb902e1033d0a1d5a31bc4f19b1b4bbff597" -dependencies = [ - "bitflags", - "cocoa", - "core-foundation 0.9.1", - "core-graphics 0.22.2", - "core-video-sys", - "dispatch", - "instant", - "lazy_static", - "libc", - "log", - "mio", - "mio-extras", - "ndk", - "ndk-glue", - "ndk-sys", - "objc", - "parking_lot", - "percent-encoding", - "raw-window-handle", - "smithay-client-toolkit", - "wayland-client", - "winapi 0.3.9", - "x11-dl", -] - -[[package]] -name = "wio" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] -name = "x11-dl" -version = "2.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8" -dependencies = [ - "lazy_static", - "libc", - "maybe-uninit", - "pkg-config", -] - -[[package]] -name = "x11rb" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffb080b3f2f616242a4eb8e7d325035312127901025b0052bc3154a282d0f19" -dependencies = [ - "gethostname", - "nix 0.20.0", - "winapi 0.3.9", - "winapi-wsapoll", -] - -[[package]] -name = "xcursor" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9a231574ae78801646617cefd13bfe94be907c0e4fa979cfd8b770aa3c5d08" -dependencies = [ - "nom", -] - -[[package]] -name = "xdg" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" diff --git a/bugs/canvas_in_scrollable/Cargo.toml b/bugs/canvas_in_scrollable/Cargo.toml deleted file mode 100644 index 77d7e84e00..0000000000 --- a/bugs/canvas_in_scrollable/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "canvas_in_scrollable" -version = "0.0.1" -authors = ["David Jaffe "] -edition = "2018" - -[dependencies] -iced = { git = "https://github.com/hecrj/iced", rev = "e68da229b384fbe78514dab0b13c8eb4637f4f5d", features = ["canvas", "tokio", "wgpu", "default_system_font", "default", "async-std"] } -iced_native = { git = "https://github.com/hecrj/iced", rev = "e68da229b384fbe78514dab0b13c8eb4637f4f5d" } - -[profile.dev] -debug = 1 -opt-level = 3 - -[[bin]] -name = "canvas_in_scrollable" -path = "src/main.rs" diff --git a/bugs/canvas_in_scrollable/src/main.rs b/bugs/canvas_in_scrollable/src/main.rs deleted file mode 100644 index 35b71629f9..0000000000 --- a/bugs/canvas_in_scrollable/src/main.rs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use iced::canvas::{self, Canvas, Cursor, Frame, Geometry, Path}; -use iced::{ - scrollable, Color, Column, Container, Element, Length, Rectangle, Sandbox, Scrollable, Settings, -}; - -pub fn main() -> iced::Result { - Circles::run(Settings::default()) -} - -#[derive(Default)] -struct Circles { - engine: Engine, - scroll: scrollable::State, -} - -#[derive(Debug, Clone, Copy)] -enum Message { - Something, -} - -impl Sandbox for Circles { - type Message = Message; - - fn new() -> Self { - Circles::default() - } - - fn title(&self) -> String { - String::from("Circles") - } - - fn update(&mut self, _message: Message) {} - - fn view(&mut self) -> Element { - let engine = self.engine.view().map(move |_message| Message::Something); - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(12) - .scroller_width(12) - .push(engine); - let content = Column::new().push(scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -#[derive(Default)] -pub struct Engine {} - -pub enum EngineMessage {} - -impl Engine { - pub fn view<'a>(&'a mut self) -> Element<'a, EngineMessage> { - Canvas::new(self) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -impl<'a> canvas::Program for Engine { - fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec { - let mut frame = Frame::new(bounds.size()); - let circle = Path::circle(frame.center(), 20.0); - frame.fill(&circle, Color::BLACK); - vec![frame.into_geometry()] - } -} diff --git a/crates.dot b/crates.dot index a5c43184c1..9b7bd279a5 100644 --- a/crates.dot +++ b/crates.dot @@ -4,22 +4,16 @@ digraph { 2 [ label = "enclone_main" shape = box] 3 [ label = "enclone_help" shape = box] 4 [ label = "enclone_tail" shape = box] - 5 [ label = "enclone_visual" shape = box] 6 [ label = "enclone_version" shape = box] 7 [ label = "enclone_tools" shape = box] 8 [ label = "enclone_paper" shape = box] 41 [ label = "enclone" ] 45 [ label = "enclone_stuff" ] 1 -> 2 [ ] - 1 -> 5 [ style = dotted] 2 -> 41 [ ] 2 -> 3 [ ] 2 -> 45 [ ] 2 -> 4 [ ] - 5 -> 2 [ ] - 5 -> 45 [ ] - 5 -> 4 [ ] - 5 -> 6 [ ] 7 -> 41 [ ] 7 -> 0 [ ] 8 -> 4 [ ] diff --git a/datasets_medium_checksum b/datasets_medium_checksum index 437f3a54df..f886f37f9e 100644 --- a/datasets_medium_checksum +++ b/datasets_medium_checksum @@ -1 +1 @@ -0b8ea7e4e87009078ca950a5d1d73b985347ea44 +4f646563659e4fbd1a9511655fc93b37019849ac diff --git a/enclone_denovo/src/bin/test_const_ighd.rs b/enclone_denovo/src/bin/test_const_ighd.rs index fed5b2e2b1..fcb342a37e 100644 --- a/enclone_denovo/src/bin/test_const_ighd.rs +++ b/enclone_denovo/src/bin/test_const_ighd.rs @@ -85,6 +85,6 @@ fn main() { println!("used {:.2} minutes\n", elapsed(&t) / 60.0); if fail { println!("\nFAILED!\n"); - std::process::exit(1); + panic!("failed"); } } diff --git a/enclone_exec/Cargo.toml b/enclone_exec/Cargo.toml index f5655b423e..12f61afbb7 100644 --- a/enclone_exec/Cargo.toml +++ b/enclone_exec/Cargo.toml @@ -28,7 +28,6 @@ chrono = { version = "0.4", default-features = false, features = ["std", "clock" enclone_core = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } enclone_main = { path = "../enclone_main" } enclone_testlist = { path = "../enclone_testlist" } -enclone_visual = { path = "../enclone_visual", optional=true } flate2 = "1" home = "0.5" io_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } @@ -59,7 +58,7 @@ stats_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = yaml-rust = "0.4" [features] -default = ["enclone_visual"] +default = [] basic = [] cpu = [] linkless = [] diff --git a/enclone_exec/src/bin/enclone.rs b/enclone_exec/src/bin/enclone.rs index 5a4a8e36c7..9d80d5f44c 100644 --- a/enclone_exec/src/bin/enclone.rs +++ b/enclone_exec/src/bin/enclone.rs @@ -8,16 +8,6 @@ use chrono::prelude::*; use enclone_core::combine_group_pics::combine_group_pics; use enclone_main::main_enclone::main_enclone; use enclone_main::USING_PAGER; -#[cfg(feature = "enclone_visual")] -use enclone_visual::enclone_client::enclone_client; -#[cfg(feature = "enclone_visual")] -use enclone_visual::enclone_server::enclone_server; -#[cfg(feature = "enclone_visual")] -use enclone_visual::gui_structures::Summary; -#[cfg(feature = "enclone_visual")] -use enclone_visual::history::write_enclone_visual_history; -#[cfg(feature = "enclone_visual")] -use enclone_visual::history::EncloneVisualHistory; use flate2::write::GzEncoder; use flate2::Compression; use io_utils::*; @@ -102,17 +92,6 @@ async fn main() -> Result<(), Box> { std::process::exit(0); } - // Client run of enclone. - #[cfg(feature = "enclone_visual")] - { - let t = std::time::Instant::now(); - for i in 0..args.len() { - if args[i] == "VIS" || args[i].starts_with("VIS=") { - enclone_client(&t).await?; - } - } - } - // Standard run of enclone. if args.len() < 2 || args[1] != "SERVER" { @@ -148,192 +127,10 @@ async fn main() -> Result<(), Box> { } } - // Process VIS_DUMP. - - #[cfg(feature = "enclone_visual")] - { - let res = res.unwrap(); - let ctl = &res.inter.setup.ctl; - if ctl.gen_opt.vis_dump { - let mut evh = EncloneVisualHistory::default(); - let mut svg = enclone_visual::blank_svg(); - if !res.outs.svgs.is_empty() { - svg = res.outs.svgs.last().unwrap().clone(); - } - evh.svg_hist_uniq.push(svg.clone()); - evh.svg_history.push(0); - let dataset_names = &res.outs.dataset_names; - let metrics0 = &res.outs.metrics; - let mut metrics = Vec::>::new(); - let n = metrics0.len(); - for i in 0..n { - let m = &metrics0[i]; - let mut lines = Vec::::new(); - for line in m.lines() { - lines.push(line.to_string()); - } - metrics.push(lines); - } - let mut all_metric_names = Vec::::new(); - for i in 0..metrics.len() { - for j in 0..metrics[i].len() { - let s = parse_csv(&metrics[i][j]); - let m = format!("{},{}", s[0], s[1]); - all_metric_names.push(m); - } - } - unique_sort(&mut all_metric_names); - let nm = all_metric_names.len(); - let s = Summary { - summary: res.outs.summary.clone(), - dataset_names: dataset_names.to_vec(), - metrics: metrics, - metric_selected: vec![false; nm], - metrics_condensed: false, - }; - let summary = s.pack(); - evh.summary_hist_uniq.push(summary); - evh.summary_history.push(0); - let mut args2 = Vec::::new(); - for i in 0..args.len() { - if args[i] == "VIS_DUMP" { - continue; - } - if args[i].starts_with("SESSION_NAME=") { - continue; - } - if args[i].starts_with("SESSION_NARRATIVE=") { - continue; - } - if args[i].starts_with("STATE_NARRATIVE=") { - continue; - } - args2.push(args[i].clone()); - } - let command = format!("{}", args2.iter().format(" ")); - evh.input1_hist_uniq.push(command.clone()); - evh.input1_history.push(0); - evh.input2_hist_uniq.push(String::new()); - evh.input2_history.push(0); - evh.inputn_hist_uniq.push(vec![String::new(); 8]); - evh.inputn_history.push(0); - evh.translated_input_hist_uniq.push(command.clone()); - evh.translated_input_history.push(0); - evh.history_index = 1; - evh.is_blank.push(svg.is_empty()); - let mut table = res.outs.pics.clone(); - let widths = res.outs.last_widths.clone(); - const MAX_TABLE: usize = 50; - if table.len() > MAX_TABLE { - table.truncate(MAX_TABLE); - } - let mut reply_text = combine_group_pics( - &table, - &widths, - res.outs.parseable_stdouth, - res.outs.noprint, - res.outs.noprintx, - res.outs.html, - res.outs.ngroup, - res.outs.pretty, - ); - if reply_text.contains("enclone failed") { - reply_text = format!("enclone failed{}", reply_text.after("enclone failed")); - } - if reply_text.len() == 0 { - if command.contains(" NOPRINT") { - reply_text = "You used the NOPRINT option, so there are no \ - clonotypes to see." - .to_string(); - } else { - reply_text = "There are no clonotypes. Please have a look at the summary." - .to_string(); - } - } - let mut reply_text_clean = String::new(); - let mut chars = Vec::::new(); - for c in reply_text.chars() { - chars.push(c); - } - let mut escaped = false; - for l in 0..chars.len() { - if chars[l] == '' { - escaped = true; - } - if escaped { - if chars[l] == 'm' { - escaped = false; - } - continue; - } - reply_text_clean.push(chars[l]); - } - reply_text = reply_text_clean; - reply_text += "\n \n \n"; // papering over truncation bug in display - evh.displayed_tables_hist_uniq.push(reply_text); - evh.displayed_tables_history.push(0); - evh.last_widths_hist_uniq.push(widths); - evh.last_widths_history.push(0); - let full_table = res.outs.pics.clone(); - let serialized = serde_json::to_string(&full_table) - .unwrap() - .as_bytes() - .to_vec(); - let mut e = GzEncoder::new(Vec::new(), Compression::default()); - let _ = e.write_all(&serialized); - let gzipped = e.finish().unwrap(); - evh.table_comp_hist_uniq.push(gzipped); - evh.table_comp_history.push(0); - evh.name_value = ctl.gen_opt.session_name.clone(); - evh.orig_name_value = ctl.gen_opt.session_name.clone(); - evh.narrative_hist_uniq - .push(ctl.gen_opt.state_narrative.clone()); - evh.narrative_history.push(0); - evh.descrip_hist_uniq.push(String::new()); - evh.descrip_history.push(0); - evh.narrative = ctl.gen_opt.session_narrative.clone(); - let mut now = format!("{:?}", Local::now()); - now = now.replace("T", "___"); - now = now.before(".").to_string(); - now = now.replace(":", "-"); - let home = home::home_dir(); - if home.is_none() { - eprintln!( - "Unable to determine home directory. This is unexpected and \ - pathological.\nPlease report this problem!\n" - ); - std::process::exit(1); - } - let enclone = format!("{}/enclone", home.unwrap().display()); - let history = format!("{}/visual/history", enclone); - if !path_exists(&history) { - let res = std::fs::create_dir_all(&history); - if res.is_err() { - eprintln!( - "Unable to create the directory ~/enclone/visual/history. \ - This is odd and unexpected.\nPlease report this problem!\n" - ); - std::process::exit(1); - } - } - let filename = format!("{}/{}", history, now); - let res = write_enclone_visual_history(&evh, &filename); - if res.is_err() { - eprintln!("\nWas unable to write history to the file {}.\n", filename); - std::process::exit(1); - } - } - } - // Done. std::process::exit(0); } - // Server run of enclone. - #[cfg(feature = "enclone_visual")] - { - enclone_server().await?; - } Ok(()) } diff --git a/enclone_exec/tests/enclone_test1.rs b/enclone_exec/tests/enclone_test1.rs index 1007dc8d0b..b91d2a6400 100644 --- a/enclone_exec/tests/enclone_test1.rs +++ b/enclone_exec/tests/enclone_test1.rs @@ -84,37 +84,36 @@ fn test_for_parseable_redundancy() { "\neparseable redundancy test: failed to execute, stderr =\n{}", strme(&new.stderr), ); - std::process::exit(1); + panic!("failed"); } let f = open_for_read!["testx/outputs/redundancy_out"]; let mut found = false; - for line in f.lines() { - let s = line.unwrap(); - let mut fields = s.split(',').collect::>(); - fields.sort(); - assert!(fields.len() > 0); - let mut i = 0; - while i < fields.len() { - let j = next_diff(&fields, i); - if j - i > 1 { - eprintln!( - "\nParseable output field {} appears more than once.\n", - fields[i] - ); - std::process::exit(1); - } - i = j; - } - for i in 0..fields.len() { - if fields[i] == "IG%" { - found = true; - } + + let s = f.lines().next().unwrap().unwrap(); + let mut fields = s.split(',').collect::>(); + fields.sort(); + assert!(fields.len() > 0); + let mut i = 0; + while i < fields.len() { + let j = next_diff(&fields, i); + if j - i > 1 { + eprintln!( + "\nParseable output field {} appears more than once.\n", + fields[i] + ); + panic!("failed"); } - if !found { - eprintln!("\nParseable output abbreviated field IG% not found.\n"); + i = j; + } + for i in 0..fields.len() { + if fields[i] == "IG%" { + found = true; } - break; } + if !found { + eprintln!("\nParseable output abbreviated field IG% not found.\n"); + } + let _ = remove_file("testx/outputs/redundancy_out"); } @@ -150,7 +149,7 @@ fn test_help_pages_edited() { "\nThe page {} has not been edited. Please run ./build.\n", f ); - std::process::exit(1); + panic!("failed"); } } let h = open_for_read![&format!("{}", f)]; @@ -163,7 +162,7 @@ fn test_help_pages_edited() { } } if fail { - std::process::exit(1); + panic!("failed"); } } @@ -218,7 +217,7 @@ fn test_sync_master() { if t != s { eprintln!("\nFound change in {}.\nold: {}\nnew: {}", toml, s, t); eprintln!("You probably need to run sync_to_master\n"); - std::process::exit(1); + panic!("failed"); } } } @@ -254,7 +253,7 @@ fn test_curl_command() { You need to create the directory enclone_exec/testx/outputs.\n\ If you run \"./build\" this will be done for you.\n" ); - std::process::exit(1); + panic!("failed"); } for pass in 1..=3 { for f in ["enclone", "bin", ".profile", ".subversion"].iter() { @@ -288,7 +287,7 @@ fn test_curl_command() { ); eprint!("stdout:\n{}", strme(&o.stdout)); eprint!("stderr:\n{}", strme(&o.stderr)); - std::process::exit(1); + panic!("failed"); } // The following test is there because a bash script can fail without setting // a nonzero exit code. @@ -300,7 +299,7 @@ fn test_curl_command() { pass, strme(&o.stderr) ); - std::process::exit(1); + panic!("failed"); } let req = [ "bin/enclone", @@ -319,7 +318,7 @@ fn test_curl_command() { eprintln!("results of install command:"); eprint!("stdout:\n{}", strme(&o.stdout)); eprint!("stderr:\n{}", strme(&o.stderr)); - std::process::exit(1); + panic!("failed"); } // Make sure that the version looks OK. It was broken at one point. @@ -328,25 +327,23 @@ fn test_curl_command() { let p = format!("testx/outputs/{}", f); let mut ok = false; let f = open_for_read![&p]; - for line in f.lines() { - let s = line.unwrap(); - println!("see version {}", s); - if s.starts_with('v') { - if s.contains('.') { - if s.between("v", ".").parse::().is_ok() { - ok = true; - } + let s = f.lines().next().unwrap().unwrap(); + println!("see version {}", s); + if s.starts_with('v') { + if s.contains('.') { + if s.between("v", ".").parse::().is_ok() { + ok = true; } } - break; } + if !ok { eprintln!( "\nDownload yielded defective version file. The version \ is gotten by parsing an\nhttp response and this problem could arise \ from changes to formatting of the response.\n" ); - std::process::exit(1); + panic!("failed"); } } @@ -371,7 +368,7 @@ fn test_curl_command() { } eprintln!(""); } - std::process::exit(1); + panic!("failed"); } } } @@ -381,7 +378,7 @@ fn test_curl_command() { install.sh created .subversion.\n", version ); - std::process::exit(1); + panic!("failed"); } for f in ["enclone", "bin", ".profile", ".subversion"].iter() { let g = format!("testx/outputs/{}", f); @@ -425,7 +422,7 @@ fn test_datasets_sha256() { "\nsha_command1 = {}\nfailed for datasets_medium_checksum\n", sha_command1 ); - std::process::exit(1); + panic!("failed"); } let sha1 = sha1.stdout; let sha2 = Command::new("sh") @@ -441,7 +438,7 @@ fn test_datasets_sha256() { strme(&sha2), strme(&sha1), ); - std::process::exit(1); + panic!("failed"); } let sha_command1 = format!( "git -C ../enclone-data write-tree --prefix=big_inputs/version{}/123085", @@ -467,7 +464,7 @@ fn test_datasets_sha256() { strme(&sha2), strme(&sha1), ); - std::process::exit(1); + panic!("failed"); } } @@ -568,7 +565,7 @@ fn test_cpu() { ); if dev.abs() > percent_dev { eprintln!("cpu deviation exceeded max of {}%\n", percent_dev); - std::process::exit(1); + panic!("failed"); } // Speed test 2. @@ -608,7 +605,7 @@ fn test_cpu() { ); if dev.abs() > percent_dev { eprintln!("cpu deviation exceeded max of {}%\n", percent_dev); - std::process::exit(1); + panic!("failed"); } } @@ -690,7 +687,7 @@ fn test_licenses() { You can also avoid this test entirely by running instead \ \"cd enclone; cargo test basic -- --nocapture\".\n" ); - std::process::exit(1); + panic!("failed"); } let lic = &new.unwrap().stdout; let mut f = &lic[..]; @@ -785,7 +782,7 @@ fn test_licenses() { at a low rate.\n", msg ); - std::process::exit(1); + panic!("failed"); } } @@ -823,7 +820,7 @@ fn test_formatting() { .unwrap_or_else(|_| panic!("{}", "failed to execute rustfmt")); if new.status.code() != Some(0) { eprintln!("\nrustfmt of {} failed", path); - std::process::exit(1); + panic!("failed"); } }); } diff --git a/enclone_exec/tests/enclone_test2.rs b/enclone_exec/tests/enclone_test2.rs index d9a61c2e49..75abba95b0 100644 --- a/enclone_exec/tests/enclone_test2.rs +++ b/enclone_exec/tests/enclone_test2.rs @@ -9,10 +9,10 @@ use ansi_escape::*; use anyhow::Error; -use enclone_core::main_testlist::*; use enclone_core::*; use enclone_proto::proto_io::{read_proto, ClonotypeIter}; use enclone_proto::types::EncloneOutputs; +use enclone_testlist::main_testlist::*; use enclone_testlist::*; use enclone_tools::html::*; use enclone_tools::run_test::*; @@ -75,7 +75,7 @@ fn test_enclone() { for i in 0..TESTS.len() { results.push((i, false, String::new())); } - let this = include_str!("main_testlist.rs"); + let this = include_str!("../../enclone_testlist/src/main_testlist.rs"); let mut tracking = false; let mut comments = Vec::::new(); let mut lines = Vec::::new(); @@ -114,7 +114,7 @@ fn test_enclone() { "\nOn main tests, NFORCE is not allowed, because it can cause \ failure in the GitHub Actions tests.\n" ); - std::process::exit(1); + panic!("failed"); } let mut out = String::new(); run_test( @@ -132,7 +132,7 @@ fn test_enclone() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -208,7 +208,7 @@ fn test_accounting() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -233,7 +233,7 @@ fn test_enclone_d() { for i in 0..DTESTS.len() { results.push((i, false, String::new())); } - let this = include_str!("testlist.rs"); + let this = include_str!("../../enclone_testlist/src/lib.rs"); let mut tracking = false; let mut comments = Vec::::new(); let mut lines = Vec::::new(); @@ -283,7 +283,7 @@ fn test_enclone_d() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -308,7 +308,7 @@ fn test_grouping() { for i in 0..GTESTS.len() { results.push((i, false, String::new())); } - let this = include_str!("testlist.rs"); + let this = include_str!("../../enclone_testlist/src/lib.rs"); let mut tracking = false; let mut comments = Vec::::new(); let mut lines = Vec::::new(); @@ -358,7 +358,7 @@ fn test_grouping() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -406,7 +406,7 @@ fn test_extended() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -457,7 +457,7 @@ fn test_crash() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -505,7 +505,7 @@ fn test_internal() { for i in 0..results.len() { print!("{}", results[i].2); if !results[i].1 { - std::process::exit(1); + panic!("failed"); } } println!( @@ -747,14 +747,14 @@ fn test_for_broken_links_and_spellcheck() { for _ in 0..depth - 1 { if !z.starts_with("../") { eprintln!("something wrong with file {} on page {}", link, x); - std::process::exit(1); + panic!("failed"); } z = z.after("../").to_string(); } z = format!("../{}", z); if !path_exists(&z) { eprintln!("failed to find file {} on page {}", link, x); - std::process::exit(1); + panic!("failed"); } s = s.after(">(); - if args.contains(&"GEX=123217") && !args.contains(&"H5") { - panic!("Oops please fix this, to prevent sporadic failures."); - } let mut new = Command::new(env!("CARGO_BIN_EXE_enclone")); let mut new = new.arg(format!( "PRE=../enclone-data/big_inputs/version{}", @@ -202,7 +196,7 @@ fn test_enclone_examples() { strme(&new.stderr), ); eprintln!("If it's not clear what is happening, make sure you've run ./build.\n"); - std::process::exit(1); + panic!("failed"); } if old != new2 { eprintln!( @@ -211,7 +205,7 @@ fn test_enclone_examples() { ); eprintln!("old output =\n{}", old); eprintln!("new output =\n{}\n", new2); - std::process::exit(1); + panic!("failed"); } } } @@ -318,7 +312,7 @@ fn test_help_output() { if new.status.code() != Some(0) { eprintln!("Attempt to run {} failed.\n", command); eprintln!("stderr = {}", strme(&new.stderr)); - std::process::exit(1); + panic!("failed"); } let new2 = edit_html(&stringme(&new.stdout)); if old != new2 { @@ -329,7 +323,7 @@ fn test_help_output() { assuming that the change is expected.\n", p ); - std::process::exit(1); + panic!("failed"); } } } @@ -354,15 +348,15 @@ fn test_help_no_stable() { .expect(&format!("failed to execute test_help_output")); if new.status.code() != Some(0) { eprintln!("Attempt to run enclone help all without STABLE_DOC failed.\n"); - std::process::exit(1); + panic!("failed"); } } // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// 21. Test that PREBUILD works. Because this creates and then deletes the .bin file, it -// would play havoc with any test that runs with GEX=123217, unless it also has H5, resulting -// in sporadic (rare) test failures. So don't do that. +// 21. Test that PREBUILD works. This test used to exercise creation of the +// binary matrix format, since removed. It's not entirely clear what purpose this +// test is serving now, beyond yet another regression test. #[cfg(not(feature = "cpu"))] #[test] @@ -377,11 +371,9 @@ fn test_enclone_prebuild() { remove_file(&mb).unwrap(); } - // First pass: run with NH5. - let test_id = 48; let it = test_id - 1; - let testn = format!("{} NH5", TESTS[it]); + let testn = TESTS[it]; let out_file = format!("testx/inputs/outputs/enclone_test{}_output", test_id); let old = read_to_string(&out_file).unwrap(); let args = testn.split(' ').collect::>(); @@ -411,17 +403,10 @@ fn test_enclone_prebuild() { eprintln!("old output =\n{}\n", old); eprintln!("new output =\n{}\n", new2); eprintln!("new stderr = \n{}\n", strme(&new.stderr)); - std::process::exit(1); - } - if !path_exists(&format!( - "../enclone-data/big_inputs/version{}/123217/outs/feature_barcode_matrix.bin", - TEST_FILES_VERSION - )) { - panic!("\nenclone_test_prebuild: did not create feature_barcode_matrix.bin."); + panic!("failed"); } - // Second pass: run without PREBUILD but using the feature_barcode_matrix.bin that the first - // pass created. + // Second pass: run without PREBUILD let testn = TESTS[it]; let args = testn.split(' ').collect::>(); @@ -448,16 +433,9 @@ fn test_enclone_prebuild() { And don't forget to remove feature_barcode_matrix.bin.\n" ); eprintln!("new output =\n{}\n", new2); - std::process::exit(1); + panic!("failed"); } - // Clean up: delete feature_barcode_matrix.bin. - - std::fs::remove_file(&format!( - "../enclone-data/big_inputs/version{}/123217/outs/feature_barcode_matrix.bin", - TEST_FILES_VERSION - )) - .unwrap(); println!("\nused {:.2} seconds in enclone_test_prebuild", elapsed(&t)); } @@ -526,7 +504,7 @@ fn test_proto_write() -> Result<(), Error> { let outputs_bin: EncloneOutputs = io_utils::read_obj(&bin_file); if outputs_proto != outputs_bin { eprintln!("\noutputs_proto is not equal to outputs_bin\n"); - std::process::exit(1); + panic!("failed"); } // Test to make sure that the clonotype iterator works @@ -571,7 +549,7 @@ fn test_proto_write() -> Result<(), Error> { point where the two files differ (or conceivably before)\n\ 7. analyze what is happening with that barcode\n" ); - std::process::exit(1); + panic!("failed"); } } Ok(()) @@ -618,7 +596,7 @@ fn test_annotated_example() { ); emit_end_escape(&mut log); eprintln!("{}", strme(&log)); - std::process::exit(1); + panic!("failed"); } } @@ -665,7 +643,7 @@ fn test_subset_json() { pass, strme(&new.stderr), ); - std::process::exit(1); + panic!("failed"); } let o1 = new.stdout; let mut args = vec!["BCR=testx/outputs/woof".to_string()]; @@ -689,7 +667,7 @@ fn test_subset_json() { pass, strme(&new.stderr), ); - std::process::exit(1); + panic!("failed"); } let o2 = new.stdout; if o1 != o2 { @@ -699,7 +677,7 @@ fn test_subset_json() { ); eprintln!("output 1:\n{}\n", strme(&o1)); eprintln!("output 2:\n{}\n", strme(&o2)); - std::process::exit(1); + panic!("failed"); } let _ = remove_dir_all("testx/outputs/woof"); } @@ -740,7 +718,6 @@ fn test_cell_exact() { .arg(&pre_arg) .arg("BCR=86237") .arg("GEX=85679") - .arg("NH5") .arg("POUT=stdout") .arg(&format!("PCOLS={}", varp)) .arg("PCELL") @@ -762,7 +739,7 @@ fn test_cell_exact() { ); } eprintln!("\n{}", msg); - std::process::exit(1); + panic!("failed"); } } @@ -783,10 +760,10 @@ fn test_ref_only() { .expect(&format!("failed to execute test_subset_json 1")); if new.status.code() == Some(0) { eprint!("\ntest_ref_only: enclone command should not have succeeded.\n"); - std::process::exit(1); + panic!("failed"); } if !strme(&new.stderr).contains("No TCR or BCR data have been specified.") { eprintln!("\ntest_ref_only: unexpected error message\n"); - std::process::exit(1); + panic!("failed"); } } diff --git a/enclone_exec/tests/enclone_test4.rs b/enclone_exec/tests/enclone_test4.rs index 77572b5912..c0111ad959 100644 --- a/enclone_exec/tests/enclone_test4.rs +++ b/enclone_exec/tests/enclone_test4.rs @@ -55,7 +55,7 @@ fn test_cpu_usage() { "\netest_cpu_usage: failed to execute, stderr =\n{}", strme(&new.stderr), ); - std::process::exit(1); + panic!("failed"); } let mut gi = 0.0; let out = strme(&new.stderr); @@ -89,7 +89,7 @@ fn test_cpu_usage() { 4. You got very unlucky." ); eprintln!("\nIf it makes sense, you can change REQUIRED_GI.\n"); - std::process::exit(1); + panic!("failed"); } else { println!("{}", report); } @@ -141,7 +141,7 @@ fn test_source_code_file_length() { } } if fail { - std::process::exit(1); + panic!("failed"); } } @@ -170,7 +170,7 @@ fn test_help_page_list() { "\nHelp page for {} is in HELP_PAGES but not in enclone/pages/auto.\n", x ); - std::process::exit(1); + panic!("failed"); } } for x in help1.iter() { @@ -179,7 +179,7 @@ fn test_help_page_list() { "\nHelp page for {} is in enclone/pages/auto but not in HELP_PAGES.\n", x ); - std::process::exit(1); + panic!("failed"); } } } @@ -215,7 +215,7 @@ fn test_dependency_structure() { crates.\n", d ); - std::process::exit(1); + panic!("failed"); } } } @@ -226,11 +226,7 @@ fn test_dependency_structure() { let top = dir_list(".."); for d in top.iter() { - if d.starts_with("enclone") - && d != "enclone_main" - && d != "enclone_visual" - && d != "enclone_paper" - { + if d.starts_with("enclone") && d != "enclone_main" && d != "enclone_paper" { let toml = format!("../{}/Cargo.toml", d); if path_exists(&toml) { let f = open_for_read![&toml]; @@ -243,7 +239,7 @@ fn test_dependency_structure() { crates.\n", d ); - std::process::exit(1); + panic!("failed"); } } } @@ -267,7 +263,7 @@ fn test_dependency_structure() { crates.\n", d ); - std::process::exit(1); + panic!("failed"); } } } @@ -296,7 +292,7 @@ fn test_rust_version() { "\netest_rust_version: failed to execute, stderr =\n{}", strme(&new.stderr), ); - std::process::exit(1); + panic!("failed"); } let version = strme(&new.stdout).between(" ", " "); let test_yaml = format!("../.github/workflows/test.yaml"); @@ -314,13 +310,13 @@ fn test_rust_version() { Please update the file .github/workflows/test.yaml.\n", version, ga_version, ); - std::process::exit(1); + panic!("failed"); } } } if !version_found { eprintln!("\nFailed to find Rust version in .github/workflows/test.yaml. Weird.\n"); - std::process::exit(1); + panic!("failed"); } } @@ -356,7 +352,7 @@ fn test_exit() { } if !comment { eprintln!("exit not allowed in crate {}, but is in file {}", cname, f); - std::process::exit(1); + panic!("failed"); } } } @@ -405,7 +401,7 @@ fn test_authors() { They are required to be the same.\n", aud[0].0, aud[i].0, ); - std::process::exit(1); + panic!("failed"); } } } @@ -438,7 +434,7 @@ fn test_honey() { "\ntest_honey 1: failed to execute, stderr =\n{}", strme(&new1.stderr), ); - std::process::exit(1); + panic!("failed"); } let new2 = Command::new(env!("CARGO_BIN_EXE_enclone")) .args(&args2) @@ -449,13 +445,13 @@ fn test_honey() { "\ntest_honey 2: failed to execute, stderr =\n{}", strme(&new2.stderr), ); - std::process::exit(1); + panic!("failed"); } let out = strme(&new2.stdout); let expected = include_str!["../testx/inputs/outputs/test_honey.svg"]; if out != expected { eprintln!("\ntest honey yielded changed answer\n"); - std::process::exit(1); + panic!("failed"); } } @@ -471,13 +467,13 @@ fn test_yaml() { let yaml = yaml_rust::YamlLoader::load_from_str(&content); if yaml.is_err() { eprintln!("\nrelease.yaml is not valid YAML.\n"); - std::process::exit(1); + panic!("failed"); } let content = include_str!["../../.github/workflows/test.yaml"]; let yaml = yaml_rust::YamlLoader::load_from_str(&content); if yaml.is_err() { eprintln!("\ntest.yaml is not valid YAML.\n"); - std::process::exit(1); + panic!("failed"); } } @@ -539,11 +535,11 @@ fn test_ranger() { } if !path_exists(&proto_out) { eprintln!("pass = {}, can't find proto_out", pass); - std::process::exit(1); + panic!("failed"); } if !path_exists(&donor_ref_out) { eprintln!("pass = {}, can't find donor_ref_out", pass); - std::process::exit(1); + panic!("failed"); } let mut f = File::open(&proto_out).unwrap(); f.read_to_end(&mut files[0][pass - 1]).unwrap(); @@ -553,7 +549,7 @@ fn test_ranger() { for i in 0..2 { if files[i][0] != files[i][1] { eprintln!("files are different"); - std::process::exit(1); + panic!("failed"); } } } @@ -578,12 +574,12 @@ fn test_unpushed() { "\netest_unpushed: failed to execute, stderr =\n{}", strme(&new.stderr), ); - std::process::exit(1); + panic!("failed"); } let out = strme(&new.stdout); if out.contains("Your branch is ahead of") { eprintln!("\nYour branch has unpushed commits. Please push them.\n"); - std::process::exit(1); + panic!("failed"); } } @@ -605,7 +601,7 @@ fn test_export_code() { let current = std::fs::read_to_string(&f).unwrap(); if outs[i].1 != current { eprintln!("\nexport_code output {} has changed.\n", outs[i].0); - std::process::exit(1); + panic!("failed"); } } } @@ -628,6 +624,6 @@ fn test_newline_bad() { if new.status.code() != Some(0) { eprintln!("\ntest_newline_bad: failed\n"); eprintln!("stderr = {}\n", strme(&new.stderr)); - std::process::exit(1); + panic!("failed"); } } diff --git a/enclone_exec/tests/enclone_test_peak_mem.rs b/enclone_exec/tests/enclone_test_peak_mem.rs deleted file mode 100644 index 68818c60fe..0000000000 --- a/enclone_exec/tests/enclone_test_peak_mem.rs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -#![allow(unused_imports, dead_code)] - -use ansi_escape::*; -use anyhow::Error; -use enclone_core::defs::*; -use enclone_core::*; -use enclone_proto::proto_io::{read_proto, ClonotypeIter}; -use enclone_proto::types::EncloneOutputs; -use enclone_tools::html::*; -use enclone_tools::run_test::*; -use flate2::read::GzDecoder; -use io_utils::*; -use itertools::Itertools; -use perf_stats::*; -use pretty_trace::*; -use rayon::prelude::*; -use serde_json::Value; -use sha2::{Digest, Sha256}; -use stats_utils::*; -use std::cmp::min; -use std::collections::{HashMap, HashSet}; -use std::env; -use std::fs::{metadata, read_dir, read_to_string, remove_dir_all, remove_file, File}; -use std::io; -use std::io::prelude::*; -use std::io::{BufRead, BufReader, BufWriter, Read, Write}; -use std::process::{Command, Stdio}; -use std::thread; -use std::time; -use std::time::{Duration, Instant}; -use string_utils::*; -use vector_utils::*; - -const LOUPE_OUT_FILENAME: &str = "testx/__test_proto"; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Test peak memory. This is designed for one server at 10x Genomics. This used to test for -// *less* memory than expected, but at a certain point, we started observing cases where the -// memory was lower, and then on a subsequent run went back to expected value. -// -// This is in a separate file because doing so makes it possible to run just this one test, -// and have it run by ./test, and have it not run by the CI. -// -// You can run this test alone by typing -// cargo test --test enclone_test_peak_mem -- --nocapture -// from the root of the repo. - -#[cfg(not(feature = "cpu"))] -#[test] -fn test_peak_memory() { - PrettyTrace::new().on(); - - // Specify mem requirements. - - let dataset = "BCR=123085"; - let expected_mb = 369.6; - - let max_percent_dev = 0.5; - - // Only run internally. - - let mut internal_run = false; - for (key, value) in env::vars() { - if key.contains("TELEPORT") && value.contains("10xgenomics.com") { - internal_run = true; - } - } - if !internal_run { - return; - } - - // Define function to get mem. - - fn mem_val(dataset: &str) -> f64 { - let new = Command::new(env!("CARGO_BIN_EXE_enclone")) - .arg(&dataset) - .args(&["NOPRINT", "COMP"]) - .output() - .expect(&format!("failed to execute peak mem test")); - if new.status.code() != Some(0) { - eprint!( - "\nenclone_site_examples: nonzero status code for peak mem test, stderr =\n{}", - strme(&new.stderr), - ); - std::process::exit(1); - } - let out = strme(&new.stdout); - let mut mem = None; - for line in out.lines() { - if line.starts_with("peak mem usage = ") && line.ends_with(" MB") { - mem = Some(line.between("peak mem usage = ", " MB").force_f64()); - } - } - if mem.is_none() { - eprintln!("\nfailed to find mem usage for peak mem\n"); - std::process::exit(1); - } - mem.unwrap() - } - - // Run the test. - - let mut ok = false; - let mut mems = Vec::::new(); - for _tries in 0..3 { - let mem = mem_val(&dataset); - mems.push(mem); - let dev = 100.0 * (mem - expected_mb).abs() / expected_mb; - if dev <= max_percent_dev { - ok = true; - break; - } - } - if !ok { - for _tries in 3..10 { - mems.push(mem_val(&dataset)); - } - } - let mut mean = 0.0; - for i in 0..mems.len() { - mean += mems[i]; - } - mean /= mems.len() as f64; - let dev = 100.0 * (mean - expected_mb) / expected_mb; - let msg = format!( - "Peak mem of {:.1} MB observed, which differs from expected value of {} by {:.2}%.", - mean, expected_mb, dev - ); - if !ok && dev > max_percent_dev { - eprintln!("\n{}\n", msg); - eprintln!("observed values:\n"); - for i in 0..mems.len() { - eprintln!("{:.1}", mems[i]); - } - eprintln!( - "Please note that this test was designed to work correctly from a single server\n\ - at 10x Genomics. \ - If you're running from a different server, the expected memory value\n\ - may need to be changed. This might also be the case if that server was changed.\n\ - Otherwise, your options are:\n\ - 1. Change the value of expected_mb in enclone_test.rs to {:.1}.\n\ - 2. Optimize to reduce mem usage (if value exceeds expected).\n\ - 3. Repeat the test, but this is very unlikely to succeed.\n", - mean - ); - std::process::exit(1); - } else { - println!("{}", msg); - } -} diff --git a/enclone_exec/tests/testlist.rs b/enclone_exec/tests/testlist.rs deleted file mode 120000 index 72e6857b8d..0000000000 --- a/enclone_exec/tests/testlist.rs +++ /dev/null @@ -1 +0,0 @@ -../../enclone_testlist/src/lib.rs \ No newline at end of file diff --git a/enclone_exec/testx/inputs/outputs/enclone_test265_output b/enclone_exec/testx/inputs/outputs/enclone_test265_output index 7b8b3d0577..7cc1a2f973 100644 --- a/enclone_exec/testx/inputs/outputs/enclone_test265_output +++ b/enclone_exec/testx/inputs/outputs/enclone_test265_output @@ -42,22 +42,3 @@ DATASET-LEVEL METRICS │86237 │ 50.8 │ 51.8│ └─────────┴──────────────────────┴────────────────────┘ -feature barcode UMI distribution for 86237 -┌─────┬────────────────┬─────────────────┬────────────────────┐ -│ │ │ NaN reference │ │ -│ │ ├─────────────────┼────────────────────┤ -│ │ │ │ inf TCAATCCTTCCGCTT│ -│ │ NaN cellular │ ├────────────────────┤ -│ │ │ NaN nonreference│ inf TCACCAGTACCTAGT│ -│ │ │ ├────────────────────┤ -│ │ │ │ inf CTCATTGTAACTCCT│ -│100.0├────────────────┼─────────────────┼────────────────────┤ -│ │ │ NaN reference │ │ -│ │ ├─────────────────┼────────────────────┤ -│ │ │ │ inf TCAATCCTTCCGCTT│ -│ │ NaN noncellular│ ├────────────────────┤ -│ │ │ NaN nonreference│ inf TCACCAGTACCTAGT│ -│ │ │ ├────────────────────┤ -│ │ │ │ inf CTCATTGTAACTCCT│ -└─────┴────────────────┴─────────────────┴────────────────────┘ - diff --git a/enclone_exec/testx/inputs/outputs/enclone_test269_output b/enclone_exec/testx/inputs/outputs/enclone_test269_output index 1360a49323..046f30e781 100644 --- a/enclone_exec/testx/inputs/outputs/enclone_test269_output +++ b/enclone_exec/testx/inputs/outputs/enclone_test269_output @@ -1,29 +1,23 @@ -[1] GROUP = 1 CLONOTYPES = 3 CELLS +[1] GROUP = 1 CLONOTYPES = 51 CELLS -[1.1] CLONOTYPE = 3 CELLS -┌──────────────────────────────────────────────────┬────────────────────────┬─────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 194|IGHV4-59 │ 349|IGLV3-1│ -│ │ ◆ 29|IGHD5-18 │ ◆ 311|IGLJ2│ -│ │ ◆ 57|IGHJ5 │ │ -│ ├────────────────────────┼─────────────┤ -│ │ 11111111111111111111 │ 11111111111│ -│ │ 11111112222222222333 │ 00000111111│ -│ │ 34567890123456789012 │ 56789012345│ -│ │ ════════CDR3════════ │ ════CDR3═══│ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQAWD◦◦◦◦◦◦│ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQAWD◦◦◦◦◦◦│ -├──────────────────────────────────────────────────┼────────────────────────┼─────────────┤ -│# barcode n fb1 fb1_n │ .................... │ ...........│ -│1 1 TCAATCCTTCCGCTT 1999 │ CARSFFGDTAMVMFQAFDPW │ CQAWDSSTVVF│ -│ GCTGGGTTCAACCAAC-1 1999 │ │ │ -│2 2 TCAATCCTTCCGCTT 1869 │ │ CQAWDSSTVVF│ -│ ACGTCAAAGTGGTAGC-1 1847 │ │ │ -│ ATGTGTGAGAGTACCG-1 1891 │ │ │ -└──────────────────────────────────────────────────┴────────────────────────┴─────────────┘ -fb2 fb2_n fb2_n_cell -TCACCAGTACCTAGT 74 74 -TCACCAGTACCTAGT 76 78 -TCACCAGTACCTAGT 76 74 +[1.1] CLONOTYPE = 51 CELLS +┌───────────┬───────────────────────────────────────────┬──────────────────────────────────────┐ +│ │ CHAIN 1 │ CHAIN 2 │ +│ │ 144.1.2|IGHV3-49 ◆ 53|IGHJ3 │ 279|IGKV3-11 ◆ 217|IGKJ5 │ +│ ├───────────────────────────────────────────┼──────────────────────────────────────┤ +│ │ 111111111111111111111111111 │ 1111111111111111111111 │ +│ │ 111122222222223333333333444 │ 0001111111111222222222 │ +│ │ 678901234567890123456789012 │ 7890123456789012345678 │ +│ │ ═══════CDR3═════════FWR4═══ │ ═════CDR3═══════FWR4══ │ +│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦WGQGTMVTVSS │ CQQ◦◦◦◦◦◦◦◦◦◦◦◦GTRLEIK │ +│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦WGQGTMVTVSS │ CQQ◦◦◦◦◦◦◦◦◦◦◦◦GTRLEIK │ +│consensus │ CTRDRDLRGATDAFDIWGQGTMVTVSS │ CXQRSNWPPSITFGQGTRLEIK │ +├───────────┼───────────────────────────────────────────┼──────────────────────────────────────┤ +│# n │ .........................x. u const │ .x.................... u const│ +│1 46 │ CTRDRDLRGATDAFDIWGQGTMVTVSS 101 IGHG1 │ CQQRSNWPPSITFGQGTRLEIK 3769 IGKC │ +│2 3 │ CTRDRDLRGATDAFDIWGQGTMVTVSS 73 IGHG1 │ CHQRSNWPPSITFGQGTRLEIK 7548 IGKC │ +│3 1 │ CTRDRDLRGATDAFDIWGQGTMVTVSS 279 IGHG1 │ CQQRSNWPPSITFGQGTRLEIK 12446 IGKC │ +│4 1 │ CTRDRDLRGATDAFDIWGQGTMVTVSS 33 IGHG1 │ CQQRSNWPPSITFGQGTRLEIK 116 IGKC │ +└───────────┴───────────────────────────────────────────┴──────────────────────────────────────┘ diff --git a/enclone_help/src/help2.rs b/enclone_help/src/help2.rs index c3ecd37a61..23c47b1cb9 100644 --- a/enclone_help/src/help2.rs +++ b/enclone_help/src/help2.rs @@ -13,8 +13,7 @@ pub const EXAMPLES: [&str; 2] = [ // 1. r###"BCR=123089 CDR3=CARRYFGVVADAFDIW"###, // 2. - // Do not use NH5 because the bin file is too big for git. - r###"BCR=123085 GEX=123217 H5 LVARSP=gex,IGHV2-5_g_μ CDR3=CALMGTYCSGDNCYSWFDPW"###, + r###"BCR=123085 GEX=123217 LVARSP=gex,IGHV2-5_g_μ CDR3=CALMGTYCSGDNCYSWFDPW"###, ]; // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ @@ -96,21 +95,13 @@ pub fn help2(args: &Vec, _ctl: &EncloneControl, h: &mut HelpDesk) -> Res h.begin_doc("example2")?; h.print("\nShown below is the output of the command:\n")?; - // Remove H5. - let ex2_args = EXAMPLES[1].split(' ').collect::>(); - let mut ex2_args2 = Vec::<&str>::new(); - for i in 0..ex2_args.len() { - if ex2_args[i] != "H5" { - ex2_args2.push(ex2_args[i]); - } - } // Proceed. h.print(&format!( "\n\\bold{{enclone {}}}\n", - ex2_args2.iter().format(" ") + ex2_args.iter().format(" ") ))?; if !h.plain { h.print_plain_unchecked(include_str!("example2")); @@ -176,23 +167,6 @@ pub fn help2(args: &Vec, _ctl: &EncloneControl, h: &mut HelpDesk) -> Res short as possible, as longer abbreviations will increase the width of the clonotype \ displays.\n\n", )?; - h.print_with_box( - "enclone can use gene expression and feature barcode data, as represented by a feature \ - matrix. Cell Ranger stores this matrix in an hdf5 file, which while generally very \ - efficient, is not optimized for interactive use. Therefore enclone provides an \ - alternate file structure, which speeds up enclone overall by up to \\boldred{50%}. \ - To use this, add the argument \\bold{NH5} to the enclone command line. This will \ - work so long as you have write permission on input directories. The first time you \ - run enclone (using given inputs), an alternate file feature_barcode_matrix.bin will \ - be written; then subsequent invocations will be faster. Once the file has been \ - created, it will always be used, regardless of whether \\bold{NH5} is used. \ - However, we may occasionally change the format of the alternate file. If do that, \ - then if you have previously generated the file, then it will be rewritten when \ - you invoke enclone for that dataset. \ - Like with other enclone command-line options, if you want \\bold{NH5} on all the \ - time, you can set the environment variable \\bold{ENCLONE_NH5}.", - true - )?; h.print( "\\boldred{█ 1 █} To point directly at input files on the command line, use e.g.\n\ \\bold{TCR=/home/jdoe/runs/dataset345}\n\ diff --git a/enclone_main/src/main_enclone.rs b/enclone_main/src/main_enclone.rs index f6a6eb61b0..05455d152c 100644 --- a/enclone_main/src/main_enclone.rs +++ b/enclone_main/src/main_enclone.rs @@ -276,49 +276,6 @@ pub fn main_enclone_setup(args: &Vec) -> Result { } check_pcols(&ctl, &gex_info, &var_def_vars, ctl.parseable_opt.pbarcode)?; - // Check ALL_BC arguments. - - if ctl.gen_opt.all_bc_filename.len() > 0 { - if gex_info.gex_barcodes.is_empty() { - return Err(format!("\nYou can't use ALL_BC with VDJ data alone.\n")); - } - for li in 0..ctl.origin_info.n() { - if !gex_info.gex_matrices[li].initialized() { - return Err(format!( - "\nALL_BC only works if feature_barcode_matrix.bin has been \ - generated.\nPlease type \"enclone help input\" for more information.\n" - )); - } - } - let known_features = get_known_features(&gex_info)?; - let extras = ["gex", "type", "clust", "cell"]; - for i in 0..ctl.gen_opt.all_bc_fields.len() { - let var = &ctl.gen_opt.all_bc_fields[i]; - let mut ok = false; - if bin_member(&known_features, var) { - ok = true; - } - let mut nd_var = false; - for j in 0..extras.len() { - if *var == extras[j] { - if *var != "cell" { - check_one_lvar( - var, - &ctl, - &gex_info, - &mut nd_var, - &Vec::::new(), - true, - )?; - } - ok = true; - } - } - if !ok { - return Err(format!("\nIllegal variable {} in ALL_BC.\n", var)); - } - } - } ctl.perf_stats(&twoof, "checking pcols"); // Check DVARS. diff --git a/enclone_main/src/setup.rs b/enclone_main/src/setup.rs index 3530f028a0..082e7a8e67 100644 --- a/enclone_main/src/setup.rs +++ b/enclone_main/src/setup.rs @@ -259,11 +259,10 @@ pub fn setup( } else if args[i] == "LONG_HELP" { long_help = true; to_delete[i] = true; - } else if args[i].starts_with("MAX_CORES=") { - to_delete[i] = true; - } else if args[i].starts_with("PRE=") { - to_delete[i] = true; - } else if args[i].starts_with("PREPOST=") { + } else if args[i].starts_with("MAX_CORES=") + || args[i].starts_with("PRE=") + || args[i].starts_with("PREPOST=") + { to_delete[i] = true; } else if args[i] == "PLAIN" { to_delete[i] = true; @@ -341,7 +340,6 @@ pub fn setup( ctl.pretty = true; let mut nopretty = false; - ctl.gen_opt.h5 = true; let mut visual = false; for i in 1..args.len() { if is_simple_arg(&args[i], "PLAIN")? { @@ -357,9 +355,6 @@ pub fn setup( ctl.perf_opt.comp = true; ctl.perf_opt.comp2 = true; } - if is_simple_arg(&args[i], "NH5")? { - ctl.gen_opt.h5 = false; - } if is_simple_arg(&args[i], "VISUAL")? { visual = true; } diff --git a/enclone_main/src/stop.rs b/enclone_main/src/stop.rs index 2b523c1347..35739e5181 100644 --- a/enclone_main/src/stop.rs +++ b/enclone_main/src/stop.rs @@ -59,7 +59,7 @@ pub fn main_enclone_stop(mut inter: EncloneIntermediates) -> Result>::new(); let mut ind_readers = Vec::>::new(); for li in 0..ctl.origin_info.n() { - if !ctl.origin_info.gex_path[li].is_empty() && !gex_info.gex_matrices[li].initialized() { + if !ctl.origin_info.gex_path[li].is_empty() { let x = gex_info.h5_data[li].as_ref(); if x.is_none() { // THIS FAILS SPORADICALLY, OBSERVED MULTIPLE TIMES, @@ -123,123 +123,13 @@ pub fn main_enclone_stop(mut inter: EncloneIntermediates) -> Result 0 { - let tallbc = Instant::now(); - let mut f = open_for_write_new![&ctl.gen_opt.all_bc_filename]; - let mut rows = Vec::>::new(); - let mut header = vec!["dataset".to_string(), "barcode".to_string()]; - header.append(&mut ctl.gen_opt.all_bc_fields_orig.clone()); - if !ctl.gen_opt.all_bc_human { - fwriteln!(f, "{}", header.iter().format(",")); - } - rows.push(header); - for li in 0..ctl.origin_info.n() { - for bc in gex_info.gex_barcodes[li].iter() { - let mut fields = Vec::::new(); - fields.push(ctl.origin_info.dataset_id[li].clone()); - fields.push(bc.to_string()); - for var in ctl.gen_opt.all_bc_fields.iter() { - let is_gex_cell = bin_member(&gex_info.gex_cell_barcodes[li], bc); - if var == "cell" { - let is_vdj_cell = bin_member(&vdj_cells[li], bc); - if is_gex_cell && is_vdj_cell { - fields.push("gex_vdj".to_string()); - } else if is_gex_cell { - fields.push("gex".to_string()); - } else if is_vdj_cell { - fields.push("vdj".to_string()); - } else { - fields.push("empty".to_string()); - } - } else if var == "type" { - if is_gex_cell { - let mut typex = gex_info.cell_type[li][bc].clone(); - if typex.contains(",") { - typex = typex.before(",").to_string(); - } - fields.push(typex); - } else { - fields.push("unknown".to_string()); - } - } else if var == "clust" { - if gex_info.cluster[li].contains_key(&bc.clone()) { - fields.push(format!("{}", gex_info.cluster[li][&bc.clone()])); - } else { - fields.push("none".to_string()); - } - } else if var == "gex" { - let mut count = 0; - let p = bin_position(&gex_info.gex_barcodes[li], bc.as_str()); - if p >= 0 { - let row = gex_info.gex_matrices[li].row(p as usize); - for j in 0..row.len() { - let f = row[j].0; - let n = row[j].1; - if gex_info.is_gex[li][f] { - count += n; - } - } - } - fields.push(format!("{}", count)); - } else { - let p = bin_position(&gex_info.gex_barcodes[li], bc.as_str()); - let mut count = 0; - if p >= 0 { - if gex_info.feature_id[li].contains_key(&var.clone()) { - let fid = gex_info.feature_id[li][&var.clone()]; - count = gex_info.gex_matrices[li].value(p as usize, fid); - } - } - fields.push(format!("{}", count)); - } - } - if !ctl.gen_opt.all_bc_human { - fwriteln!(f, "{}", fields.iter().format(",")); - } - rows.push(fields); - } - for bc in vdj_cells[li].iter() { - // We would expect the following code to be executed only rarely. - if !bin_member(&gex_info.gex_barcodes[li], bc) { - let mut fields = Vec::::new(); - fields.push(ctl.origin_info.dataset_id[li].clone()); - fields.push(bc.to_string()); - for var in ctl.gen_opt.all_bc_fields.iter() { - if var == "cell" { - fields.push("vdj".to_string()); - } else if var == "type" || var == "none" { - fields.push("unknown".to_string()); - } else { - fields.push("0".to_string()); - } - } - if !ctl.gen_opt.all_bc_human { - fwriteln!(f, "{}", fields.iter().format(",")); - } - rows.push(fields); - } - } - } - if ctl.gen_opt.all_bc_human { - let mut log = Vec::::new(); - print_tabular(&mut log, &rows, 2, None); - fwrite!(f, "{}", strme(&log)); - } - ctl.perf_stats(&tallbc, "carrying out ALL_BC"); - } - // Find and print clonotypes. (But we don't actually print them here.) let torb = Instant::now(); @@ -291,12 +181,6 @@ pub fn main_enclone_stop(mut inter: EncloneIntermediates) -> Result) { if ctl.visual_mode || ctl.gen_opt.vis_dump { @@ -55,613 +47,3 @@ pub fn description_table(ctl: &EncloneControl, logx: &mut Vec) { } } } - -// There are similar functions below, one computing by reads, the other by UMIs. - -pub fn alluvial_fb_reads( - ctl: &EncloneControl, - gex_info: &GexInfo, - vdj_cells: &Vec>, - logx: &mut Vec, -) { - let mut fs = Vec::::new(); - let mut results = Vec::<(usize, bool, FeatureBarcodeAlluvialReadsTable, Vec)>::new(); - for li in 0..ctl.origin_info.n() { - results.push(( - li, - false, - FeatureBarcodeAlluvialReadsTable::default(), - Vec::new(), - )); - } - results.par_iter_mut().for_each(|res| { - let li = res.0; - let m = &gex_info.fb_top_reads_matrices[li]; - if m.initialized() { - let mut row_is_cell = vec![false; m.nrows()]; - for j in 0..m.nrows() { - if bin_member(&vdj_cells[li], &m.row_label(j)) { - row_is_cell[j] = true; - } - } - res.1 = true; - let mut keep = 3; - let mut specials = Vec::::new(); - if !ctl.gen_opt.fb_show.is_empty() { - let fb_show = ctl.gen_opt.fb_show.split(',').collect::>(); - for x in fb_show.iter() { - if x.parse::().is_ok() { - keep = x.force_usize(); - } else { - specials.push(x.to_string()); - } - } - } - let mut cells = Vec::::new(); - for i in 0..vdj_cells[li].len() { - cells.push(vdj_cells[li][i].before("-").to_string()); - } - let brnr = &gex_info.fb_brnr[li]; - let bdcs = &gex_info.fb_bdcs[li]; - let total = gex_info.fb_total_reads[li] as usize; - let mut seq_to_id = HashMap::::new(); - { - let fref = &gex_info.feature_refs[li]; - let (mut id_pos, mut seq_pos, mut type_pos) = (0, 0, 0); - for (i, line) in fref.lines().enumerate() { - let fields = parse_csv(line); - if i == 0 { - for j in 0..fields.len() { - if fields[j] == "id" { - id_pos = j; - } else if fields[j] == "sequence" { - seq_pos = j; - } else if fields[j] == "feature_type" { - type_pos = j; - } - } - } else if fields[type_pos] == "Antibody Capture" - || fields[type_pos] == "Antigen Capture" - { - seq_to_id.insert(fields[seq_pos].to_string(), fields[id_pos].to_string()); - } - } - } - println!("{:?}", seq_to_id); - let (mut cellular_ref, mut cellular_nref) = (0, 0); - let (mut ncellular_ref, mut ncellular_nref) = (0, 0); - let (mut cellular_degen, mut ncellular_degen) = (0, 0); - // let (mut cellular_canon, mut ncellular_canon) = (0, 0); - // let (mut cellular_semi, mut ncellular_semi) = (0, 0); - let mut ncellular_canon = 0; - let mut ncellular_semi = 0; - { - for i in 0..brnr.len() { - if bin_member(&cells, &brnr[i].0) { - cellular_ref += brnr[i].1 as usize; - cellular_nref += brnr[i].2 as usize; - } else { - ncellular_ref += brnr[i].1 as usize; - ncellular_nref += brnr[i].2 as usize; - } - } - for i in 0..bdcs.len() { - if bin_member(&cells, &bdcs[i].0) { - cellular_degen += bdcs[i].1 as usize; - // cellular_canon += bdcs[i].2 as usize; - // cellular_semi += bdcs[i].3 as usize; - } else { - ncellular_degen += bdcs[i].1 as usize; - ncellular_canon += bdcs[i].2 as usize; - ncellular_semi += bdcs[i].3 as usize; - } - } - } - let mut top_ref = Vec::<(usize, String)>::new(); - let mut top_nref = Vec::<(usize, String)>::new(); - for i in 0..m.ncols() { - let bc = m.col_label(i); - if seq_to_id.contains_key(&bc) { - if top_ref.len() < keep { - top_ref.push((i, m.col_label(i))); - } - } else if top_nref.len() < keep { - top_nref.push((i, m.col_label(i))); - } - } - for i in 0..specials.len() { - let mut found = false; - for j in 0..m.ncols() { - let bc = m.col_label(j); - if specials[i] == bc { - if seq_to_id.contains_key(&bc) { - top_ref.push((j, m.col_label(j))); - } else { - top_nref.push((j, m.col_label(j))); - } - found = true; - } - } - if !found { - if seq_to_id.contains_key(&specials[i]) { - top_ref.push((1000000, specials[i].clone())); - } else { - top_nref.push((1000000, specials[i].clone())); - } - } - } - unique_sort(&mut top_ref); - unique_sort(&mut top_nref); - let xr = max(top_ref.len(), 1); - let xnr = max(top_nref.len(), 1); - fn pr(x: usize, y: usize) -> String { - format!("{:>4.1}", percent_ratio(x, y)) - } - fn pr0(x: usize, y: usize) -> String { - format!("{:.1}", percent_ratio(x, y)) - } - let nrows = 4 * (xr + xnr) + 7; - let ncols = 4; - let mut rows = vec![vec![String::new(); ncols]; nrows - 2]; - let mut csv_rows = vec![vec![String::new(); 6]; nrows - 4]; - let midrow = 2 * (xr + xnr) + 1; - rows[midrow][0] = "100.0".to_string(); - for j in 1..ncols { - rows[midrow][j] = "\\hline".to_string(); - } - - rows[0][2] = format!("{} degenerate", pr(cellular_degen, total)); - - // rows[0][3] = format!("{} canonical", pr(cellular_canon, total)); - // rows[1][3] = "\\hline".to_string(); - rows[1][2] = "\\hline".to_string(); - rows[1][3] = "\\hline".to_string(); - // rows[2][3] = format!("{} semicanonical", pr(cellular_semi, total)); - - rows[midrow][3] = "\\hline".to_string(); - rows[midrow + 1][3] = format!("{} canonical", pr(ncellular_canon, total)); - - rows[midrow + 2][2] = format!("{} degenerate", pr(ncellular_degen, total)); - rows[midrow + 2][3] = "\\hline".to_string(); - - rows[midrow + 3][3] = format!("{} semicanonical", pr(ncellular_semi, total)); - rows[midrow + 4][2] = "\\hline".to_string(); - rows[midrow + 4][3] = "\\hline".to_string(); - - let mut count = 0; - for pass in 0..2 { - if pass == 0 { - count += 2; - } else { - count += 4; - } - for i in 0..xr { - count += 1; - rows[count][3] = "\\hline".to_string(); - if i == xr - 1 { - rows[count][2] = "\\hline".to_string(); - } - count += 1 - } - for i in 0..xnr { - count += 1; - if pass == 0 || i < xnr - 1 { - rows[count][3] = "\\hline".to_string(); - } - count += 1; - } - } - - let r = 2 * (xr + xnr) + 4; - csv_rows[r - 4][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r - 4][1] = "noncellular".to_string(); - csv_rows[r - 4][2] = "degenerate".to_string(); - csv_rows[r - 4][3] = format!("{}", pr0(ncellular_canon, total)); - csv_rows[r - 4][4] = "canonical".to_string(); - - let r = 2 * (xr + xnr) + 6; - csv_rows[r - 4][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r - 4][1] = "noncellular".to_string(); - csv_rows[r - 4][2] = "degenerate".to_string(); - csv_rows[r - 4][3] = format!("{}", pr0(ncellular_semi, total)); - csv_rows[r - 4][4] = "semicanonical".to_string(); - - for pass in 0..2 { - for i in 0..top_ref.len() { - let c = top_ref[i].0; - let seq = &top_ref[i].1; - let (mut cell, mut ncell) = (0, 0); - let label = format!("{} = {}", seq, seq_to_id[seq]); - if c < 1000000 { - for j in 0..m.nrows() { - if row_is_cell[j] { - cell += m.value(j, c as usize); - } else { - ncell += m.value(j, c as usize); - } - } - } - if pass == 0 { - let r = 2 * i + 4; - rows[r - 2][3] = format!("{} {}", pr(cell, total), label); - csv_rows[r - 4][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r - 4][1] = "cellular".to_string(); - csv_rows[r - 4][2] = "reference".to_string(); - csv_rows[r - 4][3] = format!("{}", pr0(cell, total)); - csv_rows[r - 4][4] = seq.clone(); - csv_rows[r - 4][5] = seq_to_id[seq].clone(); - } else { - let r = 2 * (xr + xnr) + 2 * i + 8; - rows[r - 2][3] = format!("{} {}", pr(ncell, total), label); - csv_rows[r - 4][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r - 4][1] = "noncellular".to_string(); - csv_rows[r - 4][2] = "reference".to_string(); - csv_rows[r - 4][3] = format!("{}", pr0(ncell, total)); - csv_rows[r - 4][4] = seq.clone(); - csv_rows[r - 4][5] = seq_to_id[seq].clone(); - } - } - - for i in 0..top_nref.len() { - let c = top_nref[i].0; - let seq = &top_nref[i].1; - let (mut cell, mut ncell) = (0, 0); - if c < 1000000 { - for j in 0..m.nrows() { - if row_is_cell[j] { - cell += m.value(j, c as usize); - } else { - ncell += m.value(j, c as usize); - } - } - } - if pass == 0 { - let r = 2 * (i + xr) + 4; - rows[r - 2][3] = format!("{} {}", pr(cell, total), seq); - csv_rows[r - 4][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r - 4][1] = "cellular".to_string(); - csv_rows[r - 4][2] = "nonreference".to_string(); - csv_rows[r - 4][3] = format!("{}", pr0(cell, total)); - csv_rows[r - 4][4] = seq.clone(); - } else { - let r = 2 * (xr + xnr) + 2 * (i + xr) + 8; - csv_rows[r - 4][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r - 4][1] = "noncellular".to_string(); - csv_rows[r - 4][2] = "nonreference".to_string(); - csv_rows[r - 4][3] = format!("{}", pr0(ncell, total)); - csv_rows[r - 4][4] = seq.clone(); - rows[r - 2][3] = format!("{} {}", pr(ncell, total), seq); - } - } - } - rows[xr - 1 + 2][2] = format!("{} reference", pr(cellular_ref, total)); - rows[2 * (xr + xnr) + xr - 1 + 6][2] = - format!("{} reference", pr(ncellular_ref, total)); - rows[2 * xr + xnr - 1 + 2][2] = format!("{} nonreference", pr(cellular_nref, total)); - rows[2 * xr + 2 * (xr + xnr) + xnr - 1 + 6][2] = - format!("{} nonreference", pr(ncellular_nref, total)); - rows[xr + xnr - 1 + 1][1] = format!( - "{} cellular", - pr(cellular_ref + cellular_nref + cellular_degen, total) - ); - rows[2 * (xr + xnr) + xr + xnr - 1 + 4][1] = format!( - "{} noncellular", - pr(ncellular_ref + ncellular_nref + ncellular_degen, total) - ); - - let mut display_text = String::new(); - print_tabular_vbox( - &mut display_text, - &rows, - 0, - &b"l|l|l|l".to_vec(), - false, - false, - ); - if !ctl.visual_mode && !ctl.gen_opt.vis_dump { - fwrite!( - res.3, - "\nfeature barcode read distribution for {}\n{}", - ctl.origin_info.dataset_id[li], - display_text - ); - } else { - let mut spreadsheet_text = String::new(); - for (i, r) in csv_rows.iter().enumerate() { - if i % 2 == 0 { - spreadsheet_text += &mut format!("{}\n", r.iter().format("\t ")); - } - } - let f = FeatureBarcodeAlluvialReadsTable { - id: ctl.origin_info.dataset_id[li].clone(), - display_text: display_text.clone(), - spreadsheet_text: spreadsheet_text.clone(), - }; - res.2 = f; - } - } - }); - let mut have_some = false; - for i in 0..results.len() { - if results[i].1 { - have_some = true; - } - fs.push(results[i].2.clone()); - logx.append(&mut results[i].3.clone()); - } - if (ctl.visual_mode || ctl.gen_opt.vis_dump) && have_some { - let tables = FeatureBarcodeAlluvialReadsTableSet { s: fs }; - logx.append(&mut tables.to_string().as_bytes().to_vec()); - } -} - -pub fn alluvial_fb( - ctl: &EncloneControl, - gex_info: &GexInfo, - vdj_cells: &Vec>, - logx: &mut Vec, -) { - let mut fs = Vec::::new(); - let mut results = Vec::<(usize, bool, FeatureBarcodeAlluvialTable, Vec)>::new(); - for li in 0..ctl.origin_info.n() { - results.push(( - li, - false, - FeatureBarcodeAlluvialTable::default(), - Vec::new(), - )); - } - results.par_iter_mut().for_each(|res| { - let li = res.0; - let m = &gex_info.fb_top_matrices[li]; - if m.initialized() { - let mut row_is_cell = vec![false; m.nrows()]; - for j in 0..m.nrows() { - if bin_member(&vdj_cells[li], &m.row_label(j)) { - row_is_cell[j] = true; - } - } - res.1 = true; - let mut keep = 3; - let mut specials = Vec::::new(); - if !ctl.gen_opt.fb_show.is_empty() { - let fb_show = ctl.gen_opt.fb_show.split(',').collect::>(); - for x in fb_show.iter() { - if x.parse::().is_ok() { - keep = x.force_usize(); - } else { - specials.push(x.to_string()); - } - } - } - let mut cells = Vec::::new(); - for i in 0..vdj_cells[li].len() { - cells.push(vdj_cells[li][i].before("-").to_string()); - } - let brn = &gex_info.fb_brn[li]; - let total = gex_info.fb_total_umis[li] as usize; - let mut seq_to_id = HashMap::::new(); - { - let fref = &gex_info.feature_refs[li]; - let (mut id_pos, mut seq_pos, mut type_pos) = (0, 0, 0); - for (i, line) in fref.lines().enumerate() { - let fields = parse_csv(line); - if i == 0 { - for j in 0..fields.len() { - if fields[j] == "id" { - id_pos = j; - } else if fields[j] == "sequence" { - seq_pos = j; - } else if fields[j] == "feature_type" { - type_pos = j; - } - } - } else if fields[type_pos] == "Antibody Capture" - || fields[type_pos] == "Antigen Capture" - { - seq_to_id.insert(fields[seq_pos].to_string(), fields[id_pos].to_string()); - } - } - } - let (mut cellular_ref, mut cellular_nref) = (0, 0); - let (mut ncellular_ref, mut ncellular_nref) = (0, 0); - { - for i in 0..brn.len() { - if bin_member(&cells, &brn[i].0) { - cellular_ref += brn[i].1 as usize; - cellular_nref += brn[i].2 as usize; - } else { - ncellular_ref += brn[i].1 as usize; - ncellular_nref += brn[i].2 as usize; - } - } - } - let mut top_ref = Vec::<(usize, String)>::new(); - let mut top_nref = Vec::<(usize, String)>::new(); - for i in 0..m.ncols() { - let bc = m.col_label(i); - if seq_to_id.contains_key(&bc) { - if top_ref.len() < keep { - top_ref.push((i, m.col_label(i))); - } - } else if top_nref.len() < keep { - top_nref.push((i, m.col_label(i))); - } - } - for i in 0..specials.len() { - let mut found = false; - for j in 0..m.ncols() { - let bc = m.col_label(j); - if specials[i] == bc { - if seq_to_id.contains_key(&bc) { - top_ref.push((j, m.col_label(j))); - } else { - top_nref.push((j, m.col_label(j))); - } - found = true; - } - } - if !found { - if seq_to_id.contains_key(&specials[i]) { - top_ref.push((1000000, specials[i].clone())); - } else { - top_nref.push((1000000, specials[i].clone())); - } - } - } - unique_sort(&mut top_ref); - unique_sort(&mut top_nref); - let xr = max(top_ref.len(), 1); - let xnr = max(top_nref.len(), 1); - let nrows = 4 * (xr + xnr) - 1; - let ncols = 4; - let mut rows = vec![vec![String::new(); ncols]; nrows]; - let mut csv_rows = vec![vec![String::new(); 6]; nrows]; - rows[2 * (xr + xnr) - 1][0] = "100.0".to_string(); - for j in 1..ncols { - rows[2 * (xr + xnr) - 1][j] = "\\hline".to_string(); - } - let mut count = 0; - for pass in 0..2 { - for i in 0..xr { - count += 1; - rows[count][3] = "\\hline".to_string(); - if i == xr - 1 { - rows[count][2] = "\\hline".to_string(); - } - count += 1 - } - for i in 0..xnr { - count += 1; - if pass == 0 || i < xnr - 1 { - rows[count][3] = "\\hline".to_string(); - } - count += 1; - } - } - fn pr(x: usize, y: usize) -> String { - format!("{:>4.1}", percent_ratio(x, y)) - } - fn pr0(x: usize, y: usize) -> String { - format!("{:.1}", percent_ratio(x, y)) - } - for pass in 0..2 { - for i in 0..top_ref.len() { - let c = top_ref[i].0; - let seq = &top_ref[i].1; - let (mut cell, mut ncell) = (0, 0); - let label = format!("{} = {}", seq, seq_to_id[seq]); - if c < 1000000 { - for j in 0..m.nrows() { - if row_is_cell[j] { - cell += m.value(j, c as usize); - } else { - ncell += m.value(j, c as usize); - } - } - } - if pass == 0 { - let r = 2 * i; - rows[r][3] = format!("{} {}", pr(cell, total), label); - csv_rows[r][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r][1] = "cellular".to_string(); - csv_rows[r][2] = "reference".to_string(); - csv_rows[r][3] = format!("{}", pr0(cell, total)); - csv_rows[r][4] = seq.clone(); - csv_rows[r][5] = seq_to_id[seq].clone(); - } else { - let r = 2 * (xr + xnr) + 2 * i; - rows[r][3] = format!("{} {}", pr(ncell, total), label); - csv_rows[r][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r][1] = "noncellular".to_string(); - csv_rows[r][2] = "reference".to_string(); - csv_rows[r][3] = format!("{}", pr0(ncell, total)); - csv_rows[r][4] = seq.clone(); - csv_rows[r][5] = seq_to_id[seq].clone(); - } - } - for i in 0..top_nref.len() { - let c = top_nref[i].0; - let seq = &top_nref[i].1; - let (mut cell, mut ncell) = (0, 0); - if c < 1000000 { - for j in 0..m.nrows() { - if row_is_cell[j] { - cell += m.value(j, c as usize); - } else { - ncell += m.value(j, c as usize); - } - } - } - if pass == 0 { - let r = 2 * (i + xr); - rows[r][3] = format!("{} {}", pr(cell, total), seq); - csv_rows[r][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r][1] = "cellular".to_string(); - csv_rows[r][2] = "nonreference".to_string(); - csv_rows[r][3] = format!("{}", pr0(cell, total)); - csv_rows[r][4] = seq.clone(); - } else { - let r = 2 * (xr + xnr) + 2 * (i + xr); - csv_rows[r][0] = ctl.origin_info.dataset_id[li].clone(); - csv_rows[r][1] = "noncellular".to_string(); - csv_rows[r][2] = "nonreference".to_string(); - csv_rows[r][3] = format!("{}", pr0(ncell, total)); - csv_rows[r][4] = seq.clone(); - rows[r][3] = format!("{} {}", pr(ncell, total), seq); - } - } - } - rows[xr - 1][2] = format!("{} reference", pr(cellular_ref, total)); - rows[2 * (xr + xnr) + xr - 1][2] = format!("{} reference", pr(ncellular_ref, total)); - rows[2 * xr + xnr - 1][2] = format!("{} nonreference", pr(cellular_nref, total)); - rows[2 * xr + 2 * (xr + xnr) + xnr - 1][2] = - format!("{} nonreference", pr(ncellular_nref, total)); - rows[xr + xnr - 1][1] = format!("{} cellular", pr(cellular_ref + cellular_nref, total)); - rows[2 * (xr + xnr) + xr + xnr - 1][1] = - format!("{} noncellular", pr(ncellular_ref + ncellular_nref, total)); - let mut display_text = String::new(); - print_tabular_vbox( - &mut display_text, - &rows, - 0, - &b"l|l|l|l".to_vec(), - false, - false, - ); - if !ctl.visual_mode && !ctl.gen_opt.vis_dump { - fwrite!( - res.3, - "\nfeature barcode UMI distribution for {}\n{}", - ctl.origin_info.dataset_id[li], - display_text - ); - } else { - let mut spreadsheet_text = String::new(); - for (i, r) in csv_rows.iter().enumerate() { - if i % 2 == 0 { - spreadsheet_text += &mut format!("{}\n", r.iter().format("\t ")); - } - } - let f = FeatureBarcodeAlluvialTable { - id: ctl.origin_info.dataset_id[li].clone(), - display_text: display_text.clone(), - spreadsheet_text: spreadsheet_text.clone(), - }; - res.2 = f; - } - } - }); - let mut have_some = false; - for i in 0..results.len() { - if results[i].1 { - have_some = true; - } - fs.push(results[i].2.clone()); - logx.append(&mut results[i].3.clone()); - } - if (ctl.visual_mode || ctl.gen_opt.vis_dump) && have_some { - let tables = FeatureBarcodeAlluvialTableSet { s: fs }; - logx.append(&mut tables.to_string().as_bytes().to_vec()); - } -} diff --git a/enclone_tail/src/print_stats.rs b/enclone_tail/src/print_stats.rs index 572fa90c32..ea462a5b1d 100644 --- a/enclone_tail/src/print_stats.rs +++ b/enclone_tail/src/print_stats.rs @@ -914,7 +914,5 @@ pub fn print_stats( if ctl.gen_opt.summary && !ctl.gen_opt.vis_dump { description_table(ctl, logx); - alluvial_fb_reads(ctl, gex_info, vdj_cells, logx); - alluvial_fb(ctl, gex_info, vdj_cells, logx); } } diff --git a/enclone_tail/src/tail.rs b/enclone_tail/src/tail.rs index 72b5d087f4..d5e67f04ac 100644 --- a/enclone_tail/src/tail.rs +++ b/enclone_tail/src/tail.rs @@ -169,39 +169,36 @@ pub fn tail_code( let p = bin_position(&gex_info.gex_barcodes[li], &bc); if p >= 0 { let mut raw_count = 0 as f64; - if gex_info.gex_matrices[li].initialized() { - raw_count = - gex_info.gex_matrices[li].value(p as usize, fid) as f64; + + let z1 = gex_info.h5_indptr[li][p as usize] as usize; + // p+1 OK? + let z2 = gex_info.h5_indptr[li][p as usize + 1] as usize; + let d: Vec; + let ind: Vec; + if ctl.gen_opt.h5_pre { + d = h5_data[li].1[z1..z2].to_vec(); + ind = h5_data[li].2[z1..z2].to_vec(); } else { - let z1 = gex_info.h5_indptr[li][p as usize] as usize; - // p+1 OK? - let z2 = gex_info.h5_indptr[li][p as usize + 1] as usize; - let d: Vec; - let ind: Vec; - if ctl.gen_opt.h5_pre { - d = h5_data[li].1[z1..z2].to_vec(); - ind = h5_data[li].2[z1..z2].to_vec(); - } else { - d = d_readers[li] - .as_ref() - .unwrap() - .read_slice(s![z1..z2]) - .unwrap() - .to_vec(); - ind = ind_readers[li] - .as_ref() - .unwrap() - .read_slice(s![z1..z2]) - .unwrap() - .to_vec(); - } - for j in 0..d.len() { - if ind[j] == fid as u32 { - raw_count = d[j] as f64; - break; - } + d = d_readers[li] + .as_ref() + .unwrap() + .read_slice(s![z1..z2]) + .unwrap() + .to_vec(); + ind = ind_readers[li] + .as_ref() + .unwrap() + .read_slice(s![z1..z2]) + .unwrap() + .to_vec(); + } + for j in 0..d.len() { + if ind[j] == fid as u32 { + raw_count = d[j] as f64; + break; } } + let mult: f64; if gene { mult = gex_info.gex_mults[li]; @@ -226,39 +223,35 @@ pub fn tail_code( let p = bin_position(&gex_info.gex_barcodes[li], &bc); if p >= 0 { let mut raw_count = 0 as f64; - if gex_info.gex_matrices[li].initialized() { - raw_count = - gex_info.gex_matrices[li].value(p as usize, fid) as f64; + let z1 = gex_info.h5_indptr[li][p as usize] as usize; + // p+1 OK? + let z2 = gex_info.h5_indptr[li][p as usize + 1] as usize; + let d: Vec; + let ind: Vec; + if ctl.gen_opt.h5_pre { + d = h5_data[li].1[z1..z2].to_vec(); + ind = h5_data[li].2[z1..z2].to_vec(); } else { - let z1 = gex_info.h5_indptr[li][p as usize] as usize; - // p+1 OK? - let z2 = gex_info.h5_indptr[li][p as usize + 1] as usize; - let d: Vec; - let ind: Vec; - if ctl.gen_opt.h5_pre { - d = h5_data[li].1[z1..z2].to_vec(); - ind = h5_data[li].2[z1..z2].to_vec(); - } else { - d = d_readers[li] - .as_ref() - .unwrap() - .read_slice(s![z1..z2]) - .unwrap() - .to_vec(); - ind = ind_readers[li] - .as_ref() - .unwrap() - .read_slice(s![z1..z2]) - .unwrap() - .to_vec(); - } - for j in 0..d.len() { - if ind[j] == fid as u32 { - raw_count = d[j] as f64; - break; - } + d = d_readers[li] + .as_ref() + .unwrap() + .read_slice(s![z1..z2]) + .unwrap() + .to_vec(); + ind = ind_readers[li] + .as_ref() + .unwrap() + .read_slice(s![z1..z2]) + .unwrap() + .to_vec(); + } + for j in 0..d.len() { + if ind[j] == fid as u32 { + raw_count = d[j] as f64; + break; } } + let mult: f64; if gene { mult = gex_info.gex_mults[li]; @@ -330,45 +323,6 @@ pub fn tail_code( print!("{}", strme(&log)); } - // Print top genes. - - if ctl.gen_opt.top_genes { - let mut results = Vec::<(f64, usize)>::new(); - let nf = gex_info.gex_features[0].len(); - for fid in 0..nf { - results.push((0.0, fid)); - } - results.par_iter_mut().for_each(|res| { - let fid = res.1; - let mut vals = Vec::::new(); - for i in 0..exacts.len() { - for m in 0..exacts[i].len() { - let ex = &exact_clonotypes[exacts[i][m]]; - for l in 0..ex.clones.len() { - let li = ex.clones[l][0].dataset_index; - let bc = ex.clones[l][0].barcode.clone(); - let p = bin_position(&gex_info.gex_barcodes[li], &bc); - if p >= 0 && gex_info.gex_matrices[li].initialized() { - let raw_count = gex_info.gex_matrices[li].value(p as usize, fid) as f64; - vals.push(raw_count); - } - } - } - } - vals.sort_by(|a, b| a.partial_cmp(b).unwrap()); - if !vals.is_empty() { - res.0 = median_f64(&vals); - } - }); - results.sort_by(|b, a| a.partial_cmp(b).unwrap()); - println!("\nTOP GENES"); - for i in 0..min(50, results.len()) { - let fid = results[i].1; - let count = results[i].0; - println!("[{}] {} = {}", i + 1, gex_info.gex_features[0][fid], count); - } - } - // Report time. ctl.perf_stats(&t, "in rest of tail code"); diff --git a/enclone_testlist/src/lib.rs b/enclone_testlist/src/lib.rs index 87ac93bfa7..423f7cad89 100644 --- a/enclone_testlist/src/lib.rs +++ b/enclone_testlist/src/lib.rs @@ -1,6 +1,7 @@ // Copyright (c) 2021 10X Genomics, Inc. All rights reserved. // Information about enclone tests. +pub mod main_testlist; pub fn enclone_testdata() -> String { include_str!["enclone.testdata"].to_string() @@ -166,7 +167,7 @@ pub const EXTENDED_TESTS: [&str; 12] = [ r###"BCR=47199,47200,47212 AMINO=cdr3 NCROSS LVARS=nd2 CDR3=CVKGKSGSFWYYFENW NO_PRE NFORCE"###, // 3. test sec and mem [requires samtools] - r###"BCR=123085 GEX=123217 LVARSP=sec,mem CDR3=CVKDRVTGTITELDYW H5"###, + r###"BCR=123085 GEX=123217 LVARSP=sec,mem CDR3=CVKDRVTGTITELDYW"###, // 4. crashed at one point r###"BCR=128037,128040 GEX=127798,127801 LVARSP=pe1 NOPRINT EXPECT_OK NO_PRE NFORCE"###, // @@ -213,18 +214,16 @@ pub const EXAMPLES: [&str; 2] = [ // 1. r###"BCR=123089 CDR3=CARRYFGVVADAFDIW"###, // 2. - // Do not use NH5 because the bin file is too big for git. - r###"BCR=123085 GEX=123217 H5 LVARSP=gex,IGHV2-5_g_μ CDR3=CALMGTYCSGDNCYSWFDPW"###, + r###"BCR=123085 GEX=123217 LVARSP=gex,IGHV2-5_g_μ CDR3=CALMGTYCSGDNCYSWFDPW"###, ]; // List of examples on site. pub const SITE_EXAMPLES: [(&str, &str); 28] = [ // 1. - // Do not use NH5 because the bin file is too big for git. ( "pages/auto/clonotype_with_gex.html", - "BCR=123085 CDR3=CTRDRDLRGATDAFDIW GEX=123217 H5 LVARSP=gex,IGHV3-49_g NUMI \ + "BCR=123085 CDR3=CTRDRDLRGATDAFDIW GEX=123217 LVARSP=gex,IGHV3-49_g NUMI \ HTML=\"enclone example with gex\"", ), // 2. @@ -297,7 +296,7 @@ pub const SITE_EXAMPLES: [(&str, &str); 28] = [ // 14. ( "img/two_genes.svg", - "BCR=123085 GEX=123217 NOPRINT PLOTXY_EXACT=HLA-A_g,CD74_g,stdout H5", + "BCR=123085 GEX=123217 NOPRINT PLOTXY_EXACT=HLA-A_g,CD74_g,stdout", ), // 15. ( @@ -351,7 +350,7 @@ pub const SITE_EXAMPLES: [(&str, &str); 28] = [ ( "img/sim_mat_plot.svg", "BCR=123085 GEX=123217 SIM_MAT_PLOT=stdout,CDKN1A_g,CDKN1B_g,RBX1_g,IGLC1_g,IGLV3-21_g \ - NOPRINT H5", + NOPRINT", ), // 24. ( diff --git a/enclone_exec/tests/main_testlist.rs b/enclone_testlist/src/main_testlist.rs similarity index 96% rename from enclone_exec/tests/main_testlist.rs rename to enclone_testlist/src/main_testlist.rs index f3066c5aab..cedee06e1f 100644 --- a/enclone_exec/tests/main_testlist.rs +++ b/enclone_testlist/src/main_testlist.rs @@ -32,7 +32,7 @@ pub const TESTS: [&str; 305] = [ CONST_IGH=IGHD"###, // 12. test colon lvar in KEEP_CLONO_IF_CELL_MEAN= and test for parsing error at + r###"BCR=86237 GEX=85679 LVARSP=g37:IGHV3-7_g_μ KEEP_CLONO_IF_CELL_MEAN="n + g37 >= 5.5" - MIN_CHAINS=2 NH5"###, + MIN_CHAINS=2"###, // 13. check TSV file with BC r###"BCR=123085 BC=testx/inputs/123077_cells.tsv PER_CELL LVARSP=T CDR3=CARGYEDFTMKYGMDVW"###, // 14. test cdr3_aa_conp @@ -45,7 +45,7 @@ pub const TESTS: [&str; 305] = [ // 17. tests gex with PER_CELL and tests n_gex // See also enclone_test_prebuild below, that tests nearly the same thing, // and tests versus the same output file. - r###"BCR=86237 GEX=85679 LVARSP=gex_max,gex,n_gex,CD19_ab_μ CELLS=3 PER_CELL NH5"###, + r###"BCR=86237 GEX=85679 LVARSP=gex_max,gex,n_gex,CD19_ab_μ CELLS=3 PER_CELL"###, // 18. makes sure cross filtering isn't applied to two origins from same donor r###"BCR=123085:123089 CDR3=CVRDEGGARPNKWNYEGAFDIW"###, // 19. there was a bug that caused a twosie to be deleted, and there was foursie junk @@ -73,7 +73,7 @@ pub const TESTS: [&str; 305] = [ r###"BCR=165807 BARCODE=CCCATACGTGATGATA-1,TCTATTGAGCTGAAAT-1"###, // 29. tests KEEP_CLONO_IF_CELL_MAX and parenthesized variable in it, SUM and MEAN, use of ≥ r###"BCR=123085 GEX=123217 LVARSP=IGHV3-7_g,IGHV3-7_g_μ - KEEP_CLONO_IF_CELL_MAX="(IGHV3-7_g_μ)≥10000.0" MIN_CHAINS=2 SUM MEAN H5"###, + KEEP_CLONO_IF_CELL_MAX="(IGHV3-7_g_μ)≥10000.0" MIN_CHAINS=2 SUM MEAN"###, // 30. tests d_univ and d_donor r###"BCR=123085 CVARSP=d_univ,d_donor CDR3=CVKDRVTGTITELDYW"###, // 31. tests Cell Ranger 3.1 output @@ -82,7 +82,7 @@ pub const TESTS: [&str; 305] = [ r###"BCR=../2.0/124550 CDR3=CAREPLYYDFWSAYFDYW RE ACCEPT_BROKEN"###, // 33. tests SCAN r###"BCR=123085 GEX=123217 LVARSP=IGHV1-69D_g_μ MIN_CELLS=10 NGEX - SCAN="(IGHV1-69D_g_μ)>=100,(IGHV1-69D_g_μ)<=1,t-10*c>=0.1" NOPRINT H5"###, + SCAN="(IGHV1-69D_g_μ)>=100,(IGHV1-69D_g_μ)<=1,t-10*c>=0.1" NOPRINT"###, // 34. tests honeycomb plot // (This yields a lot of output so will be annoying to debug if something changes.) r###"BCR=123085:123089 MIN_CELLS=10 PLOT="stdout,s1->red,s2->blue" NOPRINT @@ -107,17 +107,16 @@ pub const TESTS: [&str; 305] = [ CDR3=CAADGGGDQYYYMDVW"###, // 40. indel was wrong // Note that F is deprecated, equals KEEP_CLONO_IF_CELL_MEAN. Also test ⩾. - r###"BCR=86237 GEX=85679 LVARSP=IGHV3-7_g_μ F="(IGHV3-7_g_μ)⩾4.5" MIN_CHAINS=2 SUM MEAN - NH5"###, + r###"BCR=86237 GEX=85679 LVARSP=IGHV3-7_g_μ F="(IGHV3-7_g_μ)⩾4.5" MIN_CHAINS=2 SUM MEAN"###, // 41. test case for gex_cell - r###"BCR=86237 GEX=85679 CDR3=CAKAVAGKAVAGGWDYW POUT=stdouth PCOLS=gex_cell PCELL NH5"###, + r###"BCR=86237 GEX=85679 CDR3=CAKAVAGKAVAGGWDYW POUT=stdouth PCOLS=gex_cell PCELL"###, // 42. test case that should fail because gex_cell doesn't make sense without gex data r###"BCR=85333 CDR3=CQQRSNWPLYTF POUT=stdouth PCOLS=gex_cell PCELL PER_CELL EXPECT_FAIL"###, // 43. test case that should fail because _cell variables can't be used in LVARS r###"BCR=86237 GEX=85679 CDR3=CAKAVAGKAVAGGWDYW LVARS=gex_cell EXPECT_FAIL"###, // 44. test _cell r###"BCR=86237 GEX=85679 LVARSP=gex,RPS27_g_μ CELLS=3 POUT=stdouth - PCOLS=barcode,gex_cell,CD19_ab,CD19_ab_cell NH5 PCELL"###, + PCOLS=barcode,gex_cell,CD19_ab,CD19_ab_cell PCELL"###, // 45. test ndiff... r###"BCR=123085 CVARSP=ndiff1vj,ndiff2vj CDR3=CARDQNFDESSGYDAFDIW"###, // 46. test u_μ, u_min, r_μ, r_min and r_max @@ -126,8 +125,7 @@ pub const TESTS: [&str; 305] = [ // 47. this should fail r###"BCR=85333 CDR3=CAREEYYYDSSGDAFDIW LVARSP=gex_mean EXPECT_FAIL"###, // 48. test gex_mean and gex_Σ and NGEX - // Do not use NH5 because the bin file is too big for git. - r###"BCR=123085 GEX=123217 LVARSP=gex_mean,gex_Σ CDR3=CASRKSGNYIIYW NGEX H5"###, + r###"BCR=123085 GEX=123217 LVARSP=gex_mean,gex_Σ CDR3=CASRKSGNYIIYW NGEX"###, // 49. test HTML r###"BCR=85333 CDR3=CAAWDDSLNGWVF CHAINS=1 POUT=stdouth PCOLS=barcodes,n FASTA=stdout FASTA_AA=stdout HTML=CAAWDDSLNGWVF"###, @@ -136,13 +134,11 @@ pub const TESTS: [&str; 305] = [ // 51. make sure this fails gracefully r###"BCR=123085 PLOT=/nonexistent/broken.svg NOPRINT MIN_CELLS=50 EXPECT_FAIL"###, // 52. add test for some gene patterns - // Do not use NH5 because the bin file is too big for git. - r###"BCR=123085 GEX=123217 CDR3=CARPKSDYIIDAFDIW MIN_CELLS=10 H5 + r###"BCR=123085 GEX=123217 CDR3=CARPKSDYIIDAFDIW MIN_CELLS=10 LVARSP="(IGHV5-51|IGLV1-47)_g_%,IGH.*_g_%,IG(K|L).*_g_%""###, // 53. add test for _% with PER_CELL - // Do not use NH5 because the bin file is too big for git. r###"BCR=123085 GEX=123217 LVARSP="gex,n_gex,JCHAIN_g_%,IG%:IG.*_g_%" CVARS=u_μ,const - MIN_CHAINS_EXACT=2 CDR3=CAREGGVGVVTATDWYFDLW PER_CELL H5"###, + MIN_CHAINS_EXACT=2 CDR3=CAREGGVGVVTATDWYFDLW PER_CELL"###, // 54. make sure this fails gracefully r###"BCR=86237 GEX=85679 LVARSP=GERBULXXX123_g_% EXPECT_FAIL"###, // 55. test cred @@ -170,9 +166,8 @@ pub const TESTS: [&str; 305] = [ // 65. test NCELL r###"BCR=86237 NCELL CDR3=CAKTATTLGGYYSHGLDVW MIN_CELLS=2"###, // 66. test BC in combination with PER_CELL and PCELL - // Do not use NH5 because the bin file is too big for git. r###"BCR=123085 GEX=123217 BC=testx/inputs/123077_cells.csv PER_CELL LVARSP=gex,cred,T PCELL - POUT=stdouth PCOLS=barcode,T CDR3=CAKAGPTESGYYVWYFDLW MIN_CELLS=2 H5"###, + POUT=stdouth PCOLS=barcode,T CDR3=CAKAGPTESGYYVWYFDLW MIN_CELLS=2"###, // 67. expect fail if garbage PRE r###"PRE=garbage_gerbil_stuff BCR=86237 CELLS=3 EXPECT_FAIL NO_PRE"###, // 68. a test of PRE @@ -210,9 +205,8 @@ pub const TESTS: [&str; 305] = [ r###"BCR=86237 GEX=85679 CDR3=CARSFFGDTAMVMFQAFDPW POUT=stdouth PCELL PCOLS="barcode,IG:IG.*_g_%_cell,IG.*_g_%_cell,IGN:IG.*_g_%,IG.*_g_%""###, // 82. test entropy - // Do not use NH5 because the bin file is too big for git. r###"BCR=123085 GEX=123217 LVARSP=entropy PER_CELL POUT=stdouth PCELL - PCOLS=barcode,entropy,entropy_cell CDR3=CARAQRHDFWGGYYHYGMDVW H5"###, + PCOLS=barcode,entropy,entropy_cell CDR3=CARAQRHDFWGGYYHYGMDVW"###, // 83. test COMPLETE and dref r###"BCR=86237 CDR3=CARSFFGDTAMVMFQAFDPW COMPLETE LVARSP=dref"###, // 84. test CLUSTAL_AA @@ -228,12 +222,10 @@ pub const TESTS: [&str; 305] = [ // 89. test TREE and NEWICK r###"BCR=123085 COMPLETE TREE NEWICK CDR3=CARDLGGRYYGSKDPW"###, // 90. test KEEP_CELL_IF with non-null value - // Do not use NH5 because the bin file is too big for git. - r###"BCR=123085 GEX=123217 H5 BC=testx/inputs/123077_cells.csv PER_CELL LVARSP=gex,cred,T + r###"BCR=123085 GEX=123217 BC=testx/inputs/123077_cells.csv PER_CELL LVARSP=gex,cred,T CDR3=CARGYEDFTMKYGMDVW KEEP_CELL_IF="keeper == 'yes'""###, // 91. test FCELL with null value - // Do not use NH5 because the bin file is too big for git. - r###"BCR=123085 GEX=123217 H5 BC=testx/inputs/123077_cells.csv PER_CELL LVARSP=gex,cred,T + r###"BCR=123085 GEX=123217 BC=testx/inputs/123077_cells.csv PER_CELL LVARSP=gex,cred,T CDR3=CARGYEDFTMKYGMDVW FCELL="keeper == ''""###, // 92. test NALL_CELL r###"BCR=123085 NALL_CELL CDR3=CQKYDSAPLTF MIN_CELLS=20"###, @@ -463,9 +455,9 @@ pub const TESTS: [&str; 305] = [ // 193. check that this fails gracefully r###"NOPRINT EXPECT_FAIL"###, // 194. this crashed at one point - r###"BCR=86237 GEX=85679 LVARSP=g37:IGHV3-7_g_μ NH5 POUT=stdout PCOLS=g37 EXPECT_OK"###, + r###"BCR=86237 GEX=85679 LVARSP=g37:IGHV3-7_g_μ POUT=stdout PCOLS=g37 EXPECT_OK"###, // 195. failed at one point - r###"BCR=86237 GEX=85679 LVARSP=woof:IGHV3-7_g_μ NH5 POUT=stdout PCOLS=woof EXPECT_OK"###, + r###"BCR=86237 GEX=85679 LVARSP=woof:IGHV3-7_g_μ POUT=stdout PCOLS=woof EXPECT_OK"###, // 196. test TREE=n r###"BCR=123085 COMPLETE TREE=n CDR3=CARDLGGRYYGSKDPW"###, // 197. failed at one point @@ -477,7 +469,7 @@ pub const TESTS: [&str; 305] = [ KEEP_CLONO_IF_CELL_MEAN="moo>0""###, // 200. test SCAN_EXACT r###"BCR=123085 GEX=123217 LVARSP=IGHV1-69D_g_μ,IGHV3-64D_g_μ MIN_CELLS=10 - SCAN="(IGHV1-69D_g_μ)>=1800,(IGHV3-64D_g_μ)>=100,t-10*c>=5.0" NOPRINT H5 SCAN_EXACT"###, + SCAN="(IGHV1-69D_g_μ)>=1800,(IGHV3-64D_g_μ)>=100,t-10*c>=5.0" NOPRINT SCAN_EXACT"###, // 201. test SOURCE r###"SOURCE=testx/inputs/123085_args AMINO=cdr2,cdr3"###, // 202. DUPLICATE TO REPLACE @@ -492,7 +484,7 @@ pub const TESTS: [&str; 305] = [ PCOLS=moo LVARS=moo PCELL PER_CELL"###, // 205. test g with PER_CELL and PCELL r###"BCR=123085 GEX=123217 AMINO=cdr3 LVARS=g15 CDR3=CARVRDILTGDYGMDVW POUT=stdout PCOLS=g15 - PCELL PER_CELL H5"###, + PCELL PER_CELL"###, // 206. test origins with PER_CELL and PCELL r###"BCR=123085:123089 AMINO= CDR3=CTRAGFLSYQLLSYYYYGMDVW FOLD_HEADERS POUT=stdout PCELL PER_CELL PCOLS=origins LVARSP=origins"###, @@ -515,13 +507,13 @@ pub const TESTS: [&str; 305] = [ CDR3=CSAGQGDTEAFF"###, // 213. test cred with PER_CELL and PCELL r###"BCR=123085 GEX=123217 AMINO=cdr3 LVARS=cred CVARS=u POUT=stdout PCOLS=cred,cred_cell - PCELL PER_CELL H5 CDR3=CARDPEDIVLMVYAMGGNYGMDVW"###, + PCELL PER_CELL CDR3=CARDPEDIVLMVYAMGGNYGMDVW"###, // 214. test n_ with PER_CELL and PCELL r###"BCR=123085:123089 AMINO=cdr3 FOLD_HEADERS POUT=stdout PCELL PER_CELL PCOLS=n_s1 LVARS=datasets,n_s1 CDR3=CARDLFVLVPAAITYYYGMDVW CVARS=u"###, // 215. test n_gex with PER_CELL and PCELL r###"BCR=123085 GEX=123217 AMINO=cdr3 LVARS=n_gex POUT=stdout PCOLS=n_gex,n_gex_cell PCELL - PER_CELL H5 CDR3=CAKDKVPRRSSWSVFDYYGMDVW"###, + PER_CELL CDR3=CAKDKVPRRSSWSVFDYYGMDVW"###, // 216. test near with PER_CELL and PCELL r###"BCR=123085 AMINO=cdr3 POUT=stdout PCELL PER_CELL LVARSP=near PCOLS=near CVARS=u CDR3=CARHLQWELPYW"###, @@ -539,7 +531,7 @@ pub const TESTS: [&str; 305] = [ PCOLS=cdr3_aa_conp2 CVARS=cdr3_aa_conp"###, // 221. test RPS27_g with PER_CELL and PCELL r###"BCR=123085 GEX=123217 AMINO=cdr3 POUT=stdout PCOLS=RPS27_g,RPS27_g_cell PCELL - PER_CELL H5 CDR3=CAREVEQWLERNTLDYW LVARSP=RPS27_g"###, + PER_CELL CDR3=CAREVEQWLERNTLDYW LVARSP=RPS27_g"###, // // OTHER TESTS // @@ -557,7 +549,7 @@ pub const TESTS: [&str; 305] = [ // MORE TESTS OF PER_CELL AND PCELL // // 226. test RPS27_g_mean with PER_CELL and PCELL - r###"BCR=123085 GEX=123217 AMINO=cdr3 POUT=stdout PCOLS=RPS27_g_mean PCELL PER_CELL H5 + r###"BCR=123085 GEX=123217 AMINO=cdr3 POUT=stdout PCOLS=RPS27_g_mean PCELL PER_CELL CDR3=CAREVEQWLERNTLDYW LVARSP=RPS27_g_mean CVARS=u"###, // 227. test datasets, donors, origins with PER_CELL and PCELL r###"BCR=123085:123089 CELLS=5 AMINO= CDR3=CTRAGFLSYQLLSYYYYGMDVW FOLD_HEADERS POUT=stdout @@ -577,10 +569,10 @@ pub const TESTS: [&str; 305] = [ // 231. test ≤ r###"BCR=86237 KEEP_CLONO_IF_CELL_MEAN="u2≤150" NOPRINT SUMMARY SUMMARY_CLEAN"###, // 232. test nonsense variable in linear constraint - r###"BCR=86237 KEEP_CLONO_IF_CELL_MAX="gexzz > 8000" EXPECT_FAIL H5"###, + r###"BCR=86237 KEEP_CLONO_IF_CELL_MAX="gexzz > 8000" EXPECT_FAIL"###, // 233. test use of two linear constraints r###"BCR=123085 GEX=123217 - KEEP_CLONO_IF_CELL_MAX="gex > 8000" KEEP_CLONO_IF_CELL_MAX="gex < 8200" H5"###, + KEEP_CLONO_IF_CELL_MAX="gex > 8000" KEEP_CLONO_IF_CELL_MAX="gex < 8200" "###, // 234. test tooltip comments; this is via a testing-only filename option gui_stdout r###"BCR=123085 MIN_CELLS=10 PLOT_BY_ISOTYPE=gui_stdout NOPRINT MIN_CHAINS_EXACT=2"###, // 235. test that v_name etc. do not appear in parseable output if chain is absent @@ -596,7 +588,7 @@ pub const TESTS: [&str; 305] = [ // 240. test sym option for PLOTXY_EXACT r###"BCR=123085 PLOTXY_EXACT=u1,u2,stdout,sym NOPRINT"###, // 241. test KEEP_CELL_IF on gex var - r###"BCR=123085 GEX=123217 LVARSP=IGHM_g KEEP_CELL_IF="IGHM_g>=10" CDR3=CARRYFGVVADAFDIW H5"###, + r###"BCR=123085 GEX=123217 LVARSP=IGHM_g KEEP_CELL_IF="IGHM_g>=10" CDR3=CARRYFGVVADAFDIW"###, // 242. test nchains_present r###"BCR=86237 LVARSP=nchains_present CDR3=CARSFFGDTAMVMFQAFDPW"###, // 243. this crashed at one point @@ -674,8 +666,8 @@ pub const TESTS: [&str; 305] = [ // 268. a test of VAR_DEF r###"BCR=86237 GEX=85679 VAR_DEF="pink:PINK1-AS_g" LVARSP=pink CDR3=CARSFFGDTAMVMFQAFDPW FOLD_HEADERS PER_CELL AMINO="###, - // 269. test fb variables - r###"BCR=86237 GEX=85679 ALLOW_INCONSISTENT NGEX LVARSP=fb1,fb1_n PER_CELL AMINO=cdr3 CVARS= FOLD_HEADERS POUT=stdouth PCOLS=fb2,fb2_n,fb2_n_cell PCELL CDR3=CARSFFGDTAMVMFQAFDPW"###, + // 269. used to test fb variables, now duplicating test 270 since this feature has been deleted + r###"BCR=123085 CDR3=CTRDRDLRGATDAFDIW AMINO=cdr3,fwr4 NOSPACES CONX"###, // 270. test NOSPACES r###"BCR=123085 CDR3=CTRDRDLRGATDAFDIW AMINO=cdr3,fwr4 NOSPACES CONX"###, // 271. test for weird path bug diff --git a/enclone_tools/Cargo.toml b/enclone_tools/Cargo.toml index f642f1cfae..d67328ebdc 100644 --- a/enclone_tools/Cargo.toml +++ b/enclone_tools/Cargo.toml @@ -42,7 +42,6 @@ fs_extra = "1" io_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } itertools = "0.10" lz4 = "1" -mirror_sparse_matrix = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } perf_stats = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } pretty_trace = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main", features = ["pprof"]} rand_chacha = "0.3" diff --git a/enclone_tools/src/bin/copy_for_enclone.rs b/enclone_tools/src/bin/copy_for_enclone.rs deleted file mode 100644 index 6007695f9a..0000000000 --- a/enclone_tools/src/bin/copy_for_enclone.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// copy_for_enclone SOURCE=... TARGET=... - -use enclone_tools::copy_for_enclone::copy_for_enclone; -use pretty_trace::PrettyTrace; -use string_utils::*; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = std::env::args().collect(); - let mut source = String::new(); - let mut target = String::new(); - for i in 1..args.len() { - if args[i].starts_with("SOURCE=") { - source = args[i].after("SOURCE=").to_string(); - } else if args[i].starts_with("TARGET=") { - target = args[i].after("TARGET=").to_string(); - } else { - eprint!("\nUnknown arg.\n"); - std::process::exit(1); - } - } - assert!(source.len() > 0); - assert!(target.len() > 0); - copy_for_enclone(&source, &target); -} diff --git a/enclone_tools/src/bin/import_data.rs b/enclone_tools/src/bin/import_data.rs deleted file mode 100644 index 6da1933611..0000000000 --- a/enclone_tools/src/bin/import_data.rs +++ /dev/null @@ -1,356 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Takes a single argument: a comma-separated list of ids, allowing hyphenated ranges. Copy these -// to the internal collections. If it has already been copied, it is moved aside, and at the end, -// deleted (assuming that the copy did not fail. -// -// You need to set quota first on the second internal location. -// -// This is probably not fully consistent with current pipeline structure. -// -// Run make_enclone_testlist_all after this to update the catalog. -// -// Optional second argument: FB_INFO: do nothing except attempt to create the -// feature barcode matrix. -// -// Optional second argument: FB_INFO_WRITE: do nothing except attempt to create the -// feature barcode matrix and write the corresponding files. -// -// For use at 10x Genomics. - -use enclone_core::defs::get_config; -use enclone_testlist::TEST_FILES_VERSION; -use enclone_tools::copy_for_enclone::copy_for_enclone; -use enclone_tools::feature_barcode_matrix::{ - feature_barcode_matrix, feature_barcode_matrix_seq_def, SequencingDef, -}; -use io_utils::{fwriteln, open_for_read, open_for_write_new, path_exists}; -use itertools::Itertools; -use mirror_sparse_matrix::write_to_file; -use pretty_trace::PrettyTrace; -use serde_json::Value; -use std::collections::HashMap; -use std::env; -use std::fs::{copy, remove_dir_all, rename, File}; -use std::io::{BufRead, Write}; -use std::process::Command; -use string_utils::{parse_csv, TextUtils}; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - println!("in import_data, args = {}", args[1..].iter().format(" ")); - let mut fb_info = false; - let mut fb_info_write = false; - let mut verbosity = 0; - for i in 2..args.len() { - if args[i] == "FB_INFO" { - fb_info = true; - } else if args[i] == "FB_INFO_WRITE" { - fb_info_write = true; - } else if args[i].starts_with("VERBOSITY=") { - verbosity = args[i].after("VERBOSITY=").force_usize(); - } else { - eprintln!("\nIllegal arg.\n"); - std::process::exit(1); - } - } - let mut config = HashMap::::new(); - let mut config_file = String::new(); - for (key, value) in env::vars() { - if key == "ENCLONE_CONFIG" { - config_file = value.to_string(); - if config_file.contains(',') { - config_file = config_file.after(",").to_string(); - } - } - } - let _ = get_config(&config_file, &mut config); - let mut dests = Vec::::new(); - dests.push(format!("{}/current{}", config["earth"], TEST_FILES_VERSION)); - dests.push(format!("{}/current{}", config["cloud"], TEST_FILES_VERSION)); - let ids0 = args[1].split(',').collect::>(); - let mut ids = Vec::::new(); - for id in ids0.iter() { - if id.contains('-') { - let start = id.before("-").force_usize(); - let stop = id.after("-").force_usize(); - for p in start..=stop { - ids.push(format!("{}", p)); - } - } else { - ids.push(id.to_string()); - } - } - let ones = &config["ones"]; - for id in ids.iter() { - // Get path. - - let mut p = id.clone(); - assert!(p.parse::().is_ok()); - let url = format!("{}/{}", ones, p); - let o = Command::new("curl") - .arg(&url) - .output() - .expect("failed to execute http"); - let m = String::from_utf8(o.stdout).unwrap(); - if m.contains("502 Bad Gateway") { - eprintln!( - "\nWell this is sad. The URL \ - {} yielded a 502 Bad Geteway \ - message. Either try again later or ask someone for help.\n\n", - url, - ); - std::process::exit(1); - } - if m.contains("\"path\":\"") { - let path = m.between("\"path\":\"", "\"").to_string(); - p = format!("{}/outs", path); - if !path_exists(&p) { - eprintln!( - "\nIt looks like you've provided an id {} for \ - which\nthe pipeline outs folder has not yet been \ - generated.\n\n", - p - ); - std::process::exit(1); - } - } else { - eprintln!( - "\nIt looks like you've provided either an incorrect \ - id {} or else one for which\n\ - the pipeline outs folder has not yet been generated.\n\n", - p - ); - std::process::exit(1); - } - - // Punt if the count pipeline appears to have succeeded but actually failed. - - if path_exists(&format!("{}/../SC_RNA_COUNTER_PD", p)) - && !path_exists(&format!("{}/analysis", p)) - { - println!( - "\nNo analysis directory found for\n{}\nso the outs directory is \ - incomplete, possibly because there were not enough reads. Giving up.\n", - p - ); - continue; - } - - // Move directories if they exist. - - let mut moved = false; - if !fb_info && !fb_info_write { - for dest in dests.iter() { - if path_exists(&format!("{}/{}", dest, id)) { - if path_exists(&format!("{}/{}.aside", dest, id)) { - eprintln!("\nPlease remove {}/{}.aside.\n", dest, id); - std::process::exit(1); - } - rename( - &format!("{}/{}", dest, id), - &format!("{}/{}.aside", dest, id), - ) - .unwrap(); - moved = true; - } - } - } - - // Start copy. - - if !fb_info && !fb_info_write { - println!("copying {} using path = {}", id, p); - for i in (0..dests.len()).rev() { - let dest = &dests[i]; - let target = format!("{}/{}", dest, id); - if path_exists(&target) { - eprintln!("\nPlease delete {}.\n", target); - std::process::exit(1); - } - copy_for_enclone(&format!("{}/..", p), &target); - } - } - - // Determine if the feature barcode matrix for the top feature barcodes should be - // generated, and if so, what id to use. - - let mut seq_def = None; - if path_exists(&format!("{}/../SC_RNA_COUNTER_PD", p)) { - seq_def = feature_barcode_matrix_seq_def(id.force_usize()); - } else if path_exists(&format!("{}/../SC_MULTI_PD", p)) { - let mut sample_indices = Vec::::new(); - let mut lanes = Vec::::new(); - let read_path; - { - let mut antibody_seq_id = None; - let inv = format!("{}/../_invocation", p); - let f = open_for_read![&inv]; - let mut lines = Vec::::new(); - for line in f.lines() { - let s = line.unwrap(); - lines.push(s); - } - for i in 0..lines.len() { - let fields = parse_csv(&lines[i]); - if fields.len() >= 5 - && (fields[4] == "Antibody Capture" || fields[4] == "Antigen Capture") - { - antibody_seq_id = Some(fields[3].force_usize()); - break; - } - } - if antibody_seq_id.is_some() { - let antibody_seq_id = antibody_seq_id.unwrap(); - let pid = m.between("\"pipestance_id\":\"", "\"").to_string(); - let meta = &config["meta"]; - let url = format!("{}/{}", meta, pid); - println!("getting data for {} from {}", antibody_seq_id, url); - let o = Command::new("curl") - .arg(&url) - .output() - .expect("failed to execute curl for meta"); - let mm = String::from_utf8(o.stdout).unwrap(); - let v: Value = serde_json::from_str(&mm).unwrap(); - let asi = format!("{}", antibody_seq_id); - let rrr = &v["sample_bag"]["sequencing_libraries"][&asi]; - let lane = &rrr["metadata"]["lane"]; - let lane = lane.to_string().between("\"", "\"").to_string(); - let lane = lane.split(',').collect::>(); - for x in lane.iter() { - lanes.push(x.force_usize()); - } - let si_data = rrr["sample_indexes"].as_array().unwrap(); - for j in 0..si_data.len() { - sample_indices.push( - si_data[j]["seq"] - .to_string() - .between("\"", "\"") - .to_string(), - ); - } - let flowcell = rrr["sequencing_run"]["name"] - .to_string() - .between("\"", "\"") - .to_string(); - read_path = v["fastq_paths"][&flowcell] - .to_string() - .between("\"", "\"") - .to_string(); - seq_def = Some(SequencingDef { - read_path, - sample_indices, - lanes, - }); - } - } - } - - // Build feature barcode matrix for top feature barcodes. - - if seq_def.is_some() { - // Get list of antibody reference feature barcodes. - - let mut ref_fb = Vec::::new(); - { - let mut f = format!("{}/multi/count/feature_reference.csv", p); - if !path_exists(&f) { - let g = open_for_read![&format!("{}/../_invocation", p)]; - for line in g.lines() { - let s = line.unwrap(); - if s.contains("feature_reference") { - f = s.between("\"", "\"").to_string(); - } - } - } - for i in (0..dests.len()).rev() { - let dest = &dests[i]; - let target = format!("{}/{}", dest, id); - copy(&f, &format!("{}/outs/feature_reference.csv", target)).unwrap(); - } - let f = open_for_read![&f]; - let mut seq_pos = 0; - for (i, line) in f.lines().enumerate() { - let s = line.unwrap(); - let fields = parse_csv(&s); - if i == 0 { - for j in 0..fields.len() { - if fields[j] == "sequence" { - seq_pos = j; - } - } - } else { - ref_fb.push(fields[seq_pos].to_string()); - } - } - } - ref_fb.sort(); - - // Keep going. - - let verb = std::cmp::max(1, verbosity); - let x = feature_barcode_matrix(&seq_def.unwrap(), id.force_usize(), verb, &ref_fb); - if fb_info { - std::process::exit(0); - } - if x.is_ok() { - let (m, total, brn, m_reads, total_reads, brnr, bdcs) = x.unwrap(); - for i in (0..dests.len()).rev() { - let dest = &dests[i]; - let target = format!("{}/{}", dest, id); - write_to_file( - &m, - &format!("{}/outs/feature_barcode_matrix_top.bin", target), - ); - write_to_file( - &m_reads, - &format!("{}/outs/feature_barcode_matrix_top_reads.bin", target), - ); - let mut f = - File::create(&format!("{}/outs/feature_barcode_matrix_top.total", target)) - .unwrap(); - f.write_all(&total.to_ne_bytes()).unwrap(); - let mut f = File::create(&format!( - "{}/outs/feature_barcode_matrix_top.total_reads", - target - )) - .unwrap(); - f.write_all(&total_reads.to_ne_bytes()).unwrap(); - let mut f = open_for_write_new![&format!( - "{}/outs/feature_barcode_matrix_top.brn", - target - )]; - for j in 0..brn.len() { - fwriteln!(f, "{},{},{}", brn[j].0, brn[j].1, brn[j].2); - } - let mut f = open_for_write_new![&format!( - "{}/outs/feature_barcode_matrix_top.brnr", - target - )]; - for j in 0..brnr.len() { - fwriteln!(f, "{},{},{}", brnr[j].0, brnr[j].1, brnr[j].2); - } - let mut f = open_for_write_new![&format!( - "{}/outs/feature_barcode_matrix_top.bdcs", - target - )]; - for j in 0..bdcs.len() { - fwriteln!(f, "{},{},{},{}", bdcs[j].0, bdcs[j].1, bdcs[j].2, bdcs[j].3); - } - } - } - } - - // Remove moved directories. - - if moved { - for dest in dests.iter() { - let movedir = format!("{}/{}.aside", dest, id); - if path_exists(&movedir) { - remove_dir_all(&movedir).unwrap(); - } - } - } - } -} diff --git a/enclone_tools/src/bin/merge_html.rs b/enclone_tools/src/bin/merge_html.rs index 8059249324..402e40c75d 100644 --- a/enclone_tools/src/bin/merge_html.rs +++ b/enclone_tools/src/bin/merge_html.rs @@ -21,10 +21,9 @@ use vector_utils::{bin_member, unique_sort}; pub const SITE_EXAMPLES: [(&str, &str); 28] = [ // 1. - // Do not use NH5 because the bin file is too big for git. ( "pages/auto/clonotype_with_gex.html", - "BCR=123085 CDR3=CTRDRDLRGATDAFDIW GEX=123217 H5 LVARSP=gex,IGHV3-49_g NUMI \ + "BCR=123085 CDR3=CTRDRDLRGATDAFDIW GEX=123217 LVARSP=gex,IGHV3-49_g NUMI \ HTML=\"enclone example with gex\"", ), // 2. @@ -97,7 +96,7 @@ pub const SITE_EXAMPLES: [(&str, &str); 28] = [ // 14. ( "img/two_genes.svg", - "BCR=123085 GEX=123217 NOPRINT PLOTXY_EXACT=HLA-A_g,CD74_g,stdout H5", + "BCR=123085 GEX=123217 NOPRINT PLOTXY_EXACT=HLA-A_g,CD74_g,stdout", ), // 15. ( @@ -151,7 +150,7 @@ pub const SITE_EXAMPLES: [(&str, &str); 28] = [ ( "img/sim_mat_plot.svg", "BCR=123085 GEX=123217 SIM_MAT_PLOT=stdout,CDKN1A_g,CDKN1B_g,RBX1_g,IGLC1_g,IGLV3-21_g \ - NOPRINT H5", + NOPRINT", ), // 24. ( diff --git a/enclone_tools/src/bin/pdb_test.rs b/enclone_tools/src/bin/pdb_test.rs index 17d059e123..12818265a2 100644 --- a/enclone_tools/src/bin/pdb_test.rs +++ b/enclone_tools/src/bin/pdb_test.rs @@ -56,7 +56,7 @@ pub fn fetch_atoms(pdb: &PdbStructure, chain: usize, seq: &[u8]) -> Vec<[f32; 3] } } eprintln!("fetch_atoms failed"); - std::process::exit(1); + panic!("failed"); } pub fn mean_dist(a: &Vec<[f32; 3]>, b: &Vec<[f32; 3]>) -> f32 { @@ -138,7 +138,7 @@ fn main() { "\nFailed to find EGFN in spike:\n{}.\n", strme(&pdb.chains[spike]) ); - std::process::exit(1); + panic!("failed"); } // Find SASFSTF in the spike. diff --git a/enclone_tools/src/bin/review_main_tests.rs b/enclone_tools/src/bin/review_main_tests.rs index e8102cb0ee..f857d37c8f 100644 --- a/enclone_tools/src/bin/review_main_tests.rs +++ b/enclone_tools/src/bin/review_main_tests.rs @@ -6,7 +6,7 @@ // NOTE: you have to run this from the enclone_main directory. Otherwise it won't work. use enclone::misc1::setup_pager; -use enclone_core::main_testlist::TESTS; +use enclone_testlist::main_testlist::TESTS; use enclone_tools::run_test::run_test; use pretty_trace::PrettyTrace; use rayon::prelude::*; diff --git a/enclone_tools/src/bin/run_last_test.rs b/enclone_tools/src/bin/run_last_test.rs index a77990d8a4..cd59b64a0d 100644 --- a/enclone_tools/src/bin/run_last_test.rs +++ b/enclone_tools/src/bin/run_last_test.rs @@ -4,7 +4,7 @@ // // Note that this gives the wrong answer if you haven't run ./build first. -use enclone_core::main_testlist::TESTS; +use enclone_testlist::main_testlist::TESTS; use enclone_tools::run_test::run_test; use pretty_trace::PrettyTrace; diff --git a/enclone_tools/src/bin/update_all_main_tests.rs b/enclone_tools/src/bin/update_all_main_tests.rs index bf1b3186f2..666ff1117d 100644 --- a/enclone_tools/src/bin/update_all_main_tests.rs +++ b/enclone_tools/src/bin/update_all_main_tests.rs @@ -7,7 +7,7 @@ // // NOTE: you have to run this from the enclone_main directory. Otherwise it won't work. -use enclone_core::main_testlist::TESTS; +use enclone_testlist::main_testlist::TESTS; use enclone_tools::run_test::run_test; use io_utils::{fwrite, open_for_write_new}; use pretty_trace::PrettyTrace; diff --git a/enclone_tools/src/copy_for_enclone.rs b/enclone_tools/src/copy_for_enclone.rs deleted file mode 100644 index b618922b29..0000000000 --- a/enclone_tools/src/copy_for_enclone.rs +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -// Copy a 10x pipestance, retaining only the files used by enclone, or which might otherwise -// be convenient to keep. - -use enclone_core::slurp::slurp_h5; -use io_utils::{dir_list, path_exists}; -use lz4::EncoderBuilder; -use mirror_sparse_matrix::{write_to_file, MirrorSparseMatrix}; -use std::fs::{copy, remove_file, File}; -use vector_utils::VecUtils; - -fn copy_if(f: &str, g: &str) { - if path_exists(&f) { - copy(f, g).unwrap(); - } -} - -fn copy_file(f: &str, dir1: &str, dir2: &str) { - let x = copy(&format!("{}/{}", dir1, f), &format!("{}/{}", dir2, f)); - if x.is_err() { - eprintln!("\nFailed to copy {} from\n{}\nto {}.\n", f, dir1, dir2); - } - x.unwrap(); -} - -fn mkdir(d: &str) { - let x = std::fs::create_dir(&d); - if x.is_err() { - eprintln!("\nCan't make directory {}.\n", d); - } - x.unwrap(); -} - -fn mkdirp(d: &str) { - std::fs::create_dir_all(&d).unwrap(); -} - -fn compress(source: &str, destination: &str) { - let mut input_file = File::open(source).unwrap(); - let output_file = File::create(destination).unwrap(); - let mut encoder = EncoderBuilder::new().level(4).build(output_file).unwrap(); - std::io::copy(&mut input_file, &mut encoder).unwrap(); - let _ = encoder.finish(); -} - -fn lz4_file(f: &str) { - compress(f, &format!("{}.lz4", f)); - remove_file(&f).unwrap(); -} - -pub fn copy_for_enclone(source: &str, target: &str) { - let p = format!("{}/outs", source); - - // Define most of the gex files to be copied. - - let gex_files = [ - // "barcode_correction_csv.csv", // don't know why this was here - // "barcode_summary.h5", // don't know why this was here - "filtered_barcodes.csv", - "filtered_feature_bc_matrix.h5", - "gene_properties.json", - "metrics_summary_csv.csv", - "metrics_summary_json.json", - // "per_barcode_metrics.csv", // don't know why this was here - "per_feature_metrics.csv", - "web_summary.html", - "web_summary_pd.html", - ] - .to_vec(); - - // Copy VDJ. - - if path_exists(&format!("{}/all_contig_annotations.json", p)) { - mkdirp(&format!("{}/outs", target)); - - // Copy and compress all_contig_annotations.json. - - let json_target = format!("{}/outs/all_contig_annotations.json", target); - copy(&format!("{}/all_contig_annotations.json", p), &json_target).unwrap(); - lz4_file(&json_target); - - // Copy _invocation and _log. - - copy( - &format!("{}/../_invocation", p), - &format!("{}/_invocation", target), - ) - .unwrap(); - copy_if(&format!("{}/../_log", p), &format!("{}/_log", target)); - - // Copy these two files used for Immcantation. - - copy_if( - &format!("{}/filtered_contig_annotations.csv", p), - &format!("{}/outs/filtered_contig_annotations.csv", target), - ); - copy_if( - &format!("{}/filtered_contig.fasta", p), - &format!("{}/outs/filtered_contig.fasta", target), - ); - - // Copy these files that are nice to have. - - copy_if( - &format!("{}/cell_barcodes.json", p), - &format!("{}/outs/cell_barcodes.json", target), - ); - copy( - &format!("{}/metrics_summary_json.json", p), - &format!("{}/outs/metrics_summary_json.json", target), - ) - .unwrap(); - - // Copy GEX. - } else if path_exists(&format!("{}/raw_feature_bc_matrix.h5", p)) - || path_exists(&format!("{}/raw_gene_bc_matrices_h5.h5", p)) - { - mkdirp(&format!("{}/outs", target)); - - // Copy _invocation. - - copy( - &format!("{}/../_invocation", p), - &format!("{}/_invocation", target), - ) - .unwrap(); - - // Copy h5 file, allowing for older-named version. - - let f; - if path_exists(&format!("{}/raw_feature_bc_matrix.h5", p)) { - f = "raw_feature_bc_matrix.h5"; - } else { - f = "raw_gene_bc_matrices_h5.h5"; - } - let h5_target = format!("{}/outs/{}", target, f); - copy(&format!("{}/{}", p, f), &h5_target).unwrap(); - - // Generate feature_barcode_matrix.bin. - - let mut barcodes = Vec::::new(); - let mut features = Vec::::new(); - let mut matrix = Vec::>::new(); - slurp_h5(&h5_target, true, &mut barcodes, &mut features, &mut matrix).unwrap(); - let msm = MirrorSparseMatrix::build_from_vec(&matrix, &barcodes, &features); - let bin_file = format!("{}/outs/feature_barcode_matrix.bin", target); - write_to_file(&msm, &bin_file); - - // Copy other files in outs. - - for f in gex_files.iter() { - if path_exists(&format!("{}/{}", p, f)) { - copy(&format!("{}/{}", p, f), &format!("{}/outs/{}", target, f)).unwrap(); - } - } - - // Copy subdirectories of outs. - - { - use fs_extra::dir::{copy, CopyOptions}; - let opt = CopyOptions::new(); - let mut d = "filtered_feature_bc_matrix"; - if !path_exists(&format!("{}/{}", p, d)) { - d = "filtered_gene_bc_matrices_mex"; - } - copy(&format!("{}/{}", p, d), &format!("{}/outs", target), &opt).unwrap(); - let dirs = vec!["analysis".to_string(), "analysis_csv".to_string()]; - for d in dirs.iter() { - copy(&format!("{}/{}", p, d), &format!("{}/outs", target), &opt).unwrap(); - } - } - - // Copy multi. - } else if path_exists(&format!("{}/multi", p)) - && (path_exists(&format!("{}/count", p)) || path_exists(&format!("{}/count_pd", p))) - { - let count; - if path_exists(&format!("{}/count_pd", p)) { - count = "count_pd"; - } else { - count = "count"; - } - mkdirp(&format!("{}/outs/multi", target)); - mkdir(&format!("{}/outs/{}", target, count)); - std::fs::copy( - &format!("{}/../_invocation", p), - &format!("{}/_invocation", target), - ) - .unwrap(); - std::fs::copy(&format!("{}/../_log", p), &format!("{}/_log", target)).unwrap(); - for vdj in ["vdj_b", "vdj_t"].iter() { - let vdj_from = format!("{}/multi/{}", p, vdj); - if path_exists(&vdj_from) { - let vdj_to = format!("{}/outs/multi/{}", target, vdj); - mkdir(&vdj_to); - let json_target = format!("{}/all_contig_annotations.json", vdj_to); - copy_file("all_contig_annotations.json", &vdj_from, &vdj_to); - lz4_file(&json_target); - } - } - if path_exists(&format!("{}/outs/multi/count", target)) { - let count_to = format!("{}/outs/multi/count", target); - mkdir(&count_to); - let count_from = format!("{}/count", p); - copy_file("raw_feature_bc_matrix.h5", &count_from, &count_to); - } - if path_exists(&format!("{}/vdj_reference", p)) { - mkdirp(&format!("{}/outs/vdj_reference/fasta", target)); - let ref_from = format!("{}/vdj_reference", p); - let ref_to = format!("{}/outs/vdj_reference", target); - copy_file("reference.json", &ref_from, &ref_to); - let fasta_from = format!("{}/vdj_reference/fasta", p); - let fasta_to = format!("{}/outs/vdj_reference/fasta", target); - copy_file("regions.fa", &fasta_from, &fasta_to); - } - - let summary = format!("{}/multi_web_summary_json/metrics_summary_csv", p); - if path_exists(&summary) { - let summary_out = format!("{}/outs/multi_web_summary_json/metrics_summary_csv", target); - mkdirp(&summary_out); - let list = dir_list(&summary); - for f in list.iter() { - copy_file(f, &summary, &summary_out); - } - } - - let mut gex_files = gex_files.clone(); - gex_files.push("raw_feature_bc_matrix.h5"); - let count_pd_from = format!("{}/{}", p, count); - let count_pd_to = format!("{}/outs/{}", target, count); - for f in gex_files.iter() { - if path_exists(&format!("{}/{}", count_pd_from, f)) { - copy_file(f, &count_pd_from, &count_pd_to); - } - } - - // Generate feature_barcode_matrix.bin. - - let h5_target = format!("{}/raw_feature_bc_matrix.h5", count_pd_to); - let mut barcodes = Vec::::new(); - let mut features = Vec::::new(); - let mut matrix = Vec::>::new(); - slurp_h5(&h5_target, true, &mut barcodes, &mut features, &mut matrix).unwrap(); - let msm = MirrorSparseMatrix::build_from_vec(&matrix, &barcodes, &features); - let bin_file = format!("{}/feature_barcode_matrix.bin", count_pd_to); - write_to_file(&msm, &bin_file); - - // Copy more. - - use fs_extra::dir::{copy, CopyOptions}; - let opt = CopyOptions::new(); - let dirs = ["filtered_feature_bc_matrix", "analysis_csv"]; - for d in dirs.iter() { - copy( - &format!("{}/{}/{}", p, count, d), - &format!("{}/outs/{}", target, count), - &opt, - ) - .unwrap(); - } - - // Delete some stuff. Yeah dumb to copy then delete. - - let diffexp = format!("{}/outs/{}/analysis_csv/diffexp", target, count); - if path_exists(&diffexp) { - std::fs::remove_dir_all(&diffexp).unwrap(); - } - let filt_h5 = format!("{}/outs/{}/filtered_feature_bc_matrix.h5", target, count); - if path_exists(&filt_h5) { - std::fs::remove_file(&filt_h5).unwrap(); - } - let filt_dir = format!("{}/outs/{}/filtered_feature_bc_matrix", target, count); - if path_exists(&filt_dir) { - std::fs::remove_dir_all(&filt_dir).unwrap(); - } - - // Copy per_sample_outs. - - if path_exists(&format!("{}/per_sample_outs", p)) { - let list = dir_list(&format!("{}/per_sample_outs", p)); - if list.solo() { - let x = &list[0]; - let pso = format!("per_sample_outs/{}", x); - let mut d = format!("{}/count/analysis", pso); - if !path_exists(&format!("{}/{}", p, d)) { - d = format!("{}/count/analysis_csv", pso); - } - mkdirp(&format!("{}/outs/{}", target, d)); - copy( - &format!("{}/{}", p, d), - &format!("{}/outs/{}/count", target, pso), - &opt, - ) - .unwrap(); - for vdj in ["vdj_b", "vdj_t"].iter() { - let sdir = format!("{}/{}/{}", p, pso, vdj); - if path_exists(&format!("{}/filtered_contig.fasta", sdir)) { - let tdir = format!("{}/outs/{}/{}", target, pso, vdj); - mkdirp(&tdir); - copy_file("filtered_contig.fasta", &sdir, &tdir); - copy_file("filtered_contig_annotations.csv", &sdir, &tdir); - } - } - } - } - - // Copy new dir structure. - } else if path_exists(&format!("{}/count", p)) || path_exists(&format!("{}/count_pd", p)) { - let count; - if path_exists(&format!("{}/count_pd", p)) { - count = "count_pd"; - } else { - count = "count"; - } - mkdirp(&format!("{}/outs/{}", target, count)); - std::fs::copy( - &format!("{}/../_invocation", p), - &format!("{}/_invocation", target), - ) - .unwrap(); - std::fs::copy(&format!("{}/../_log", p), &format!("{}/_log", target)).unwrap(); - for vdj in ["vdj_b", "vdj_t"].iter() { - let vdj_from = format!("{}/{}", p, vdj); - if path_exists(&vdj_from) { - let vdj_to = format!("{}/outs/{}", target, vdj); - mkdir(&vdj_to); - let json_target = format!("{}/all_contig_annotations.json", vdj_to); - copy_file("all_contig_annotations.json", &vdj_from, &vdj_to); - lz4_file(&json_target); - } - } - if path_exists(&format!("{}/vdj_reference", p)) { - mkdirp(&format!("{}/outs/vdj_reference/fasta", target)); - let ref_from = format!("{}/vdj_reference", p); - let ref_to = format!("{}/outs/vdj_reference", target); - copy_file("reference.json", &ref_from, &ref_to); - let fasta_from = format!("{}/vdj_reference/fasta", p); - let fasta_to = format!("{}/outs/vdj_reference/fasta", target); - copy_file("regions.fa", &fasta_from, &fasta_to); - } - let mut gex_files = gex_files.clone(); - gex_files.push("raw_feature_bc_matrix.h5"); - let count_pd_from = format!("{}/{}", p, count); - let count_pd_to = format!("{}/outs/{}", target, count); - for f in gex_files.iter() { - if path_exists(&format!("{}/{}", count_pd_from, f)) { - copy_file(f, &count_pd_from, &count_pd_to); - } - } - - // Generate feature_barcode_matrix.bin. - - let h5_target = format!("{}/raw_feature_bc_matrix.h5", count_pd_to); - let mut barcodes = Vec::::new(); - let mut features = Vec::::new(); - let mut matrix = Vec::>::new(); - slurp_h5(&h5_target, true, &mut barcodes, &mut features, &mut matrix).unwrap(); - let msm = MirrorSparseMatrix::build_from_vec(&matrix, &barcodes, &features); - let bin_file = format!("{}/feature_barcode_matrix.bin", count_pd_to); - write_to_file(&msm, &bin_file); - - // Copy more. - - use fs_extra::dir::{copy, CopyOptions}; - let opt = CopyOptions::new(); - let dirs = ["filtered_feature_bc_matrix", "analysis_csv"]; - for d in dirs.iter() { - copy( - &format!("{}/{}/{}", p, count, d), - &format!("{}/outs/{}", target, count), - &opt, - ) - .unwrap(); - } - - // Or something is wrong. - } else { - eprintln!( - "\nThe directory {} is not a complete VDJ or GEX or MULTI directory.\n", - p - ); - std::process::exit(1); - } -} diff --git a/enclone_tools/src/feature_barcode_matrix.rs b/enclone_tools/src/feature_barcode_matrix.rs deleted file mode 100644 index 81ab56451f..0000000000 --- a/enclone_tools/src/feature_barcode_matrix.rs +++ /dev/null @@ -1,789 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. -// -// Input = id (integer). -// -// Create a cell barcode x feature barcode matrix for the most frequent barcodes. -// 1. Extract {cell barcode, umi, feature barcode} for each read. -// 2. For a given {cell barcode, umi}, pick the most frequent feature barcode. -// 3. Report data for only the top 100 feature barcodes. -// 4. List the barcodes in order by frequency. -// -// Also compute several other statistical entities. - -use chrono::prelude::*; -use enclone_core::defs::get_config; -use enclone_core::fetch_url; -use flate2::read::MultiGzDecoder; -use io_utils::{dir_list, path_exists}; -use itertools::Itertools; -use mirror_sparse_matrix::MirrorSparseMatrix; -use perf_stats::*; -use rayon::prelude::*; -use serde_json::Value; -use stats_utils::*; -use std::collections::HashMap; -use std::env; -use std::fs; -use std::fs::File; -use std::io::{BufRead, BufReader, Read}; -use std::time::Instant; -use string_utils::{stringme, strme, TextUtils}; -use vector_utils::*; - -pub struct SequencingDef { - pub read_path: String, - pub sample_indices: Vec, - pub lanes: Vec, -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn feature_barcode_matrix_seq_def(id: usize) -> Option { - println!("getting feature barcode matrix for {}", id); - - // Get configuration. - - let mut config = HashMap::::new(); - let mut config_file = String::new(); - for (key, value) in env::vars() { - if key == "ENCLONE_CONFIG" { - config_file = value.to_string(); - if config_file.contains(',') { - config_file = config_file.after(",").to_string(); - } - } - } - let _ = get_config(&config_file, &mut config); - - // Get pipestance path. - - let url = format!("{}/{}", config["ones"], id); - let m = fetch_url(&url).unwrap(); - if m.contains("502 Bad Gateway") { - eprintln!( - "\nWell, this is sad. The URL \ - {} returned a 502 Bad Gateway \ - message. Please try again later or ask someone for help.\n", - url - ); - std::process::exit(1); - } - let v: Value = serde_json::from_str(&m).unwrap(); - let latest = &v["latest_analysis_run"]; - let pipestance = latest["path"].to_string().between("\"", "\"").to_string(); - - // Get read path and lanes and sample indices from the invocation file. - - let invocation = format!("{}/_invocation", pipestance); - if !path_exists(&invocation) { - eprintln!("\n_invocation does not exist for {}\n", pipestance); - std::process::exit(1); - } - let mut read_path = String::new(); // path to reads - let mut si = Vec::::new(); // sample indices - let mut lanes = Vec::::new(); // lanes - { - let mut f = File::open(&invocation).unwrap(); - let mut bytes = Vec::::new(); - f.read_to_end(&mut bytes).unwrap(); - let mut sample_def = Vec::::new(); - let mut bracks: isize = 0; - for i in 0..bytes.len() { - if bytes[i] == b'[' { - bracks += 1; - } else if bytes[i] == b']' { - bracks -= 1; - } - if bracks > 0 { - sample_def.push(bytes[i]); - } else if bracks == 0 && !sample_def.is_empty() { - sample_def.append(&mut b"]\n".to_vec()); - break; - } - } - let mut sample_def = stringme(&sample_def); - sample_def = sample_def.replace(",\n }", "\n }"); - let mut sample_def = format!( - "{}{}", - sample_def.rev_before(","), - sample_def.rev_after(",") - ); - - // Remove some trailing commas to get proper json. - - let mut chars = Vec::::new(); - for char in sample_def.chars() { - chars.push(char); - } - let mut to_delete = vec![false; chars.len()]; - for i in 0..chars.len() { - if chars[i] == ',' { - for j in i + 1..chars.len() { - if chars[j] == ' ' || chars[j] == '\n' { - } else if chars[j] == ']' { - to_delete[i] = true; - } else { - break; - } - } - } - } - sample_def.clear(); - for i in 0..chars.len() { - if !to_delete[i] { - sample_def.push(chars[i]); - } - } - - // Convert string to json. - - let v: Result = serde_json::from_str(&sample_def); - if v.is_err() { - println!("\nsample_def = $$${}$$$", sample_def); - } - let v = v.unwrap(); - let sample_defx = &v.as_array().unwrap(); - for x in sample_defx.iter() { - if x["library_type"] == "Antibody Capture" || x["library_type"] == "Antigen Capture" { - read_path = x["read_path"].to_string().between("\"", "\"").to_string(); - let y = x["sample_indices"].as_array().unwrap().to_vec(); - for i in 0..y.len() { - // Manually converting one case for backward compatibility. Could use a - // full table if needed. - if y[i] == "SI-P01-E1" { - si.push("CGCCCGTA".to_string()); - si.push("GTTTGCCT".to_string()); - si.push("TAAGTTAG".to_string()); - si.push("ACGAAAGC".to_string()); - } else { - si.push(y[i].to_string()); - } - } - let y = x["lanes"].as_array().unwrap().to_vec(); - for i in 0..y.len() { - lanes.push(y[i].to_string().force_usize()); - } - } - } - for i in 0..si.len() { - if si[i].contains("\"") { - si[i] = si[i].between("\"", "\"").to_string(); - } - } - if read_path.is_empty() { - println!("\nfailed to find read path, presumably because there's no antibody data\n"); - println!("(this is probably ok)\n"); - return None; - } - if !path_exists(&read_path) { - eprintln!("\nread path does not exist"); - std::process::exit(1); - } - } - if lanes.is_empty() { - eprintln!("\nfailed to find lanes\n"); - std::process::exit(1); - } - let attr = fs::metadata(&read_path).unwrap(); - if !attr.is_dir() { - eprintln!("\nread path is not a directory\n"); - std::process::exit(1); - } - - let seq_def = SequencingDef { - read_path, - sample_indices: si, - lanes, - }; - Some(seq_def) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// This computes a feature barcode matrix and several other statistical entities: -// -// 1 = MirrorSparseMatrix -// • rows = cell barcodes -// • columns = frequent feature barcodes -// • entries = number of UMIs -// -// 2 = u64 = "total UMIs" = total number of pairs (cell barcode, UMI) observed -// -// 3 = Vec<(String, u32, u32)> = for each cell barcode the number of UMIs whose feature barcode -// is reference, and the number whose feature barcode is nonreference. -// -// 4 = MirrorSparseMatrix -// • rows = cell barcodes -// • columns = frequent feature barcodes -// • entries = number of nondegenerate reads -// -// 5 = u64 = total number of reads (meaning as usual, read pairs) -// -// 6 = Vec<(String, u32, u32)> = for each cell barcode the number of nondegenerate reads whose -// feature barcode is reference, and the number whose feature barcode is nonreference. -// -// 7 = Vec<(String, u32, u32, u32)> = for each cell barcode the number of degenerate reads, -// the number of those that are canonical, and the number of those that are semicanonical. - -pub fn feature_barcode_matrix( - seq_def: &SequencingDef, - id: usize, - verbosity: usize, - ref_fb: &Vec, -) -> Result< - ( - MirrorSparseMatrix, - u64, - Vec<(String, u32, u32)>, - MirrorSparseMatrix, - u64, - Vec<(String, u32, u32)>, - Vec<(String, u32, u32, u32)>, - ), - String, -> { - let t = Instant::now(); - - // Find the read files. - - let mut read_files = Vec::::new(); - let x = dir_list(&seq_def.read_path); - if verbosity > 0 { - println!(); - } - for f in x.iter() { - for sample_index in seq_def.sample_indices.iter() { - for lane in seq_def.lanes.iter() { - if f.starts_with(&format!("read-RA_si-{}_lane-00{}-", sample_index, lane)) { - if verbosity > 0 { - println!("{}", f); - } - if f.ends_with("__evap") { - eprintln!( - "\nfound an evaporated read file =\n{}\n", - format!("{}/{}", seq_def.read_path, f), - ); - std::process::exit(1); - } - read_files.push(f.clone()); - } - } - } - } - if read_files.is_empty() { - eprintln!("\nreads do not exist"); - eprintln!("read path =\n{}", seq_def.read_path); - eprintln!( - "sample indices = {}", - seq_def.sample_indices.iter().format(",") - ); - eprintln!("lanes = {}", seq_def.lanes.iter().format(",")); - eprintln!("filename structure = read-RA_si-_lane-00-\n"); - std::process::exit(1); - } - - // Report what we found. - - if verbosity > 0 { - println!("\nread path = {}", seq_def.read_path); - println!("lanes = {}", seq_def.lanes.iter().format(",")); - println!( - "sample indices = {}", - seq_def.sample_indices.iter().format(",") - ); - println!("used {:.1} seconds\n", elapsed(&t)); - } - - // A read pair is called degenerate if the first ten bases of R2 are GGGGGGGGGG. - // The following sequence is the 22-base end of the // Illumina Nextera-version of - // the R2 primer = CTGTCTCTTATACACATCTCCGAGCCCACGAGAC. We call a read pair canonical if it - // is degenerate and R1 contains the 22-base sequence, and semicanonical if it does not, but - // does contain the first ten bases of it. - - let canonical = b"CACATCTCCGAGCCCACGAGAC".to_vec(); // 22 bases - - // Traverse the reads. - - println!("start parsing reads for {}", id); - let mut buf = Vec::>::new(); // {barcode_umi_fb} - // let mut buf = Vec::<(Vec, Vec, Vec)>::new(); // {(barcode, umi, fb)} - let mut bdcs = Vec::<(String, u32, u32, u32)>::new(); - let (mut ncanonical, mut nsemicanonical) = (0, 0); - let mut ndegen = 0; - for pass in 1..=2 { - let mut degen = Vec::<(Vec, Vec)>::new(); // {(barcode, umi)} - if verbosity > 0 { - println!("megapass {}", pass); - } - for (i, rf) in read_files.iter().enumerate() { - let local: DateTime = Local::now(); - let local = format!("{:?}", local); - let time = local.between("T", "."); - if verbosity > 0 { - println!( - "- at {}, processing dataset {} of {}; buf has size {} and degen has size {}", - time, - i + 1, - read_files.len(), - buf.len(), - degen.len() - ); - } - let f = format!("{}/{}", seq_def.read_path, rf); - let gz = MultiGzDecoder::new(File::open(&f).unwrap()); - let b = BufReader::new(gz); - - // Paired reads are in groups of eight lines. Line 2 is the cell barcode-umi read, - // and line 6 is the read that contains the feature barcode. - - let mut count = 0; - let mut barcode = Vec::::new(); - let mut umi = Vec::::new(); - let mut read1 = Vec::::new(); - let mut fb; - for line in b.lines() { - count += 1; - if count % 8 == 2 || count % 8 == 6 { - let s = line.unwrap(); - let s = s.as_bytes(); - if count % 8 == 2 { - if s.len() < 28 { - return Err(format!( - "\nencountered read of length {} < 28 in {}\n", - s.len(), - f - )); - } - assert!(s.len() >= 28); - barcode = s[0..16].to_vec(); - umi = s[16..28].to_vec(); - read1 = s.to_vec(); - } else { - fb = s[10..25].to_vec(); - let mut degenerate = true; - for i in 0..10 { - if s[i] != b'G' { - degenerate = false; - break; - } - } - - // Save. - - if verbosity == 2 { - let (mut is_canonical, mut is_semicanonical) = (false, false); - if degenerate { - for j in 0..=read1.len() - canonical.len() { - if read1[j..j + canonical.len()] == canonical { - is_canonical = true; - break; - } - } - } - if degenerate && !is_canonical { - for i in 0..18 { - let mut w = true; - for j in 0..10 { - if read1[i + j] != canonical[j] { - w = false; - break; - } - } - if w { - is_semicanonical = true; - break; - } - } - } - print!( - "r: {} {} {} {} {} {}", - strme(&barcode), - strme(&umi), - strme(&s[0..10]), - strme(&fb), - strme(&s[25..35]), - strme(&s[35..55]), - ); - if is_canonical { - print!(" = canon"); - } else if is_semicanonical { - print!(" = semi"); - } - println!(""); - } - if degenerate && pass == 1 { - degen.push((barcode.clone(), umi.clone())); - } else if pass == 2 { - let mut x = barcode.clone(); - x.append(&mut umi.clone()); - x.append(&mut fb.clone()); - buf.push(x); - } - } - } - } - } - - // Build data structure for the degenerate reads. - - if pass == 1 { - if verbosity > 0 { - println!("parallel sorting"); - } - degen.par_sort(); - if verbosity > 0 { - println!("build data structure for degenerate reads"); - } - let mut i = 0; - while i < degen.len() { - let j = next_diff1_2(°en, i as i32) as usize; - let (mut canon, mut semi) = (0, 0); - for k in i..j { - let mut read1 = degen[k].0.clone(); - read1.append(&mut degen[k].1.clone()); - let mut is_canonical = false; - for j in 0..=read1.len() - canonical.len() { - if read1[j..j + canonical.len()] == canonical { - is_canonical = true; - canon += 1; - ncanonical += 1; - break; - } - } - if !is_canonical { - for i in 0..18 { - let mut w = true; - for j in 0..10 { - if read1[i + j] != canonical[j] { - w = false; - break; - } - } - if w { - semi += 1; - nsemicanonical += 1; - break; - } - } - } - } - bdcs.push((stringme(°en[i].0), (j - i) as u32, canon, semi)); - i = j; - } - ndegen = degen.len(); - drop(degen); - } - } - - // Print summary stats. - - let total_reads = ndegen + buf.len(); - if verbosity > 0 { - println!("there are {} read pairs", total_reads); - println!( - "of which {:.1}% are degenerate", - percent_ratio(ndegen, total_reads) - ); - let canonical_percent = 100.0 * ncanonical as f64 / total_reads as f64; - println!("canonical fraction = {:.1}%", canonical_percent); - let semicanonical_percent = 100.0 * nsemicanonical as f64 / total_reads as f64; - println!("semicanonical fraction = {:.1}%", semicanonical_percent); - println!("\nused {:.1} seconds\n", elapsed(&t)); - } - - // Find the most common feature barcodes, by read count. - - let mut fbs = Vec::>::new(); - for i in 0..buf.len() { - fbs.push(buf[i][28..43].to_vec()); - } - fbs.par_sort(); - let mut fb_freq = Vec::<(u32, Vec)>::new(); - make_freq(&fbs, &mut fb_freq); - drop(fbs); - const TOP_FEATURE_BARCODES: usize = 100; - if fb_freq.len() > TOP_FEATURE_BARCODES { - fb_freq.truncate(TOP_FEATURE_BARCODES); - } - let mut fb_freq_sorted = Vec::>::new(); - for i in 0..fb_freq.len() { - fb_freq_sorted.push(fb_freq[i].1.clone()); - } - let mut ids_ffs = Vec::::new(); - for i in 0..fb_freq_sorted.len() { - ids_ffs.push(i); - } - sort_sync2(&mut fb_freq_sorted, &mut ids_ffs); - - // Generate a feature-barcode matrix for the common feature barcodes, by read count. Also, - // make a table of all barcodes, and for each, the number of reference and nonreference reads. - - if verbosity > 0 { - println!("making mirror sparse matrix, by read counts"); - } - let mut bf = Vec::<(Vec, Vec)>::new(); - for i in 0..buf.len() { - bf.push((buf[i][0..16].to_vec(), buf[i][28..43].to_vec())); - } - bf.par_sort(); - let mut brnr = Vec::<(String, u32, u32)>::new(); - let mut x = Vec::>::new(); - let mut row_labels = Vec::::new(); - let mut col_labels = Vec::::new(); - for z in fb_freq.iter() { - col_labels.push(stringme(&z.1)); - } - if verbosity > 0 { - println!("start making m_reads, used {:.1} seconds", elapsed(&t)); - } - let mut i = 0; - while i < bf.len() { - let j = next_diff1_2(&bf, i as i32) as usize; - let mut y = Vec::<(i32, i32)>::new(); - let mut k = i; - while k < j { - let l = next_diff(&bf, k); - let p = bin_position(&fb_freq_sorted, &bf[k].1); - if p >= 0 { - y.push((ids_ffs[p as usize] as i32, (l - k) as i32)); - } - k = l; - } - if !y.is_empty() { - row_labels.push(format!("{}-1", strme(&bf[i].0))); - x.push(y); - } - let (mut refx, mut nrefx) = (0, 0); - for k in i..j { - if bin_member(ref_fb, &stringme(&bf[k].1)) { - refx += 1; - } else { - nrefx += 1; - } - } - brnr.push((stringme(&bf[i].0), refx, nrefx)); - i = j; - } - drop(bf); - let m_reads = MirrorSparseMatrix::build_from_vec(&x, &row_labels, &col_labels); - if verbosity > 0 { - println!("after making m_reads, used {:.1} seconds", elapsed(&t)); - } - - // Sort buf. - - buf.par_sort(); - - // Reduce buf to UMI counts. - - let mut bfu = Vec::>::new(); // {barcode_fb_umi} - let mut singletons = 0; - let mut i = 0; - while i < buf.len() { - let mut j = i + 1; - while j < buf.len() { - if buf[j][0..28] != buf[i][0..28] { - break; - } - j += 1; - } - let mut sing = true; - if i > 0 && buf[i][0..16] == buf[i - 1][0..16] { - sing = false; - } - if i < buf.len() - 1 && buf[i][0..16] == buf[i + 1][0..16] { - sing = false; - } - if sing { - singletons += 1; - } - let mut bfs = Vec::::new(); - for k in i..j { - bfs.push(stringme(&buf[k][28..43].to_vec())); - } - let mut uniq = true; - for k in i + 1..j { - if buf[k][28..43] != buf[k - 1][28..43] { - uniq = false; - } - } - if uniq { - let mut x = buf[i][0..16].to_vec(); - x.append(&mut buf[i][28..43].to_vec()); - x.append(&mut buf[i][16..28].to_vec()); - bfu.push(x); - } else { - // Sloppy, just take the most frequent feature barcode, ignoring quality scores. - let mut fs = Vec::>::new(); - for k in i..j { - fs.push(buf[k][28..43].to_vec()); - } - fs.sort(); - let mut freq = Vec::<(u32, Vec)>::new(); - make_freq(&fs, &mut freq); - let mut x = buf[i][0..16].to_vec(); - x.append(&mut freq[0].1.clone()); - x.append(&mut buf[i][16..28].to_vec()); - bfu.push(x); - } - i = j; - } - drop(buf); - bfu.par_sort(); - - // Make table of all barcodes, and for each, the number of reference and nonreference UMIs. - - let mut brn = Vec::<(String, u32, u32)>::new(); - let mut i = 0; - while i < bfu.len() { - let mut j = i + 1; - while j < bfu.len() { - if bfu[j][0..16] != bfu[i][0..16] { - break; - } - j += 1; - } - let mut refx = 0; - let mut nrefx = 0; - for k in i..j { - if bin_member(ref_fb, &stringme(&bfu[k][16..31])) { - refx += 1; - } else { - nrefx += 1; - } - } - brn.push((stringme(&bfu[i][0..16]), refx, nrefx)); - i = j; - } - - // Proceed. - - if verbosity > 0 { - let singleton_percent = 100.0 * singletons as f64 / total_reads as f64; - println!("singleton fraction = {:.1}%", singleton_percent); - let mut bc = 0; - let mut i = 0; - while i < bfu.len() { - let mut j = i + 1; - while j < bfu.len() { - if bfu[j][0..16] != bfu[i][0..16] { - break; - } - j += 1; - } - bc += 1; - i = j; - } - println!("total barcodes = {}", bc); - } - let mut bfn = Vec::<(Vec, Vec, usize)>::new(); // {(barcode, fb, numis)} - let mut i = 0; - while i < bfu.len() { - let mut j = i + 1; - while j < bfu.len() { - if bfu[j][0..31] != bfu[i][0..31] { - break; - } - j += 1; - } - let mut n = 1; - for k in i + 1..j { - if bfu[k][31..43] != bfu[k - 1][31..43] { - n += 1; - } - } - bfn.push((bfu[i][0..16].to_vec(), bfu[i][16..31].to_vec(), n)); - i = j; - } - if verbosity > 0 { - println!("there are {} uniques", bfu.len()); - println!("\nused {:.1} seconds\n", elapsed(&t)); - } - let mut total_umis = 0; - for i in 0..bfn.len() { - total_umis += bfn[i].2 as u64; - } - if verbosity > 0 { - println!("total UMIs = {}\n", total_umis); - } - - // Report common feature barcodes, by UMI count. - - if verbosity > 0 { - println!("common feature barcodes and their total UMI counts\n"); - } - let mut fbx = Vec::>::new(); - for i in 0..bfu.len() { - fbx.push(bfu[i][16..31].to_vec()); - } - drop(bfu); - if verbosity > 0 { - println!("parallel sorting fbx"); - } - fbx.par_sort(); - let mut freq = Vec::<(u32, Vec)>::new(); - make_freq(&fbx, &mut freq); - drop(fbx); - if verbosity > 0 { - for i in 0..10 { - println!("{} = {}", strme(&freq[i].1), freq[i].0); - } - } - let mut tops = Vec::>::new(); - for i in 0..std::cmp::min(TOP_FEATURE_BARCODES, freq.len()) { - tops.push(freq[i].1.clone()); - } - let mut tops_sorted = tops.clone(); - let mut ids = Vec::::new(); - for i in 0..tops.len() { - ids.push(i); - } - sort_sync2(&mut tops_sorted, &mut ids); - if verbosity > 0 { - println!("\nused {:.1} seconds\n", elapsed(&t)); - } - - // Generate a feature-barcode matrix for the common feature barcodes, by UMI count. - - if verbosity > 0 { - println!("making mirror sparse matrix"); - } - let mut x = Vec::>::new(); - let mut row_labels = Vec::::new(); - let mut col_labels = Vec::::new(); - for x in tops.iter() { - col_labels.push(stringme(x)); - } - let mut i = 0; - while i < bfn.len() { - let j = next_diff1_3(&bfn, i as i32) as usize; - let mut y = Vec::<(i32, i32)>::new(); - for k in i..j { - let p = bin_position(&tops_sorted, &bfn[k].1); - if p >= 0 { - y.push((ids[p as usize] as i32, bfn[k].2 as i32)); - } - } - if !y.is_empty() { - row_labels.push(format!("{}-1", strme(&bfn[i].0))); - x.push(y); - } - i = j; - } - drop(bfn); - if verbosity > 0 { - println!("building last mirror sparse matrix"); - } - let m = MirrorSparseMatrix::build_from_vec(&x, &row_labels, &col_labels); - if verbosity > 0 { - println!("used {:.1} seconds\n", elapsed(&t)); - #[cfg(not(target_os = "windows"))] - { - println!( - "peak mem usage for feature barcode matrix = {:.1} GB\n", - peak_mem_usage_gb() - ); - } - } - Ok((m, total_umis, brn, m_reads, total_reads as u64, brnr, bdcs)) -} diff --git a/enclone_tools/src/html.rs b/enclone_tools/src/html.rs index 1546ae1921..ac02865eeb 100644 --- a/enclone_tools/src/html.rs +++ b/enclone_tools/src/html.rs @@ -136,8 +136,6 @@ pub fn insert_html(in_file: &str, out_file: &str, up: bool, level: usize) { const ENCLONE_FORMATTED: &str = "enclone"; - const ENCLONE_VISUAL_FORMATTED: &str = - "enclone visual"; let pwd = env::current_dir().unwrap(); let pwd = pwd.to_str().unwrap(); let mut title = String::new(); @@ -238,7 +236,6 @@ pub fn insert_html(in_file: &str, out_file: &str, up: bool, level: usize) { fwriteln!(g, "{}", s); } } else { - s = s.replace("#enclone_visual", ENCLONE_VISUAL_FORMATTED); s = s.replace("#enclone", ENCLONE_FORMATTED); s = s.replace("#required_fps", &format!("{}", required_fps)); s = s.replace("#required_cells", &add_commas(required_cells)); diff --git a/enclone_tools/src/lib.rs b/enclone_tools/src/lib.rs index b900043e55..cdd0501960 100644 --- a/enclone_tools/src/lib.rs +++ b/enclone_tools/src/lib.rs @@ -1,7 +1,5 @@ // Copyright (c) 2021 10x Genomics, Inc. All rights reserved. -pub mod copy_for_enclone; -pub mod feature_barcode_matrix; pub mod html; pub mod pdb; pub mod run_test; diff --git a/enclone_tools/src/run_test.rs b/enclone_tools/src/run_test.rs index 5667756e5f..df2ca7cec5 100644 --- a/enclone_tools/src/run_test.rs +++ b/enclone_tools/src/run_test.rs @@ -118,25 +118,6 @@ pub fn run_test( } let args = parse_bsv(&test); - // Try to prevent a sporadic failure mode. - - let (mut p1, mut p2) = (false, false); - for i in 0..args.len() { - if args[i] == "GEX=123217" { - p1 = true; - } else if args[i] == "H5" { - p2 = true; - } - } - if p1 && !p2 { - eprintln!( - "\nFound GEX=123217 without H5. Because of the PREBUILD test, this \ - can cause sporadic failures.\nHere is the test:\n{}\n", - orig_test - ); - std::process::exit(1); - } - // Form the command and execute it. let mut new = Command::new(&enclone); @@ -327,7 +308,7 @@ pub fn run_test( // version, args[0].after("=") ); // if !path_exists(&f) { // println!( "Perhaps you forgot to lz4 compress the json file.\n" ); - // std::process::exit(1); + // panic!("failed"); // } // println!( "The size of {} is {} bytes.", f, fs::metadata(&f).unwrap().len() ); diff --git a/enclone_visual/Cargo.toml b/enclone_visual/Cargo.toml deleted file mode 100644 index 2867bd48f8..0000000000 --- a/enclone_visual/Cargo.toml +++ /dev/null @@ -1,86 +0,0 @@ -[package] -name = "enclone_visual" -version = "0.5.219" -authors = ["""David Jaffe , - Nigel Delaney , - Keri Dockter , - Jessica Hamel , - Lance Hepler , - Shaun Jackman , - Sreenath Krishnan , - Meryl Lewis , - Alvin Liang , - Patrick Marks , - Wyatt McDonnell """] -edition = "2018" -license-file = "LICENSE.txt" -publish = false - -# Please do not edit crate versions within this file. Instead edit the file master.toml -# in the root of the enclone repo. - -# [[bin]] -# name = "enclone" -# path = "src/bin/enclone.rs" - -[dependencies] -anyhow = "1" -base64 = "0.13" -chrono = { version = "0.4", default-features = false, features = ["std", "clock"] } -crc = "2" -dirs = "4" -enclone_core = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -enclone_main = { path = "../enclone_main" } -enclone_stuff = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -enclone_tail = { path = "../enclone_tail" } -enclone_version = { path = "../enclone_version" } -enclone_build = { path = "../enclone_build" } - -flate2 = "1" -fs_extra = "1" -home = "0.5" -iced = { git = "https://github.com/hecrj/iced", rev = "3042fa2cb63c651ebed2abe6f4054e61f70b0331", features = ["canvas", "image", "async-std"] } -iced_native = { git = "https://github.com/hecrj/iced", rev = "3042fa2cb63c651ebed2abe6f4054e61f70b0331" } -image = { version = "0.23", features = ["jpeg", "png", "jpeg_rayon"], default-features = false } -include_dir = { version = "0.6", features = ["search"] } -io_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -itertools = "0.10" -jpeg-decoder = "0.2" -lazy_static = "1" -libc = "0.2" -log = "0.4" -nix = { version = "0.27", features = ["signal"] } -num-traits = "0.2" -perf_stats = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -png-decoder = "0.1" -pretty_trace = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main", features = ["pprof"]} -prost = { version = "0.9", default_features = false, features = ["std", "prost-derive"] } -rayon = "1" -serde_json = "1" -string_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -tables = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -tokio = { version = "1", default-features = false, features = ["io-util", "macros", "rt-multi-thread"] } -tokio-stream = { version = "0.1", default-features = false, features = ["net"] } -tonic = { version = "0.6", default-features = false, features = ["transport", "codegen", "prost"] } -vector_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -whoami = "1" - -[target.'cfg(target_os = "linux")'.dependencies] -procfs = { version = "0.12", default_features = false } - -[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies] -arboard = "2" - -[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] -clipboard = "0.5" -cocoa = "0.24" -core-foundation = "0.9" -core-graphics = "0.22" -mach = "0.3" -objc = "0.2" - -[target.'cfg(not(target_os = "windows"))'.dependencies] -users = "0.11" - -[build-dependencies] -tonic-build = { version = "0.6", default-features = false, features = ["transport", "prost"] } diff --git a/enclone_visual/LICENSE.txt b/enclone_visual/LICENSE.txt deleted file mode 120000 index 4ab43736a8..0000000000 --- a/enclone_visual/LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -../LICENSE.txt \ No newline at end of file diff --git a/enclone_visual/README b/enclone_visual/README deleted file mode 100644 index 9cc05001e3..0000000000 --- a/enclone_visual/README +++ /dev/null @@ -1,29 +0,0 @@ -NOTES - ---------------------------------------------------------------------------------------------------- - -1. From a Mac, if you type "enclone VIS", when enclone starts up, it forks enclone in server -mode, still on the Mac. We sometimes observe a 9.2 second delay in this operation. We believe -this is attributable to the MacOS Gatekeeper. Gatekeeper checks executable codesigning. Probably -because enclone is not codesigned, Gatekeeper attempts to determine if the enclone executable -is "ok", and times out after 9.2 seconds. We think this only happens when the MAC IS OFFLINE. -Still, when offline, as best we can tell, eventually this behavior stops, but we don't know what -determines when that happens. Rebuilding the executable restarts the delays. Importantly, we -only know how Gatekeeper behaves on the version of OSX that we've tested. - ---------------------------------------------------------------------------------------------------- - -2. For automated testing on a Mac, the command to test is test_vis. - -Again this can be slow because of Gatekeeper behavior for enclone. And again the slowness -generally goes away, either if one is online or after a period of time. - -Note that automated testing causes an enclone visual window to open on your Mac. - ---------------------------------------------------------------------------------------------------- - -3. We have made various attempts to bypass Gatekeeper behavior: -(a) sudo spctl --master-disable -(b) xattr -dr com.apple.quarantine path -(c) system preferences ==> security and privacy ==> Privacy ==> Developer Tools ==> allow apps ... -However, none seem effective. diff --git a/enclone_visual/build.rs b/enclone_visual/build.rs deleted file mode 100644 index ab657df064..0000000000 --- a/enclone_visual/build.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -fn main() -> Result<(), Box> { - // compiling protos using path on build time - - tonic_build::compile_protos("./server.proto")?; - - Ok(()) -} diff --git a/enclone_visual/images/history_region.png b/enclone_visual/images/history_region.png deleted file mode 100644 index 874d369b02..0000000000 Binary files a/enclone_visual/images/history_region.png and /dev/null differ diff --git a/enclone_visual/images/input_region.png b/enclone_visual/images/input_region.png deleted file mode 100644 index 59dc3bf9ad..0000000000 Binary files a/enclone_visual/images/input_region.png and /dev/null differ diff --git a/enclone_visual/images/middle_region.png b/enclone_visual/images/middle_region.png deleted file mode 100644 index 6f4162fd9c..0000000000 Binary files a/enclone_visual/images/middle_region.png and /dev/null differ diff --git a/enclone_visual/images/right_region.png b/enclone_visual/images/right_region.png deleted file mode 100644 index 11a4e5e536..0000000000 Binary files a/enclone_visual/images/right_region.png and /dev/null differ diff --git a/enclone_visual/images/top_region.png b/enclone_visual/images/top_region.png deleted file mode 100644 index 1bf724132a..0000000000 Binary files a/enclone_visual/images/top_region.png and /dev/null differ diff --git a/enclone_visual/regression_images/.gitignore b/enclone_visual/regression_images/.gitignore deleted file mode 100644 index e33609d251..0000000000 --- a/enclone_visual/regression_images/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.png diff --git a/enclone_visual/regression_images/README b/enclone_visual/regression_images/README deleted file mode 100644 index 9d164b5379..0000000000 --- a/enclone_visual/regression_images/README +++ /dev/null @@ -1,5 +0,0 @@ -The .jpg files are tracked by git. - -THe .png files are not. They should be current if you've been making successive commits -on the same branch, but other operations (like backing up on the same branch) could cause -them to be out of data. We could add a tool to update them. diff --git a/enclone_visual/regression_images/abbr.jpg b/enclone_visual/regression_images/abbr.jpg deleted file mode 100644 index 20747fa2a0..0000000000 Binary files a/enclone_visual/regression_images/abbr.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/alluvial_tables.jpg b/enclone_visual/regression_images/alluvial_tables.jpg deleted file mode 100644 index 159eabfb28..0000000000 Binary files a/enclone_visual/regression_images/alluvial_tables.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/color_by_var.jpg b/enclone_visual/regression_images/color_by_var.jpg deleted file mode 100644 index d8fda564aa..0000000000 Binary files a/enclone_visual/regression_images/color_by_var.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/delete1.jpg b/enclone_visual/regression_images/delete1.jpg deleted file mode 100644 index c03bfc4055..0000000000 Binary files a/enclone_visual/regression_images/delete1.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/delete2.jpg b/enclone_visual/regression_images/delete2.jpg deleted file mode 100644 index d55824af95..0000000000 Binary files a/enclone_visual/regression_images/delete2.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/expand.jpg b/enclone_visual/regression_images/expand.jpg deleted file mode 100644 index 1747c15f26..0000000000 Binary files a/enclone_visual/regression_images/expand.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/metrics.jpg b/enclone_visual/regression_images/metrics.jpg deleted file mode 100644 index b81e77df77..0000000000 Binary files a/enclone_visual/regression_images/metrics.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/no_legend.jpg b/enclone_visual/regression_images/no_legend.jpg deleted file mode 100644 index 20c90d0b74..0000000000 Binary files a/enclone_visual/regression_images/no_legend.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/rename.jpg b/enclone_visual/regression_images/rename.jpg deleted file mode 100644 index df7ba559a0..0000000000 Binary files a/enclone_visual/regression_images/rename.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/restore1.jpg b/enclone_visual/regression_images/restore1.jpg deleted file mode 100644 index 55ae50f717..0000000000 Binary files a/enclone_visual/regression_images/restore1.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/restore2.jpg b/enclone_visual/regression_images/restore2.jpg deleted file mode 100644 index 3be797f111..0000000000 Binary files a/enclone_visual/regression_images/restore2.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/restore_metrics.jpg b/enclone_visual/regression_images/restore_metrics.jpg deleted file mode 100644 index b81e77df77..0000000000 Binary files a/enclone_visual/regression_images/restore_metrics.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/select_metrics.jpg b/enclone_visual/regression_images/select_metrics.jpg deleted file mode 100644 index b81e77df77..0000000000 Binary files a/enclone_visual/regression_images/select_metrics.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/share.jpg b/enclone_visual/regression_images/share.jpg deleted file mode 100644 index c37dc9c336..0000000000 Binary files a/enclone_visual/regression_images/share.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test1.jpg b/enclone_visual/regression_images/test1.jpg deleted file mode 100644 index e69c610403..0000000000 Binary files a/enclone_visual/regression_images/test1.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test10.jpg b/enclone_visual/regression_images/test10.jpg deleted file mode 100644 index deb90350a6..0000000000 Binary files a/enclone_visual/regression_images/test10.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test11.jpg b/enclone_visual/regression_images/test11.jpg deleted file mode 100644 index 530dfd9f07..0000000000 Binary files a/enclone_visual/regression_images/test11.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test12.jpg b/enclone_visual/regression_images/test12.jpg deleted file mode 100644 index 181a4822e8..0000000000 Binary files a/enclone_visual/regression_images/test12.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test13.jpg b/enclone_visual/regression_images/test13.jpg deleted file mode 100644 index abaccb586b..0000000000 Binary files a/enclone_visual/regression_images/test13.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test14.jpg b/enclone_visual/regression_images/test14.jpg deleted file mode 100644 index 4a45d39561..0000000000 Binary files a/enclone_visual/regression_images/test14.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test15.jpg b/enclone_visual/regression_images/test15.jpg deleted file mode 100644 index 279b57fbb0..0000000000 Binary files a/enclone_visual/regression_images/test15.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test16.jpg b/enclone_visual/regression_images/test16.jpg deleted file mode 100644 index 9ab9d8b7de..0000000000 Binary files a/enclone_visual/regression_images/test16.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test17.jpg b/enclone_visual/regression_images/test17.jpg deleted file mode 100644 index 1cc92f1b33..0000000000 Binary files a/enclone_visual/regression_images/test17.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test18.jpg b/enclone_visual/regression_images/test18.jpg deleted file mode 100644 index b5aa4e9eaf..0000000000 Binary files a/enclone_visual/regression_images/test18.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test19.jpg b/enclone_visual/regression_images/test19.jpg deleted file mode 100644 index 2be2d77788..0000000000 Binary files a/enclone_visual/regression_images/test19.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test1a.jpg b/enclone_visual/regression_images/test1a.jpg deleted file mode 100644 index 6e1addc28f..0000000000 Binary files a/enclone_visual/regression_images/test1a.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test1b.jpg b/enclone_visual/regression_images/test1b.jpg deleted file mode 100644 index 31eaecf757..0000000000 Binary files a/enclone_visual/regression_images/test1b.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test1c.jpg b/enclone_visual/regression_images/test1c.jpg deleted file mode 100644 index 536c3fcdf7..0000000000 Binary files a/enclone_visual/regression_images/test1c.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test1d.jpg b/enclone_visual/regression_images/test1d.jpg deleted file mode 100644 index 60300e7673..0000000000 Binary files a/enclone_visual/regression_images/test1d.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test1x.jpg b/enclone_visual/regression_images/test1x.jpg deleted file mode 100644 index 31eaecf757..0000000000 Binary files a/enclone_visual/regression_images/test1x.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test2.jpg b/enclone_visual/regression_images/test2.jpg deleted file mode 100644 index c6de7a6be8..0000000000 Binary files a/enclone_visual/regression_images/test2.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test20.jpg b/enclone_visual/regression_images/test20.jpg deleted file mode 100644 index 8732b926e2..0000000000 Binary files a/enclone_visual/regression_images/test20.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test3.jpg b/enclone_visual/regression_images/test3.jpg deleted file mode 100644 index fad6e141e8..0000000000 Binary files a/enclone_visual/regression_images/test3.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test4.jpg b/enclone_visual/regression_images/test4.jpg deleted file mode 100644 index fd00e95725..0000000000 Binary files a/enclone_visual/regression_images/test4.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test5.jpg b/enclone_visual/regression_images/test5.jpg deleted file mode 100644 index fad6e141e8..0000000000 Binary files a/enclone_visual/regression_images/test5.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test6.jpg b/enclone_visual/regression_images/test6.jpg deleted file mode 100644 index 97aaf4469f..0000000000 Binary files a/enclone_visual/regression_images/test6.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test7.jpg b/enclone_visual/regression_images/test7.jpg deleted file mode 100644 index 63dd02f487..0000000000 Binary files a/enclone_visual/regression_images/test7.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test8.jpg b/enclone_visual/regression_images/test8.jpg deleted file mode 100644 index b4c1840eba..0000000000 Binary files a/enclone_visual/regression_images/test8.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/test9.jpg b/enclone_visual/regression_images/test9.jpg deleted file mode 100644 index 530dfd9f07..0000000000 Binary files a/enclone_visual/regression_images/test9.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/trunc.jpg b/enclone_visual/regression_images/trunc.jpg deleted file mode 100644 index b8b9c3f274..0000000000 Binary files a/enclone_visual/regression_images/trunc.jpg and /dev/null differ diff --git a/enclone_visual/regression_images/unexpand.jpg b/enclone_visual/regression_images/unexpand.jpg deleted file mode 100644 index b785b7adc2..0000000000 Binary files a/enclone_visual/regression_images/unexpand.jpg and /dev/null differ diff --git a/enclone_visual/repeat_test_vis b/enclone_visual/repeat_test_vis deleted file mode 100755 index 60cfd80670..0000000000 --- a/enclone_visual/repeat_test_vis +++ /dev/null @@ -1,22 +0,0 @@ -#/bin/csh - -# repeat_test_vis -# or -# repeat_test_vis VERBOSE - -foreach i (1 2 3 4 5 6 7 8 9 10) - if ( $1 == "VERBOSE" ) then - test_vis VERBOSE - if ( $status != 0 ) then - echo "attempt $i failed" - break - endif - else - test_vis QUIET - if ( $status != 0 ) then - echo "attempt $i failed" - break - endif - endif - echo "attempt $i done" -end diff --git a/enclone_visual/server.proto b/enclone_visual/server.proto deleted file mode 100644 index dc28c72d85..0000000000 --- a/enclone_visual/server.proto +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -// version of protocol buffer used - -syntax = "proto3"; - -package enclone; - -// Analyzer service that runs enclone. A rust trait will be generated -// from this service for the server code to implement. - -service Analyzer { - - rpc Ping(Unit) returns (Unit); - - // Runs enclone. - - rpc Enclone(EncloneRequest) returns (EncloneResponse); - - // Returns the table for one clonotype. - - rpc GetClonotype(ClonotypeRequest) returns (ClonotypeResponse); - - // Test a user name to see if it is valid. - - rpc TestUserName(UserNameRequest) returns (UserNameResponse); - - // Share a session. - - rpc ShareSession(SendShareRequest) returns (SendShareResponse); - - // Fetch my shares. - - rpc get_my_shares(GetMySharesRequest) returns (GetMySharesResponse); - - // Release my shares. - - rpc release_my_shares(ReleaseMySharesRequest) returns (ReleaseMySharesResponse); - - // Fetch remote cookbooks. - - rpc get_my_cookbooks(GetMyCookbooksRequest) returns (GetMyCookbooksResponse); - -} - -message Unit {} - -message EncloneRequest { - string args = 1; - optional string server_logfile = 2; -} - -message EncloneResponse { - string args = 1; - string plot = 2; // SVG - string table = 3; // partial clonotype table as terminal text - string summary = 4; - repeated string metrics = 5; - repeated string dataset_names = 6; - bytes table_comp = 7; // full clonotype table as terminal text, compressed - repeated uint32 last_widths = 8; -} - -message ClonotypeRequest { - uint32 clonotypeNumber = 1; -} - -message ClonotypeResponse { - string table = 1; // Colored terminal text. -} - -message UserNameRequest { - string user_name = 1; -} - -message UserNameResponse { - bool value = 1; -} - -message SendShareRequest { - string share_dir = 1; - bytes content = 2; - string sender = 3; - repeated string recipients = 4; -} - -message SendShareResponse { - bool ok = 1; -} - -message GetMySharesRequest { - string share_dir = 1; - bool me_only = 2; -} - -message GetMySharesResponse { - repeated bytes content = 1; - repeated string messages = 2; - repeated string filenames = 3; -} - -message ReleaseMySharesRequest { - string share_dir = 1; - repeated string filenames = 2; -} - -message ReleaseMySharesResponse { - bool ok = 1; -} - -message GetMyCookbooksRequest { - repeated string cookbook_dirs = 1; -} - -message GetMyCookbooksResponse { - repeated bytes cookbooks = 1; -} diff --git a/enclone_visual/src/apocalypse.rs b/enclone_visual/src/apocalypse.rs deleted file mode 100644 index 81347de3e1..0000000000 --- a/enclone_visual/src/apocalypse.rs +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::*; -use chrono::{TimeZone, Utc}; -use enclone_build::version_string; -use enclone_core::{BUG_REPORT_ADDRESS, REMOTE_HOST}; -use itertools::Itertools; -use pretty_trace::*; -use std::env; -use std::io::{Read, Write}; -use std::process::Stdio; -use std::sync::atomic::Ordering::SeqCst; - -pub fn prepare_for_apocalypse_visual() { - let email = INTERNAL.load(SeqCst); - let ctrlc = CTRLC.load(SeqCst); - let bug_reports = &BUG_REPORTS.lock().unwrap()[0]; - let args: Vec = std::env::args().collect(); - if email { - assert!(bug_reports.len() > 0); - } - let now = Utc::now().naive_utc().timestamp(); - let build_date = version_string().after(":").between(": ", " :").to_string(); - let build_datetime = format!("{} 00:00:00", build_date); - let then = Utc - .datetime_from_str(&build_datetime, "%Y-%m-%d %H:%M:%S") - .unwrap() - .timestamp(); - let days_since_build = (now - then) / (60 * 60 * 24); - let mut elapsed_message = String::new(); - if days_since_build > 30 { - elapsed_message = format!( - "Your build is {} days old. You might want to check \ - to see if there is a newer build now.\n\n", - days_since_build - ); - } - if !email { - let exit_message = format!( - "Something has gone badly wrong. You have probably encountered an internal \ - error in enclone.\n\n\ - Please email us at enclone@10xgenomics.com, including the traceback shown\n\ - above and also the following version information:\n\ - {} : {}.\n\n\ - Your command was:\n\n{}\n\n\ - {}\ - 🌸 Thank you so much for finding a bug and have a nice day! 🌸", - env!("CARGO_PKG_VERSION"), - version_string(), - args.iter().format(" "), - elapsed_message, - ); - if !ctrlc { - PrettyTrace::new().exit_message(&exit_message).on(); - } else { - PrettyTrace::new().exit_message(&exit_message).ctrlc().on(); - } - } else { - // Set up to email bug report on panic. This is only for internal users! - - let mut contemplate = "".to_string(); - if bug_reports == "enclone@10xgenomics.com" { - contemplate = ", for the developers to contemplate".to_string(); - } - let exit_message = format!( - "Something has gone badly wrong. You have probably encountered an internal \ - error in enclone.\n\n\ - Here is the version information:\n\ - {} : {}.\n\n\ - Your command was:\n\n{}\n\n\ - {}\ - Thank you for being a happy internal enclone user. All of this information \ - is being\nemailed to {}{}.\n\n\ - 🌸 Thank you so much for finding a bug and have a nice day! 🌸", - env!("CARGO_PKG_VERSION"), - version_string(), - args.iter().format(" "), - elapsed_message, - bug_reports, - contemplate, - ); - BUG_REPORT_ADDRESS - .lock() - .unwrap() - .push(bug_reports.to_string()); - fn exit_function(msg: &str) { - let mut msg = msg.to_string(); - - // Get messages and shrink. - - let mut messages = compressed_message_history(); - let mut messages2 = Vec::::new(); - for i in 0..messages.len() { - if i == messages.len() - 1 - || !messages[i].starts_with("ArchiveName(") - || !messages[i + 1].starts_with("ArchiveName(") - { - messages2.push(messages[i].clone()); - } - } - messages = messages2; - let mut messages2 = Vec::::new(); - let mut i = 0; - while i < messages.len() { - if i < messages.len() - 1 - && messages[i] == "SubmitButtonPressed(Ok(()))" - && messages[i + 1] == "ComputationDone(Ok(()))" - { - messages2.push("Submit button pressed".to_string()); - i += 1; - } else { - messages2.push(messages[i].clone()); - } - i += 1; - } - messages = messages2; - let mut messages2 = Vec::::new(); - let mut i = 0; - while i < messages.len() { - if i < messages.len() - 1 - && messages[i] == "Save" - && messages[i + 1] == "CompleteSave(Ok(()))" - { - messages2.push("Save button pressed".to_string()); - i += 1; - } else { - messages2.push(messages[i].clone()); - } - i += 1; - } - messages = messages2; - let mut messages2 = Vec::::new(); - let mut i = 0; - while i < messages.len() { - if i < messages.len() - 1 - && messages[i] == "ArchiveRefresh" - && messages[i + 1] == "ArchiveRefreshComplete(Ok(()))" - { - messages2.push("Refresh button pressed".to_string()); - i += 1; - } else { - messages2.push(messages[i].clone()); - } - i += 1; - } - messages = messages2; - let mut messages2 = Vec::::new(); - let mut i = 0; - while i < messages.len() { - if i < messages.len() - 1 - && messages[i] == "DoShare(true)" - && messages[i + 1] == "CompleteDoShare(Ok(()))" - { - messages2.push("sharing".to_string()); - i += 1; - } else { - messages2.push(messages[i].clone()); - } - i += 1; - } - messages = messages2; - for i in 0..messages.len() { - if messages[i] == "ArchiveOpen(Ok(()))" { - messages[i] = "Archive button pressed".to_string(); - } else if messages[i] == "ArchiveClose" { - messages[i] = "Dismiss button pressed".to_string(); - } else if messages[i] == "DelButtonPressed(Ok(()))" { - messages[i] = "Del button pressed".to_string(); - } - } - - // Proceed. - - println!("enclone visual message history:\n"); - msg += "enclone visual message history:\n\n"; - for i in 0..messages.len() { - println!("[{}] {}", i + 1, messages[i]); - msg += &mut format!("[{}] {}\n", i + 1, messages[i]); - } - println!(""); - let msg = format!("{}\n.\n", msg); - let bug_report_address = &BUG_REPORT_ADDRESS.lock().unwrap()[0]; - if !version_string().contains("macos") { - let process = std::process::Command::new("mail") - .arg("-s") - .arg("internal automated bug report") - .arg(&bug_report_address) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn(); - let process = process.unwrap(); - process.stdin.unwrap().write_all(msg.as_bytes()).unwrap(); - let mut _s = String::new(); - process.stdout.unwrap().read_to_string(&mut _s).unwrap(); - } else if REMOTE_HOST.lock().unwrap().len() > 0 { - let remote_host = &REMOTE_HOST.lock().unwrap()[0]; - let process = std::process::Command::new("ssh") - .arg(&remote_host) - .arg("mail") - .arg("-s") - .arg("\"internal automated bug report\"") - .arg(&bug_report_address) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - let mut process = process.unwrap(); - process - .stdin - .as_ref() - .unwrap() - .write_all(msg.as_bytes()) - .unwrap(); - if !process.wait().unwrap().success() { - eprintln!("\nAttempt to send email failed.\n"); - } - } - } - if !ctrlc { - PrettyTrace::new() - .exit_message(&exit_message) - .run_this(exit_function) - .on(); - } else { - PrettyTrace::new() - .exit_message(&exit_message) - .run_this(exit_function) - .ctrlc() - .on(); - } - } -} diff --git a/enclone_visual/src/archive.rs b/enclone_visual/src/archive.rs deleted file mode 100644 index 6315f9b828..0000000000 --- a/enclone_visual/src/archive.rs +++ /dev/null @@ -1,640 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -// Be very careful about editing the archive function as it is delicate and under-tested. - -use crate::*; -use iced::Length::Units; -use iced::{ - Alignment, Button, Checkbox, Color, Column, Container, Element, Length, Row, Rule, Scrollable, - Space, Text, TextInput, -}; -use io_utils::*; -use itertools::izip; -use messages::Message; - -pub fn archive(slf: &mut gui_structures::EncloneVisual) -> Element { - let archive_title = Text::new(&format!("Archive")) - .font(LIBERATION_SANS) - .size(30); - let archive_snapshot_button = Button::new( - &mut slf.archive_snapshot_button, - Text::new("Snapshot") - .font(LIBERATION_SANS) - .color(slf.archive_snapshot_button_color), - ) - .on_press(Message::ArchiveSnapshot); - let archive_close_button = Button::new( - &mut slf.archive_close_button, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::ArchiveClose); - let archive_save_close_button = Button::new( - &mut slf.archive_save_close_button, - Text::new("Save and dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::ArchiveSaveClose); - let open_archive_doc_button = Button::new( - &mut slf.open_archive_doc_button, - Text::new("Expand documentation").font(LIBERATION_SANS), - ) - .on_press(Message::OpenArchiveDoc); - let close_archive_doc_button = Button::new( - &mut slf.close_archive_doc_button, - Text::new("Hide documentation").font(LIBERATION_SANS), - ) - .on_press(Message::CloseArchiveDoc); - let refresh_button = Button::new( - &mut slf.archive_refresh_button, - Text::new("Refresh") - .font(LIBERATION_SANS) - .color(slf.archive_refresh_button_color), - ) - .on_press(Message::ArchiveRefresh); - - // Display top bar. Don't display the refresh button if a restore has been requested. - - let mut is_restore_requested = false; - for i in 0..slf.restore_requested.len() { - if slf.restore_requested[i] { - is_restore_requested = true; - } - } - for i in 0..slf.restore_cookbook_requested.len() { - if slf.restore_cookbook_requested[i] { - is_restore_requested = true; - } - } - let mut top_bar = Row::new() - .push(archive_title) - .push(Space::with_width(Length::Fill)); - top_bar = top_bar - .push(archive_snapshot_button) - .push(Space::with_width(Units(8))); - if !is_restore_requested { - top_bar = top_bar - .push(refresh_button) - .push(Space::with_width(Units(8))); - } else { - top_bar = top_bar - .push(archive_save_close_button) - .push(Space::with_width(Units(8))); - } - top_bar = top_bar.push(archive_close_button); - - // Define help text messages. - - let text0 = - Text::new("enclone visual can save sessions to the directory ~/enclone/visual/history.") - .font(LIBERATION_SANS); - let text1 = Text::new( - "For a given enclone visual session:\n\ - • click the Save box on the main screen to immediately save your session\n\ - • or click the On Exit box on the main screen; it will turn red \ - (pushing again toggles state)\n\ - • when you later push the Exit button, your session will be saved.", - ) - .font(LIBERATION_SANS); - let text1b = Text::new( - "▒ cookbooks - These are hardcoded sessions that are provided with enclone visual. They \ - do not have date or time fields and may not be deleted or renamed.", - ) - .font(LIBERATION_SANS); - let text2 = - Text::new("▒ expand - Display the commands in a saved session by checking the expand box.") - .font(LIBERATION_SANS); - let text3 = Text::new( - "▒ restore - Restore a saved session or cookbook by checking the restore box, and then \ - pushing Dismiss. If you want your current session to be saved first (rather than \ - deleted), you should instead push Save and dismiss.", - ) - .font(LIBERATION_SANS); - let text4 = Text::new("▒ delete - Delete a saved session by checking the delete box.") - .font(LIBERATION_SANS); - let text5 = Text::new( - "▒ share - Share with other users by checking the share box. You will be prompted for \ - their names.\n\ - Conversely another user may share with you. Use the Refresh button to receive shares.", - ) - .font(LIBERATION_SANS); - let text6 = Text::new( - "▒ name - Name of a previous session is displayed:\n\ - • change it using the rectangular box and then click Apply\n\ - • up to 30 characters are allowed.", - ) - .font(LIBERATION_SANS); - let text7 = Text::new( - "▒ Narrative is displayed in a box:\n\ - • if there is no narrative, a tiny box is seen\n\ - • clicking on the box will change the narrative to whatever is on your clipboard\n\ - • clicking on the Copy button to the right of it will copy the existing narrative \ - to your clipboard.", - ) - .font(LIBERATION_SANS); - - // Define help column. - - let mut help_col = Column::new(); - if slf.archive_doc_open { - help_col = help_col - .spacing(SPACING) - .push(text1) - .push(text1b) - .push(text2) - .push(text3) - .push(text4); - if slf.sharing_enabled { - help_col = help_col.push(text5); - } - help_col = help_col.push(text6); - help_col = help_col.push(text7); - help_col = help_col.push(close_archive_doc_button); - } else { - help_col = help_col.push(open_archive_doc_button); - } - - let mut labels = "# date time expand restore delete".to_string(); - if slf.sharing_enabled { - labels += " share"; - } - labels += " name"; - let labels = Text::new(&labels).font(DEJAVU); - - fn share_col() -> Column<'static, Message> { - let c = Color::from_rgb(0.4, 0.1, 0.2); - Column::new() - .push(Space::with_height(Units(8))) - .push( - Text::new( - " Enter user names (usually first.last), one per line, \ - and check the box to the right.", - ) - .font(LIBERATION_SANS) - .size(16) - .color(c), - ) - .push(Space::with_height(Units(4))) - .push( - Text::new(" A new line will appear once you do so.") - .font(LIBERATION_SANS) - .size(16) - .color(c), - ) - .push(Space::with_height(Units(4))) - .push( - Text::new( - " Lines may be prepopulated based on your recent shares; \ - you can check them.", - ) - .font(LIBERATION_SANS) - .size(16) - .color(c), - ) - } - - let mut archive_scrollable = Scrollable::new(&mut slf.scroll) - .width(Length::Fill) - .height(Length::Fill) - .scrollbar_width(SCROLLBAR_WIDTH) - .scroller_width(12) - .style(style::ScrollableStyle); - - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - let mut sharing = false; - for i in 0..slf.archive_share_requested.len() { - if slf.archive_share_requested[i] { - sharing = true; - } - } - let mut share_body = Column::new(); - if sharing { - share_body = share_body.push(share_col()); - for (j, u) in slf.user.iter_mut().enumerate() { - share_body = share_body.push(Space::with_height(Units(8))); - let mut row = Row::new() - .push(Text::new(" ").font(DEJAVU)) - .push( - TextInput::new(u, "", &slf.user_value[j], move |x: String| { - Message::UserName(x, j) - }) - .width(Units(345)) - .font(DEJAVU) - .padding(2), - ) - .push(Space::with_width(Units(8))) - .push(Checkbox::new(slf.user_selected[j], "", move |x: bool| { - Message::UserSelected(x, j) - })) - .push(Space::with_width(Units(4))); - if !slf.user_selected[j] { - row = row.push(Text::new(" ").font(DEJAVU)); - } else { - if slf.user_valid[j] { - row = row.push(Text::new("valid ").font(DEJAVU)); - } else { - row = row.push(Text::new("invalid").font(DEJAVU)); - } - } - share_body = share_body.push(row); - } - let mut valids = 0; - for x in slf.user_valid.iter() { - if *x { - valids += 1; - } - } - if valids > 0 { - let row = Row::new() - .align_items(Alignment::Center) - .push( - Text::new(" check to complete share") - .font(LIBERATION_SANS) - .size(16), - ) - .push(Space::with_width(Units(14))) - .push(Checkbox::new(slf.do_share, "", Message::DoShare)) - .push( - Text::new("or uncheck share to cancel") - .font(LIBERATION_SANS) - .size(16), - ); - share_body = share_body.push(Space::with_height(Units(8))); - share_body = share_body.push(row); - if slf.do_share_complete { - share_body = share_body - .push(Space::with_height(Units(8))) - .push( - Text::new( - " Done, your session has been shared! \ - You can uncheck the share box to make the share information vanish.", - ) - .font(LIBERATION_SANS) - .size(16), - ) - .push(Space::with_height(Units(8))) - .push( - Text::new( - " You have to uncheck the share box to do \ - another share.", - ) - .font(LIBERATION_SANS) - .size(16), - ); - } - } - } - let mut share_body = Some(share_body); - - // Display cookbooks. - - let ncookbooks = slf.cookbooks.len(); - let narchive = slf.archive_name.len(); - for (i, y, narbut, copynarbut) in izip!( - 0..ncookbooks, - slf.cookbook_name.iter_mut(), - slf.cookbook_narrative_button.iter_mut(), - slf.copy_cookbook_narrative_button.iter_mut() - ) { - let mut row = Row::new().align_items(Alignment::Center); - let date = "········"; - let time = "·····"; - row = row.push(Text::new(&format!("{:<3} {} {} ", i + 1, date, time,)).font(DEJAVU)); - row = row - .push(Checkbox::new( - slf.expand_cookbook_entry[i], - "", - move |x: bool| Message::ExpandCookbookEntry(x, i), - )) - .push(Space::with_width(Units(70))) - .push(Checkbox::new( - slf.restore_cookbook_requested[i], - "", - move |x: bool| Message::RestoreCookbook(x, i), - )) - .push(Space::with_width(Units(67))) - .push(Text::new("·····").font(DEJAVU)) - .push(Space::with_width(Units(51))); - if slf.sharing_enabled { - row = row - .push(Text::new("·····").font(DEJAVU)) - .push(Space::with_width(Units(39))); - } - row = row.push(Space::with_width(Units(5))); - row = row.push(Text::new(&*y).font(LIBERATION_SANS)); - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - archive_scrollable = archive_scrollable.push(row); - const MAX_LINE: usize = 113; - let mut log = String::new(); - let mut rows = Vec::>::new(); - let folds = fold(&slf.cookbook_narrative[i], MAX_LINE); - for i in 0..folds.len() { - rows.push(vec![folds[i].clone()]); - } - for i in 0..rows.len() { - if i > 0 { - log += "\n"; - } - log += &mut rows[i][0].clone(); - } - let copy_cookbook_narrative_button = Button::new( - copynarbut, - Text::new("Copy") - .font(LIBERATION_SANS) - .color(slf.copy_cookbook_narrative_button_color[i]), - ) - .on_press(Message::CopyCookbookNarrative(i)); - let mut row = Row::new().push(Text::new(" ").font(DEJAVU)).push( - Button::new(narbut, Text::new(&log).font(LIBERATION_SANS)) - .on_press(Message::CopyCookbookNarrative(i)), - ); - if slf.cookbook_narrative[i].len() > 0 { - row = row - .push(Space::with_width(Units(8))) - .push(copy_cookbook_narrative_button); - } - archive_scrollable = archive_scrollable.push(Space::with_height(Units(12))); - archive_scrollable = archive_scrollable.push(row); - if slf.restore_cookbook_msg[i].len() > 0 { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - let mut row = Row::new(); - row = row.push(Space::with_width(Units(43))); - row = row.push( - Text::new(&format!("{}", slf.restore_cookbook_msg[i])) - .font(DEJAVU) - .color(Color::from_rgb(1.0, 0.0, 0.0)) - .size(16), - ); - archive_scrollable = archive_scrollable.push(row); - } - if slf.expand_cookbook_entry[i] { - let clist = &slf.cookbook_command_list[i].as_ref().unwrap(); - if !clist.is_empty() { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - } - for (j, y) in clist.iter().enumerate() { - // THIS CODE IS DUPLICATED BELOW. - // Determine max_line. Sloppy, as we don't actually do the correct math. - const MAX_LINE: usize = 110; - let max_line = MAX_LINE as f64 * slf.width as f64 / INITIAL_WIDTH as f64; - let max_line = max_line.round() as usize; - let lines = fold(&y, max_line); - for k in 0..lines.len() { - let s = if k == 0 { - format!(" {} = {}", j + 1, lines[k]) - } else { - let len = format!(" {} = ", j + 1).len(); - let b = stringme(&vec![b' '; len]); - format!("{}{}", b, lines[k]) - }; - let row = Row::new().push( - Text::new(&s) - .font(DEJAVU) - .color(Color::from_rgb(0.0, 0.0, 0.4)) - .size(16), - ); - archive_scrollable = archive_scrollable.push(row); - if j < clist.len() - 1 || k < lines.len() - 1 { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(4))); - } - } - } - if !clist.is_empty() { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(3))); - } - } - - if i < ncookbooks - 1 || narchive > 0 { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - archive_scrollable = - archive_scrollable.push(Rule::horizontal(10).style(style::ThinRuleStyle)); - } - - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - } - - // Display saved sessions. - - let mut count = 0; - for (i, y, q, narbut, copynarbut) in izip!( - 0..narchive, - slf.archive_name.iter_mut(), - slf.archive_name_change_button.iter_mut(), - slf.archive_narrative_button.iter_mut(), - slf.copy_archive_narrative_button.iter_mut() - ) { - let x = &slf.archive_list[i]; - let path = format!("{}/{}", slf.archive_dir.as_ref().unwrap(), x); - let mut make_row = x.contains("___") && !slf.deleted[i]; - if !path_exists(&path) && !slf.delete_requested[i] { - make_row = false; - } - if make_row { - let mut row = Row::new().align_items(Alignment::Center); - let date = x.before("___").to_string(); - let date1 = stringme(&date.as_bytes()[2..4]); - let date2 = date.after("-").to_string(); - let mut date = format!("{}-{}", date2, date1); - let mut time = x.after("___").to_string(); - if time.contains(":") { - time = time.rev_before(":").to_string(); - } else { - time = time.rev_before("-").to_string(); - time = time.replace("-", ":"); - } - if TEST_MODE.load(SeqCst) || META_TESTING.load(SeqCst) { - date = stringme(&vec![b' '; 8]); - time = stringme(&vec![b' '; 5]); - } - row = row.push( - Text::new(&format!( - "{:<3} {} {} ", - count + 1 + slf.cookbooks.len(), - date, - time, - )) - .font(DEJAVU), - ); - row = row - .push(Checkbox::new( - slf.expand_archive_entry[i], - "", - move |x: bool| Message::ExpandArchiveEntry(x, i), - )) - .push(Space::with_width(Units(70))) - .push(Checkbox::new( - slf.restore_requested[i], - "", - move |x: bool| Message::Restore(x, i), - )) - .push(Space::with_width(Units(69))) - .push(Checkbox::new( - slf.delete_requested[i], - "", - move |x: bool| Message::DeleteArchiveEntry(x, i), - )) - .push(Space::with_width(Units(68))); - if slf.sharing_enabled { - row = row.push(Checkbox::new( - slf.archive_share_requested[i], - "", - move |x: bool| Message::ArchiveShare(x, i), - )); - row = row.push(Space::with_width(Units(58))); - } - row = row.push( - TextInput::new(y, "", &slf.archive_name_value[i], move |x: String| { - Message::ArchiveName(x, i) - }) - .font(LIBERATION_SANS) - .width(Units(300)) - // .max_width(300) - .padding(2), - ); - row = row.push(Space::with_width(Units(8))); - row = row.push( - Button::new( - q, - Text::new("Apply") - .font(LIBERATION_SANS) - .color(slf.archive_name_change_button_color[i]), - ) - .on_press(Message::ArchiveNameChange(i)), - ); - if i > 0 { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - } - archive_scrollable = archive_scrollable.push(row); - - if slf.archive_origin[i].len() > 0 { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - archive_scrollable = archive_scrollable.push( - Text::new(&format!(" {}", &slf.archive_origin[i])) - .font(DEJAVU) - .size(16), - ); - } - - // Show narrative. - - const MAX_LINE: usize = 116; - let mut log = String::new(); - let mut rows = Vec::>::new(); - let folds = fold(&slf.archive_narrative[i], MAX_LINE); - for i in 0..folds.len() { - rows.push(vec![folds[i].clone()]); - } - for i in 0..rows.len() { - if i > 0 { - log += "\n"; - } - log += &mut rows[i][0].clone(); - } - let copy_narrative_button = Button::new( - copynarbut, - Text::new("Copy") - .font(LIBERATION_SANS) - .color(slf.copy_archive_narrative_button_color[i]), - ) - .on_press(Message::CopyArchiveNarrative(i)); - let mut row = Row::new().push(Text::new(" ").font(DEJAVU)).push( - Button::new(narbut, Text::new(&log).font(LIBERATION_SANS)) - .on_press(Message::ArchiveNarrative(i)), - ); - if slf.archive_narrative[i].len() > 0 { - row = row - .push(Space::with_width(Units(8))) - .push(copy_narrative_button); - } - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - archive_scrollable = archive_scrollable.push(row); - - // Show if share requested. - - if slf.archive_share_requested[i] { - archive_scrollable = archive_scrollable.push(share_body.take().unwrap()); - } - - // Show restore message. - - if slf.restore_msg[i].len() > 0 { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - let mut row = Row::new(); - row = row.push(Space::with_width(Units(43))); - row = row.push( - Text::new(&format!("{}", slf.restore_msg[i])) - .font(DEJAVU) - .color(Color::from_rgb(1.0, 0.0, 0.0)) - .size(16), - ); - archive_scrollable = archive_scrollable.push(row); - } - - // Show the commands if expansion requested. - - if slf.expand_archive_entry[i] { - let clist = &slf.archived_command_list[i].as_ref().unwrap(); - if !clist.is_empty() { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - } - for (j, y) in clist.iter().enumerate() { - // Determine max_line. Sloppy, as we don't actually do the correct math. - const MAX_LINE: usize = 110; - let max_line = MAX_LINE as f64 * slf.width as f64 / INITIAL_WIDTH as f64; - let max_line = max_line.round() as usize; - let lines = fold(&y, max_line); - for k in 0..lines.len() { - let s = if k == 0 { - format!(" {} = {}", j + 1, lines[k]) - } else { - let len = format!(" {} = ", j + 1).len(); - let b = stringme(&vec![b' '; len]); - format!("{}{}", b, lines[k]) - }; - let row = Row::new().push( - Text::new(&s) - .font(DEJAVU) - .color(Color::from_rgb(0.0, 0.0, 0.4)) - .size(16), - ); - archive_scrollable = archive_scrollable.push(row); - if j < clist.len() - 1 || k < lines.len() - 1 { - archive_scrollable = - archive_scrollable.push(Space::with_height(Units(4))); - } - } - } - if !clist.is_empty() { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(3))); - } - } - - let mut have_more = false; - for j in i + 1..narchive { - if !slf.deleted[j] { - have_more = true; - } - } - if have_more { - archive_scrollable = archive_scrollable.push(Space::with_height(Units(8))); - archive_scrollable = - archive_scrollable.push(Rule::horizontal(10).style(style::ThinRuleStyle)); - } - - count += 1; - } - } - let content = Column::new() - .spacing(SPACING) - .padding(20) - .push(top_bar) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(text0) - .push(help_col) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(labels) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(archive_scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} diff --git a/enclone_visual/src/bin/circ_fail.rs.aside b/enclone_visual/src/bin/circ_fail.rs.aside deleted file mode 100644 index bcd140f6eb..0000000000 --- a/enclone_visual/src/bin/circ_fail.rs.aside +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use engine::Engine; -use iced::{ - button, scrollable, Button, Column, Container, Element, Length, Sandbox, Scrollable, Settings, - Text, -}; -use std::time::{SystemTime, UNIX_EPOCH}; - -pub fn rotate(r: i64) -> i64 { - 6_364_136_223_846_793_005i64 - .wrapping_mul(r) - .wrapping_add(1_442_695_040_888_963_407) -} - -pub fn main() -> iced::Result { - Circles::run(Settings::default()) -} - -#[derive(Default)] -struct Circles { - engine: Engine, - button: button::State, - scroll: scrollable::State, -} - -#[derive(Debug, Clone, Copy)] -enum Message { - ButtonPressed, -} - -impl Sandbox for Circles { - type Message = Message; - - fn new() -> Self { - Circles::default() - } - - fn title(&self) -> String { - String::from("Circles") - } - - fn update(&mut self, message: Message) { - match message { - Message::ButtonPressed => { - self.engine.state.button_pressed = true; - let start = SystemTime::now(); - let since_the_epoch = start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); - let nanos = since_the_epoch.subsec_nanos() as u64; - let radius = (nanos % 99) as f32; - self.engine.state.radius = radius; - self.engine.state.rand = rotate(self.engine.state.rand); - } - } - } - - fn view(&mut self) -> Element { - let button = Button::new(&mut self.button, Text::new("Submit")) - .padding(10) - .on_press(Message::ButtonPressed); - let engine = self - .engine - .view() - .map(move |_message| Message::ButtonPressed); - - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(12) - .scroller_width(12) - // .style(style::Squeak) - .push(engine); - - let content = Column::new().push(button).push(scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -mod engine { - use crate::rotate; - use iced::{ - canvas::{self, Canvas, Cursor, Frame, Geometry, Path}, - Color, Element, Length, Rectangle, - }; - use iced_native::Point; - use iced_native::Vector; - - #[derive(Default)] - pub struct State { - pub button_pressed: bool, - pub radius: f32, - pub rand: i64, - } - - pub struct Engine { - pub state: State, - } - - #[derive(Debug, Clone)] - pub enum Message {} - - impl Default for Engine { - fn default() -> Self { - Self { - state: State::default(), - } - } - } - - impl Engine { - pub fn view<'a>(&'a mut self) -> Element<'a, Message> { - Canvas::new(self) - .width(Length::Fill) - .height(Length::Fill) - .into() - } - } - - impl<'a> canvas::Program for Engine { - fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec { - let pos = cursor.position_in(&bounds); - let mut frame = Frame::new(bounds.size()); - let radius = self.state.radius; - let center = frame.center(); - if pos.is_some() { - let xdiff = pos.unwrap().x - center.x; - let ydiff = pos.unwrap().y - center.y; - let dist = (xdiff * xdiff + ydiff * ydiff).sqrt(); - if dist <= radius { - frame.translate(Vector { x: 100.0, y: 100.0 }); - frame.fill_text(format!( - "delta = ({:.1}, {:.1}); in circle one at distance {:.1} <= {:.1}", - pos.unwrap().x - center.x, - pos.unwrap().y - center.y, - dist, - radius - )); - frame.translate(Vector { - x: -100.0, - y: -100.0, - }); - } - } - let circle1 = Path::circle(center, radius); - frame.fill(&circle1, Color::from_rgb(0.5, 0.5, 1.0)); - let circlex = Path::circle(center, 2.0); - frame.fill(&circlex, Color::from_rgb(0.0, 0.0, 0.0)); - - let mut r = self.state.rand; - for _ in 0..10000 { - r = rotate(r); - let x = r % 200; - r = rotate(r); - let y = r % 200; - r = rotate(r); - let rad = r % 10; - let circle2 = Path::circle( - Point { - x: center.x + x as f32, - y: center.y + y as f32, - }, - rad as f32, - ); - r = rotate(r); - let c1 = 0.7 + (r % 1000) as f32 / 3000.0; - r = rotate(r); - let c2 = 0.7 + (r % 1000) as f32 / 3000.0; - r = rotate(r); - let c3 = 0.7 + (r % 1000) as f32 / 3000.0; - frame.fill(&circle2, Color::from_rgb(c1, c2, c3)); - } - - vec![frame.into_geometry()] - } - } -} diff --git a/enclone_visual/src/bin/circ_fail_simple.rs.aside b/enclone_visual/src/bin/circ_fail_simple.rs.aside deleted file mode 100644 index 9458cd51d6..0000000000 --- a/enclone_visual/src/bin/circ_fail_simple.rs.aside +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// This is also in enclone/bugs/canvas_in_scrollable, where we can use the latest version of iced. - -use iced::canvas::{self, Canvas, Cursor, Frame, Geometry, Path}; -use iced::{ - scrollable, Color, Column, Container, Element, Length, Rectangle, Sandbox, Scrollable, Settings, -}; - -pub fn main() -> iced::Result { - Circles::run(Settings::default()) -} - -#[derive(Default)] -struct Circles { - engine: Engine, - scroll: scrollable::State, -} - -#[derive(Debug, Clone, Copy)] -enum Message { - Something, -} - -impl Sandbox for Circles { - type Message = Message; - - fn new() -> Self { - Circles::default() - } - - fn title(&self) -> String { - String::from("Circles") - } - - fn update(&mut self, _message: Message) {} - - fn view(&mut self) -> Element { - let engine = self.engine.view().map(move |_message| Message::Something); - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(12) - .scroller_width(12) - .push(engine); - let content = Column::new().push(scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -#[derive(Default)] -pub struct Engine {} - -pub enum EngineMessage {} - -impl Engine { - pub fn view<'a>(&'a mut self) -> Element<'a, EngineMessage> { - Canvas::new(self) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -impl<'a> canvas::Program for Engine { - fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec { - let mut frame = Frame::new(bounds.size()); - let circle = Path::circle(frame.center(), 20.0); - frame.fill(&circle, Color::BLACK); - vec![frame.into_geometry()] - } -} diff --git a/enclone_visual/src/bin/circles_example.rs.aside b/enclone_visual/src/bin/circles_example.rs.aside deleted file mode 100644 index b097192038..0000000000 --- a/enclone_visual/src/bin/circles_example.rs.aside +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Illustrate the following: -// -// 1. Display a tooltip message in a Canvas. -// 2. Make a Canvas change based on pushing a button. -// 3. Show that a Canvas is stil performant even when it has a large number of objects in it. - -use engine::Engine; -use iced::{button, Button, Column, Container, Element, Length, Sandbox, Settings, Text}; -use std::time::{SystemTime, UNIX_EPOCH}; - -pub fn rotate(r: i64) -> i64 { - 6_364_136_223_846_793_005i64 - .wrapping_mul(r) - .wrapping_add(1_442_695_040_888_963_407) -} - -pub fn main() -> iced::Result { - Circles::run(Settings::default()) -} - -#[derive(Default)] -struct Circles { - engine: Engine, - button: button::State, -} - -#[derive(Debug, Clone, Copy)] -enum Message { - ButtonPressed, -} - -impl Sandbox for Circles { - type Message = Message; - - fn new() -> Self { - Circles::default() - } - - fn title(&self) -> String { - String::from("Circles") - } - - fn update(&mut self, message: Message) { - match message { - Message::ButtonPressed => { - self.engine.state.button_pressed = true; - let start = SystemTime::now(); - let since_the_epoch = start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); - let nanos = since_the_epoch.subsec_nanos() as u64; - let radius = (nanos % 99) as f32; - self.engine.state.radius = radius; - self.engine.state.rand = rotate(self.engine.state.rand); - } - } - } - - fn view(&mut self) -> Element { - let button = Button::new(&mut self.button, Text::new("Push")) - .padding(10) - .on_press(Message::ButtonPressed); - let content = Column::new().push(button).push( - self.engine - .view() - .map(move |_message| Message::ButtonPressed), - ); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -mod engine { - use crate::rotate; - use iced::{ - canvas::{self, Canvas, Cursor, Frame, Geometry, Path}, - Color, Element, Length, Rectangle, - }; - use iced_native::Point; - use iced_native::Vector; - - #[derive(Default)] - pub struct State { - pub button_pressed: bool, - pub radius: f32, - pub rand: i64, - } - - pub struct Engine { - pub state: State, - } - - #[derive(Debug, Clone)] - pub enum Message {} - - impl Default for Engine { - fn default() -> Self { - Self { - state: State::default(), - } - } - } - - impl Engine { - pub fn view<'a>(&'a mut self) -> Element<'a, Message> { - Canvas::new(self) - .width(Length::Fill) - .height(Length::Fill) - .into() - } - } - - impl<'a> canvas::Program for Engine { - fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec { - let pos = cursor.position_in(&bounds); - let mut frame = Frame::new(bounds.size()); - let radius = self.state.radius; - let center = frame.center(); - if pos.is_some() { - let xdiff = pos.unwrap().x - center.x; - let ydiff = pos.unwrap().y - center.y; - let dist = (xdiff * xdiff + ydiff * ydiff).sqrt(); - if dist <= radius { - frame.translate(Vector { x: 100.0, y: 100.0 }); - frame.fill_text(format!( - "in circle one at distance {:.1} <= {:.1}", - dist, radius - )); - frame.translate(Vector { - x: -100.0, - y: -100.0, - }); - } - } - - let mut r = self.state.rand; - for _ in 0..10000 { - r = rotate(r); - let x = r % 200; - r = rotate(r); - let y = r % 200; - r = rotate(r); - let rad = r % 10; - let circle2 = Path::circle( - Point { - x: center.x + x as f32, - y: center.y + y as f32, - }, - rad as f32, - ); - r = rotate(r); - let c1 = 0.7 + (r % 1000) as f32 / 3000.0; - r = rotate(r); - let c2 = 0.7 + (r % 1000) as f32 / 3000.0; - r = rotate(r); - let c3 = 0.7 + (r % 1000) as f32 / 3000.0; - frame.fill(&circle2, Color::from_rgb(c1, c2, c3)); - } - - let circle1 = Path::circle(center, radius); - frame.fill(&circle1, Color::from_rgb(0.5, 0.5, 1.0)); - let circlex = Path::circle(center, 2.0); - frame.fill(&circlex, Color::from_rgb(0.0, 0.0, 0.0)); - - vec![frame.into_geometry()] - } - } -} diff --git a/enclone_visual/src/bin/print_clipboard.rs b/enclone_visual/src/bin/print_clipboard.rs deleted file mode 100644 index 93f26272f8..0000000000 --- a/enclone_visual/src/bin/print_clipboard.rs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. -// -// Print the contents of the clipboard, Mac only for now. - -use enclone_visual::*; - -fn main() { - let copy = get_clipboard_content(); - println!("{:?}", copy); -} diff --git a/enclone_visual/src/bin/print_phys.rs b/enclone_visual/src/bin/print_phys.rs deleted file mode 100644 index 0d667aad75..0000000000 --- a/enclone_visual/src/bin/print_phys.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Takes a single argument, the name of a PNG file. Print the pHYs chunk, which -// if present contains the physical pixel dimensions. -// See https://www.w3.org/TR/2003/REC-PNG-20031110/#11pHYs - -use crc::*; -use io_utils::*; -use pretty_trace::*; -use std::env; - -use std::io::{Read, Seek, SeekFrom}; -use string_utils::*; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - let filename = &args[1]; - let mut f = open_for_read![&filename]; - let mut pos = 8 as u64; - let mut found = false; - loop { - f.seek(SeekFrom::Start(pos)).unwrap(); - let mut x = vec![0 as u8; 4]; - let res = f.read_exact(&mut x); - if res.is_err() { - break; - } - let len = u32::from_be_bytes([x[0], x[1], x[2], x[3]]); - pos += 4; - f.seek(SeekFrom::Start(pos)).unwrap(); - let mut chunk_type = vec![0 as u8; 4]; - f.read_exact(&mut chunk_type).unwrap(); - pos += 4; - println!("found chunk of type {}", strme(&chunk_type)); - if chunk_type == b"pHYs" { - found = true; - f.seek(SeekFrom::Start(pos)).unwrap(); - f.read_exact(&mut x).unwrap(); - let xpix = u32::from_be_bytes([x[0], x[1], x[2], x[3]]); - f.seek(SeekFrom::Start(pos + 4)).unwrap(); - f.read_exact(&mut x).unwrap(); - let ypix = u32::from_be_bytes([x[0], x[1], x[2], x[3]]); - f.seek(SeekFrom::Start(pos + 8)).unwrap(); - let mut unit_spec = vec![0 as u8]; - f.read_exact(&mut unit_spec).unwrap(); - println!("\npixels per x unit = {}", xpix); - println!("pixels per y unit = {}", ypix); - println!("unit specifier = {}\n", unit_spec[0]); - f.seek(SeekFrom::Start(pos + 9)).unwrap(); - f.read_exact(&mut x).unwrap(); - let checksum = u32::from_be_bytes([x[0], x[1], x[2], x[3]]); - println!("checksum in file = {}", checksum); - f.seek(SeekFrom::Start(pos - 4)).unwrap(); - let mut bytes = vec![0 as u8; 13]; - f.read_exact(&mut bytes).unwrap(); - let crc = Crc::::new(&CRC_32_ISO_HDLC); - let cs = crc.checksum(&bytes); - println!("computed checksum = {}", cs); - // break; - } - pos += len as u64 + 4; - } - if !found { - println!("\nThere is no pHYs block.\n"); - } -} diff --git a/enclone_visual/src/bin/set_pixels_per_meter.rs b/enclone_visual/src/bin/set_pixels_per_meter.rs deleted file mode 100644 index 23d391b5d6..0000000000 --- a/enclone_visual/src/bin/set_pixels_per_meter.rs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. -// -// set_pixels_per_meter n in out -// -// Modify or add the pHYs chunk in a PNG file, to set the pixels per meter value to n. -// See https://www.w3.org/TR/2003/REC-PNG-20031110/#11pHYs -// See also print_phys.rs. -// -// Note that Mac tools including screen capture add an iDOT chunk. That's an undocumented -// apple-ism, which appears to interfer with pHYs. Googling will get you a partial structure -// description, obtained by reverse engineering. - -use crc::*; -use io_utils::*; -use pretty_trace::*; -use std::env; - -use std::io::{Read, Seek, SeekFrom, Write}; -use string_utils::*; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - let n = args[1].force_usize() as u32; - let (infile, outfile) = (&args[2], &args[3]); - - // Form the pHYs chunk. - - let mut bytes = Vec::::new(); - { - let mut data = Vec::::new(); - data.append(&mut n.to_be_bytes().to_vec()); - data.append(&mut n.to_be_bytes().to_vec()); - data.append(&mut vec![1 as u8]); - let len = 9 as u32; - bytes.append(&mut len.to_be_bytes().to_vec()); - bytes.append(&mut b"pHYs".to_vec()); - bytes.append(&mut data); - let crc = Crc::::new(&CRC_32_ISO_HDLC); - let cs = crc.checksum(&bytes[4..bytes.len()]); - bytes.append(&mut cs.to_be_bytes().to_vec()); - } - - // Copying the file, inserting a new pHYs chunk, and deleting the existing one. We put the - // new one right after the IHDR chunk. According to the spec, it needs to go after IHDR and - // before the first IDAT. - - let mut f = open_for_read![&infile]; - let mut file = open_for_write_new![&outfile]; - let mut header = vec![0 as u8; 8]; - f.read_exact(&mut header).unwrap(); - file.write_all(&header).unwrap(); - let mut first = true; - let mut pos = 8; - loop { - f.seek(SeekFrom::Start(pos)).unwrap(); - let mut x = vec![0 as u8; 4]; - let res = f.read_exact(&mut x); - if res.is_err() { - break; - } - let len = u32::from_be_bytes([x[0], x[1], x[2], x[3]]); - let total = len + 12; - f.seek(SeekFrom::Start(pos + 4)).unwrap(); - f.read_exact(&mut x).unwrap(); - if x != b"pHYs" { - f.seek(SeekFrom::Start(pos)).unwrap(); - let mut x = vec![0 as u8; total as usize]; - f.read_exact(&mut x).unwrap(); - file.write_all(&x).unwrap(); - } - if first { - file.write_all(&bytes).unwrap(); - first = false; - } - pos += total as u64; - } -} diff --git a/enclone_visual/src/bin/show_diffs.rs b/enclone_visual/src/bin/show_diffs.rs deleted file mode 100644 index c3f800a9d4..0000000000 --- a/enclone_visual/src/bin/show_diffs.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. -// -// Show differences for one test, after having run test_vis. - -use enclone_visual::compare_images::*; -use enclone_visual::testsuite::TESTS; -use pretty_trace::*; -use std::env; -use std::fs::File; -use std::io::Read; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - for i in 1..=TESTS.len() { - if TESTS[i - 1].2 == args[1] { - let (mut image_old, mut image_new) = (Vec::::new(), Vec::::new()); - let old_file = format!("enclone_visual/regression_images/{}.png", TESTS[i - 1].2); - let mut f = File::open(&old_file).unwrap(); - f.read_to_end(&mut image_old).unwrap(); - let new_file = format!("enclone_visual/outputs/{}.png", TESTS[i - 1].2); - let mut f = File::open(&new_file).unwrap(); - f.read_to_end(&mut image_new).unwrap(); - let (header, image_data_old) = png_decoder::decode(&image_old).unwrap(); - let (width, height) = (header.width as usize, header.height as usize); - println!("\nimage is {} x {}\n", width, height); - let (_, image_data_new) = png_decoder::decode(&image_new).unwrap(); - if image_data_old.len() != image_data_new.len() { - eprintln!("\nimage size for test {} changed", i); - std::process::exit(1); - } - let big_diffs = compare_images(&image_data_old, &image_data_new, width, height, true); - eprintln!( - "\nThere are {} big diffs for {}.\n", - big_diffs, - TESTS[i - 1].2 - ); - } - } -} diff --git a/enclone_visual/src/bin/test_png_conversion.rs b/enclone_visual/src/bin/test_png_conversion.rs deleted file mode 100644 index 99463b6783..0000000000 --- a/enclone_visual/src/bin/test_png_conversion.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// usage: test_png_conversion whatever.svg -// ==> generates whatever.png - -use enclone_tail::convert_svg_to_png::*; -use pretty_trace::*; -use std::env; -use string_utils::*; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - let svg_file = &args[1]; - let png_file = format!("{}.png", svg_file.rev_before(".svg")); - let svg = std::fs::read(&svg_file).unwrap(); - let png = convert_svg_to_png(&svg, 2000); - std::fs::write(&png_file, &png).unwrap(); -} diff --git a/enclone_visual/src/bin/test_svg.rs b/enclone_visual/src/bin/test_svg.rs deleted file mode 100644 index 1da08e2d61..0000000000 --- a/enclone_visual/src/bin/test_svg.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use enclone_visual::svg_to_geometry::*; -use pretty_trace::*; -use std::env; -use std::fs::read_to_string; - -fn main() { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - let s = read_to_string(&args[1]).unwrap(); - let g = svg_to_geometry(&s, true); - if g.is_none() { - eprintln!("failed\n"); - } -} diff --git a/enclone_visual/src/bin/test_vis.rs b/enclone_visual/src/bin/test_vis.rs deleted file mode 100644 index bc0d1646a7..0000000000 --- a/enclone_visual/src/bin/test_vis.rs +++ /dev/null @@ -1,693 +0,0 @@ -// Copyright (c) 2022 10X Genomics, Inc. All rights reserved. -// -// Run some tests of enclone visual on a Mac. -// -// As part of the tests, this opens a window. Ideally we would instead run this without opening -// a window, and that might be eventually possible, given changes on the roadmap for iced. -// -// The current images vary some from laptop to laptop, depending on hardware, OS, and personal -// configuration. Because of this, perhaps only one person can run this test "officially". -// However other people can create their own regression test results, and test against those, as -// described below. -// -// Create mode. This mode is invoked by adding the argument CREATE. This creates PNG images, -// which exist only locally, and are not in git. When the enclone repo is initialized, this needs -// to be run. You might also want to run it if you somehow mess up the images. Otherwise, do -// not run in this mode. Create mode also creates JPG images. -// -// Create PNG mode. Similar, invoked by CREATE_PNG, only creates PNG files. -// -// Unofficial mode. This mode is invoked by adding the argument UNOFFICIAL. This does not read or -// write files in regression_images, some of which are in git, and instead uses a directory -// unofficial_images. If you are running "unofficially" you need this. -// -// Local mode. This mode is invoked by adding the argument LOCAL. It does not run the remote -// tests, which is currently only possible at 10x. Local mode is also easier to run because it -// does not require compiling on two machines. -// -// Update mode. This mode is invoked by adding the argument UPDATE. This causing failing results -// to be replaced. -// -// If you are outside 10x, then the first time you run you should: -// test_vis CREATE UNOFFICIAL LOCAL -// and thereafter: -// test_vis UNOFFICIAL LOCAL. -// This will allow you to tell if, with fairly high probability, changes you make have an effect -// on enclone visual. However they cannot tell you with with certainty, and if you deliberately -// make a change, there is no mechanism for you to create the jpg files that need to be updated. -// -// Other arguments: -// QUIET. -// VERBOSE. -// TESTS=... (comma-separated list, subset of 1,2,3,4,5,main). -// PRINTER. -// -// -// This code works by comparing lowest resolution JPEG files. We use that format to avoid -// having larger files in git. A better solution would be to use lowest resolution -// JPEG2000 files, which would be even smaller. -// -// The tests use only public data. -// -// Part of these tests assume that you can connect to a server. Also we test receiving shares, -// and this could fail and mess things up if someone else happened to send a share. -// -// See also show_diffs. - -use enclone_core::tilde_expand_me; -use enclone_visual::compare_images::*; -use enclone_visual::messages::*; -use enclone_visual::testsuite::{metatests, TESTS}; -use enclone_visual::*; -use image::codecs::jpeg::JpegEncoder; -use image::ColorType::Rgba8; -use io_utils::*; -use jpeg_decoder::Decoder; -use perf_stats::*; -use pretty_trace::*; -use std::env; -use std::fs::{copy, File}; -use std::io::{BufReader, BufWriter, Read}; -use std::process::Command; -use std::time::Instant; -use string_utils::*; - -fn main() { - PrettyTrace::new().on(); - let tall = Instant::now(); - let args: Vec = env::args().collect(); - let mut update = false; - let mut quiet = false; - let mut verbose = false; - let mut printer = false; - let mut local = false; - let mut create = false; - let mut create_png = false; - let mut unofficial = false; - let mut tests = Vec::::new(); - for i in 1..args.len() { - if args[i] == "UPDATE" { - update = true; - } else if args[i] == "QUIET" { - quiet = true; - } else if args[i] == "VERBOSE" { - verbose = true; - } else if args[i] == "PRINTER" { - printer = true; - } else if args[i] == "LOCAL" { - local = true; - } else if args[i] == "CREATE" { - create = true; - } else if args[i] == "CREATE_PNG" { - create_png = true; - } else if args[i] == "UNOFFICIAL" { - unofficial = true; - } else if args[i].starts_with("TESTS=") { - tests = args[i] - .after("TESTS=") - .split(',') - .map(str::to_owned) - .collect(); - } else { - eprintln!("\nUnknown argument {}.\n", args[i]); - std::process::exit(1); - } - } - if !path_exists("enclone_visual") { - eprintln!("\nYou need to run this from the top level directory of the enclone repo.\n"); - std::process::exit(1); - } - let mut all_testnames = Vec::::new(); - let options = fs_extra::dir::CopyOptions::new(); - let source = "enclone_visual/tests/sample_visual"; - let target = "enclone_visual/outputs/sample_visual"; - if path_exists(&target) { - fs_extra::dir::remove("enclone_visual/outputs/sample_visual").unwrap(); - } - std::fs::create_dir_all("enclone_visual/outputs").unwrap(); - fs_extra::dir::copy(&source, "enclone_visual/outputs", &options).unwrap(); - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // TEST THAT REMOTE SHARE DIR HAS WORLD PERMISSIONS - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // This assumes that you have defined ENCLONE_CONFIG_DEFAULT. - // - // The reason for having this test is that if the remote share dir does not have world - // permissions, then some people may not be able to share. And the permissions on the remote - // share dir might get accidentally changed by git. - - if !local && tests.is_empty() { - let mut found = false; - for (key, value) in env::vars() { - if key == "ENCLONE_CONFIG_DEFAULT" { - found = true; - let host = value.before(":"); - let rdir = value.after(":").rev_before("/"); - let o = Command::new("ssh") - .arg(&host) - .arg(&format!("ls -l {}", rdir)) - .output() - .expect("failed to execute ssh for world permissions test"); - let out = strme(&o.stdout); - let mut found2 = false; - for line in out.lines() { - if line.ends_with(" share") { - found2 = true; - if line.as_bytes()[7..10].to_vec() != b"rwx".to_vec() { - eprintln!("\nThe remote share dir does not have world permissions.\n"); - std::process::exit(1); - } - } - } - if !found2 { - eprintln!("\nFailed to find remote share dir in {}:{}.\n", host, rdir); - std::process::exit(1); - } - } - } - if !found { - eprintln!("\nYou need to define ENCLONE_CONFIG_DEFAULT.\n"); - std::process::exit(1); - } - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // A UNIT TEST - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - test_fold(); - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // RUN A COUPLE TESTS IN LOCAL MODE - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - for n in [4, 5, 6].iter() { - if printer { - println!("running test {}", n); - } - let n = *n; - if tests.is_empty() || tests.contains(&format!("{}", n)) { - let metas = metatests()[n - 1].clone(); - let mut testnames = Vec::::new(); - for m in metas.iter() { - match m { - Message::SetName(x) => { - testnames.push(x.to_string()); - } - _ => {} - }; - } - for t in testnames.iter() { - let png = format!("enclone_visual/outputs/{}.png", t); - if path_exists(&png) { - std::fs::remove_file(&png).unwrap(); - } - } - let o = Command::new("enclone") - .arg(&"VIS") - .arg(&format!("META={}", n)) - .arg(&"VISUAL_DIR=enclone_visual/outputs/sample_visual") - .output() - .expect(&format!("failed to execute enclone visual metatest {}", n)); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone visual metatest {}\n", n); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - all_testnames.append(&mut testnames); - } - } - - // Reset sample_visual. - - if path_exists(&target) { - fs_extra::dir::remove("enclone_visual/outputs/sample_visual").unwrap(); - } - fs_extra::dir::copy(&source, "enclone_visual/outputs", &options).unwrap(); - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // RUN ARCHIVE TESTS IN LOCAL MODE - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - if tests.is_empty() || tests.contains(&"1".to_string()) { - let metas = metatests()[0].clone(); - let mut testnames = Vec::::new(); - for m in metas.iter() { - match m { - Message::SetName(x) => { - testnames.push(x.to_string()); - } - _ => {} - }; - } - for t in testnames.iter() { - let png = format!("enclone_visual/outputs/{}.png", t); - if path_exists(&png) { - std::fs::remove_file(&png).unwrap(); - } - } - let o = Command::new("enclone") - .arg(&"VIS") - .arg(&"META=1") - .arg(&"VISUAL_DIR=enclone_visual/outputs/sample_visual") - .output() - .expect("failed to execute enclone visual metatest 1"); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone visual metatest 1\n"); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - all_testnames.append(&mut testnames); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // RUN ARCHIVE TESTS IN REMOTE MODE - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // This is dangerous, because it tests receiving shares, and someone else could send a share - // before or during the test. Should change to restrict to receiving only shares from self. - - if !local && (tests.is_empty() || tests.contains(&"2".to_string())) { - if path_exists(&target) { - fs_extra::dir::remove("enclone_visual/outputs/sample_visual").unwrap(); - } - fs_extra::dir::copy(&source, "enclone_visual/outputs", &options).unwrap(); - let metas = metatests()[1].clone(); - let mut testnames = Vec::::new(); - for m in metas.iter() { - match m { - Message::SetName(x) => { - testnames.push(x.to_string()); - } - _ => {} - }; - } - for t in testnames.iter() { - let png = format!("enclone_visual/outputs/{}.png", t); - if path_exists(&png) { - std::fs::remove_file(&png).unwrap(); - } - } - let o = Command::new("enclone") - .arg(&"VIS=b") - .arg(&"META=2") - .arg(&"REQUIRE_COMPATIBLE") - .arg(&"VISUAL_DIR=enclone_visual/outputs/sample_visual") - .output() - .expect("failed to execute enclone visual metatest 2"); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone visual metatest 2\n"); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - all_testnames.append(&mut testnames); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // ANOTHER TEST - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - if printer { - println!("starting another test"); - } - if tests.is_empty() || tests.contains(&"3".to_string()) { - let metas = metatests()[2].clone(); - let mut testnames = Vec::::new(); - for m in metas.iter() { - match m { - Message::SetName(x) => { - testnames.push(x.to_string()); - } - _ => {} - }; - } - for t in testnames.iter() { - let png = format!("enclone_visual/outputs/{}.png", t); - if path_exists(&png) { - std::fs::remove_file(&png).unwrap(); - } - } - let o = Command::new("enclone") - .arg(&"VIS") - .arg("FAIL_ON_ERROR") - .arg(&"META=3") - .arg(&"VISUAL_DIR=enclone_visual/outputs/sample_visual") - .output() - .expect("failed to execute enclone visual metatest 3"); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone visual metatest 3\n"); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - all_testnames.append(&mut testnames); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // PRETEST - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Run enclone once to get it in cache. This doesn't totally make sense but seems to improve - // the reproducibility of timing of the actual work. - - if printer { - println!("starting pretest"); - } - if tests.is_empty() { - let o = Command::new("enclone") - .arg(&"--version") - .output() - .expect("failed to execute enclone visual pretest"); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone visual pretest\n"); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // RUN MAIN TESTS - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - if printer { - println!("running main tests"); - } - let t = Instant::now(); - if tests.is_empty() || tests.contains(&"main".to_string()) { - let o = Command::new("enclone") - .arg(&"VIS") - .arg(&"TEST") - .arg(&"VISUAL_DIR=enclone_visual/tests/sample_visual") - .output() - .expect("failed to execute enclone visual test"); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone visual test\n"); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - if !quiet { - print!("{}", strme(&o.stdout)); - } - for i in 0..TESTS.len() { - if TESTS[i].2.len() > 0 { - all_testnames.push(TESTS[i].2.to_string()); - } - } - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // CHECK TESTS VERSUS REGRESSION OUTPUTS - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - let mut fail = false; - const MAX_DIFFS: usize = 450; - let reg = if !unofficial { - "regression_images" - } else { - "unofficial_images" - }; - if unofficial { - std::fs::create_dir_all("enclone_visual/unofficial_images").unwrap(); - } - for i in 0..all_testnames.len() { - let mut image_new = Vec::::new(); - let old_png_file = format!("enclone_visual/{reg}/{}.png", all_testnames[i]); - let new_png_file = format!("enclone_visual/outputs/{}.png", all_testnames[i]); - let mut f = File::open(&new_png_file).unwrap(); - f.read_to_end(&mut image_new).unwrap(); - let (header, image_data_new0) = png_decoder::decode(&image_new).unwrap(); - let (width, height) = (header.width as usize, header.height as usize); - - // Convert the new png file to a jpg, and read that back in as a bit image. - - let new_jpg_file = format!("{}.jpg", new_png_file.rev_before(".png")); - { - let quality = 1 as u8; // lowest quality - if path_exists(&new_jpg_file) { - // This file removal is to circumvent a bug in Carbon Black. - std::fs::remove_file(&new_jpg_file).unwrap(); - } - let mut f = open_for_write_new![&new_jpg_file]; - let mut buff = BufWriter::new(&mut f); - let mut encoder = JpegEncoder::new_with_quality(&mut buff, quality); - encoder - .encode(&image_data_new0, width as u32, height as u32, Rgba8) - .unwrap(); - } - let file = open_for_read![&new_jpg_file]; - let mut decoder_new = Decoder::new(BufReader::new(file)); - let image_data_new = decoder_new.decode().expect("failed to decode image"); - - // In create mode, just copy file. - - let old_jpg_file = format!("{}.jpg", old_png_file.rev_before(".png")); - if create || create_png { - copy(&new_png_file, &old_png_file).unwrap(); - if create { - copy(&new_jpg_file, &old_jpg_file).unwrap(); - } - continue; - } - - // Check for existence of old jpg file. - - if !path_exists(&old_jpg_file) { - eprintln!( - "\nLooks like you've added a test. Please look at \ - enclone_visual/outputs/{}.png and\n\ - if it's right, copy it and the jpg file to regression_tests and git add the jpg.\n", - all_testnames[i], - ); - std::process::exit(1); - } - - // Read in the old jpg file as a bit image. - - let file = open_for_read![&old_jpg_file]; - let mut decoder_old = Decoder::new(BufReader::new(file)); - let image_data_old = decoder_old.decode().expect("failed to decode image"); - - // Test for differences. - - if image_data_old.len() != image_data_new.len() { - eprintln!( - "\nimage size for {} = {} changed from {} x {} to {} x {}", - i, - all_testnames[i], - decoder_old.info().unwrap().width, - decoder_old.info().unwrap().height, - decoder_new.info().unwrap().width, - decoder_new.info().unwrap().height, - ); - fail = true; - } else { - let diffs = compare_images(&image_data_old, &image_data_new, width, height, verbose); - if diffs > MAX_DIFFS { - eprintln!( - "\nThere are {} diffs for {}. Please open enclone_visual/outputs/\ - joint.{}.jpg.", - diffs, all_testnames[i], all_testnames[i] - ); - - // Create and save concatenated image. Note that we're depending on the png - // in regression_images as being current. We could do the same thing with the jpg - // versions, which would be guaranteed to be correct, but of lower quality. We did - // this in 8949a053552c478af5c952ee407416d0e52ab8a0 of dj/189, if you want to go - // back to that. - - if !path_exists(&old_png_file) { - eprintln!( - "\nThe file\n{old_png_file}\nis missing. If you have never run \ - test_vis before, then probably you should run either\n\ - test_vis CREATE [if you're at 10x]\nor\n\ - test_vis CREATE LOCAL [if not]\n" - ); - std::process::exit(1); - } - let mut f = File::open(&old_png_file).unwrap(); - let mut image_old = Vec::::new(); - f.read_to_end(&mut image_old).unwrap(); - let (_, image_data_old0) = png_decoder::decode(&image_old).unwrap(); - if image_data_old0.len() != width * height * 4 { - eprintln!( - "\nThe size of {} is wrong, so it is probably corrupted.\n", - old_png_file - ); - eprintln!( - "You may want to checkout master and run with CREATE_PNG to \ - regenerate valid PNG files.\n" - ); - std::process::exit(1); - } - let mut joint = Vec::::new(); - for i in 0..height { - let start = i * width * 4; - let stop = (i + 1) * width * 4; - joint.append(&mut image_data_old0[start..stop].to_vec()); - joint.append(&mut image_data_new0[start..stop].to_vec()); - for j in start..stop { - let diff = image_data_new0[j].wrapping_sub(image_data_old0[j]); - joint.push(255 - diff); - } - } - let new_jpg_file = format!("enclone_visual/outputs/joint.{}.jpg", all_testnames[i]); - let quality = 80 as u8; - let mut f = open_for_write_new![&new_jpg_file]; - let mut buff = BufWriter::new(&mut f); - let mut encoder = JpegEncoder::new_with_quality(&mut buff, quality); - encoder - .encode(&joint, (width * 3) as u32, height as u32, Rgba8) - .unwrap(); - - // Keep going. - - fail = true; - if update { - copy(&new_png_file, &old_png_file).unwrap(); - copy(&new_jpg_file, &old_jpg_file).unwrap(); - } - } - } - } - let state = if fail { - "UNSUCCESSFULLY" - } else { - "successfully" - }; - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // TEST COMPUTATIONAL PERFORMANCE - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - let used = elapsed(&t); - if tests.is_empty() { - const EXPECTED_TIME: f64 = 49.4; // this is supposed to be the lowest observed value - const MAX_PERCENT_OVER: f64 = 4.2; - let percent_over = 100.0 * (used - EXPECTED_TIME) / EXPECTED_TIME; - if percent_over > MAX_PERCENT_OVER { - eprintln!( - "\nUsed {:.1} seconds, exceeding expected test time of {:.1} seconds by {:.1}%, \ - versus max allowed = {}%.", - used, EXPECTED_TIME, percent_over, MAX_PERCENT_OVER, - ); - eprintln!( - "You might want to retry a second time. Note that if you're disconnected from\n\ - the internet, then the Mac Gatekeeper could introduce very long delays.\n" - ); - std::process::exit(1); - } - - // Get peak memory. This is sensitive to changes of a few percent or so. - - #[cfg(not(target_os = "windows"))] - { - let maxrss_children; - unsafe { - let mut rusage: libc::rusage = std::mem::zeroed(); - let retval = libc::getrusage(libc::RUSAGE_CHILDREN, &mut rusage as *mut _); - assert_eq!(retval, 0); - maxrss_children = rusage.ru_maxrss; - } - let peak_mem_mb = maxrss_children as f64 / ((1024 * 1024) as f64); - const MAX_PEAK_MEM: f64 = 168.2; // this is supposed to be the lowest observed value - const MAX_PERCENT_OVER_MEM: f64 = 17.6; - let percent_over = 100.0 * (peak_mem_mb - MAX_PEAK_MEM) / MAX_PEAK_MEM; - - eprintln!( - "\nPeak mem {:.1} MB, exceeded expected peak mem of {:.1} MB by {:.1}%, \ - versus max allowed = {}%.", - peak_mem_mb, MAX_PEAK_MEM, percent_over, MAX_PERCENT_OVER_MEM, - ); - if percent_over > MAX_PERCENT_OVER_MEM { - eprintln!("That's too high. This happens occasionally, so please retry.\n"); - eprintln!( - "Also the value is probably different if you're using a Mac with an \ - Apple chip.\n" - ); - std::process::exit(1); - } - } - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // TEST FOR STRAY PROCESSES - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - if tests.is_empty() { - let o = Command::new("ps") - .arg(&"ux") - .output() - .expect("failed to execute ps"); - let out = strme(&o.stdout); - for line in out.lines() { - if line.contains("ssh -p") { - eprintln!( - "\nLooks like you may have a stray process running:\n{}\n\n\ - Treating this as an error.\n", - line - ); - std::process::exit(1); - } - } - for (key, value) in env::vars() { - if key == "ENCLONE_CONFIG" { - let host = value.before(":"); - let o = Command::new("ssh") - .arg(&host) - .arg(&"ps x") - .output() - .expect("failed to execute ssh"); - let out = strme(&o.stdout); - for line in out.lines() { - if line.contains("enclone SERVER") { - eprintln!( - "\nLooks like you may have a stray process running on the \ - remote server:\n{}\n\n\ - Treating this as an error.\n", - line - ); - std::process::exit(1); - } - } - } - } - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // MAC TESTS THAT DON'T REALLY BELONG HERE BUT DON'T HAVE A BETTER HOME - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Test that a particular case of tilde expansion works on a Mac. - - if tests.is_empty() { - let o = Command::new("enclone") - .arg("BCR=123085") - .arg("MIN_CELLS=10") - .arg("PLOT_BY_ISOTYPE=gui") - .arg("HONEY_OUT=~/enclone_temp_test_file") - .arg("NOPRINT") - .output() - .expect("failed to execute enclone tilde test"); - if o.status.code() != Some(0) { - eprintln!("\nnonzero exit code from enclone tilde test\n"); - eprintln!("stderr =\n{}", strme(&o.stderr)); - std::process::exit(1); - } - let mut f = "~/enclone_temp_test_file".to_string(); - tilde_expand_me(&mut f); - std::fs::remove_file(&f).unwrap(); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - // DONE, REPORT STATUS - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - println!( - "\nenclone visual tests completed {} in {:.1} seconds", - state, used, - ); - println!("actual total time = {:.1} seconds\n", elapsed(&tall)); - if fail { - std::process::exit(1); - } -} diff --git a/enclone_visual/src/canvas_view.rs b/enclone_visual/src/canvas_view.rs deleted file mode 100644 index ad93b7d8dd..0000000000 --- a/enclone_visual/src/canvas_view.rs +++ /dev/null @@ -1,636 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::dimensions::*; -use crate::GROUP_ID; -use crate::GROUP_ID_CLICKED_ON; -use crate::*; -use enclone_tail::string_width::*; -use iced::canvas::event::{self, Event}; -use iced::{ - alignment, - canvas::{self, Canvas, Cursor, Frame, Geometry, Path, Stroke, Text}, - mouse, Color, Element, Length, Rectangle, Size, -}; -use iced_native::{Point, Vector}; -use lazy_static::lazy_static; -use std::sync::atomic::AtomicBool; -use std::sync::atomic::Ordering::SeqCst; -use std::sync::Mutex; - -lazy_static! { - pub static ref IN_GEOMETRIES: Mutex> = - Mutex::new(Vec::::new()); - pub static ref OUT_GEOMETRIES: Mutex> = Mutex::new(Vec::::new()); - pub static ref OUT_GEOMETRIES_TOOLTIP: Mutex> = - Mutex::new(Vec::::new()); - pub static ref POS: Mutex = Mutex::new(Point::default()); -} -pub static POS_IS_SOME: AtomicBool = AtomicBool::new(false); - -#[derive(Default)] -pub struct State { - pub geometry_value: Option>, -} - -pub struct CanvasView { - pub state: State, -} - -#[derive(Debug, Clone)] -pub enum Message { - DoNothing, - GroupClick, -} - -impl Default for CanvasView { - fn default() -> Self { - Self { - state: State::default(), - } - } -} - -impl CanvasView { - pub fn view<'a>(&'a mut self) -> Element<'a, Message> { - Canvas::new(self) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} - -fn to_color(c: &crate::geometry::Color) -> Color { - Color { - r: c.r as f32 / 255.0, - g: c.g as f32 / 255.0, - b: c.b as f32 / 255.0, - a: c.t as f32 / 255.0, - } -} - -impl CanvasView { - fn dimensions(&self) -> (f32, f32) { - let g = self.state.geometry_value.as_ref().unwrap(); - let mut height = 0.0 as f32; - let mut width = 0.0 as f32; - for i in 0..g.len() { - match &g[i] { - crate::geometry::Geometry::Text(o) => { - height = height.max(o.p.y); - let mut tmax = o.p.x; - // what about dejavusans? - if o.font == "Arial" { - tmax += arial_width(&o.t, o.font_size as f64) as f32; - } - width = width.max(tmax); - } - crate::geometry::Geometry::Rectangle(rect) => { - height = height.max(rect.p.y + rect.height + rect.stroke_width); - width = width.max(rect.p.x + rect.width + rect.stroke_width); - } - crate::geometry::Geometry::PolySegment(segs) => { - for i in 0..segs.p.len() - 1 { - height = height.max(segs.p[i].y); - width = width.max(segs.p[i].x); - } - } - crate::geometry::Geometry::Segment(seg) => { - height = height.max(seg.p1.y); - height = height.max(seg.p2.y); - width = width.max(seg.p1.x); - width = width.max(seg.p2.x); - } - crate::geometry::Geometry::CircleWithTooltip(circ) => { - height = height.max(circ.p.y + circ.r); - width = width.max(circ.p.x + circ.r); - } - crate::geometry::Geometry::CircleWithTooltipAndStroke(circ) => { - height = height.max(circ.p.y + circ.r); - width = width.max(circ.p.x + circ.r); - } - crate::geometry::Geometry::Circle(circ) => { - height = height.max(circ.p.y + circ.r); - width = width.max(circ.p.x + circ.r); - } - crate::geometry::Geometry::CircleWithStroke(circ) => { - height = height.max(circ.p.y + circ.r); - width = width.max(circ.p.x + circ.r); - } - }; - } - (width, height) - } -} - -impl<'a> canvas::Program for CanvasView { - fn update( - &mut self, - event: Event, - bounds: Rectangle, - cursor: Cursor, - ) -> (event::Status, Option) { - let _cursor_position = if let Some(position) = cursor.position_in(&bounds) { - position - } else { - return (event::Status::Ignored, None); - }; - match event { - Event::Mouse(mouse_event) => match mouse_event { - mouse::Event::ButtonPressed(button) => { - let message = match button { - mouse::Button::Left => { - let g = self.state.geometry_value.as_ref().unwrap(); - let (width, height) = self.dimensions(); - let scale = get_graphic_scale(width, height, g.len() == 1); - let mut group_id = None; - let pos = cursor.position_in(&bounds); - for i in 0..g.len() { - match &g[i] { - crate::geometry::Geometry::CircleWithTooltip(circ) => { - let xdiff = pos.unwrap().x - circ.p.x * scale; - let ydiff = pos.unwrap().y - circ.p.y * scale; - let dist = (xdiff * xdiff + ydiff * ydiff).sqrt(); - if dist <= circ.r { - let stext = circ.t.clone(); - let xs = stext.split(',').collect::>(); - for j in 0..xs.len() { - if xs[j].starts_with("group_id=") { - group_id = Some(xs[j].after("=").force_usize()); - } - } - let group_id = group_id.unwrap(); - GROUP_ID_CLICKED_ON.store(true, SeqCst); - GROUP_ID.store(group_id, SeqCst); - break; - } - } - crate::geometry::Geometry::CircleWithTooltipAndStroke(circ) => { - let xdiff = pos.unwrap().x - circ.p.x * scale; - let ydiff = pos.unwrap().y - circ.p.y * scale; - let dist = (xdiff * xdiff + ydiff * ydiff).sqrt(); - if dist <= circ.r { - let stext = circ.t.clone(); - let xs = stext.split(',').collect::>(); - for j in 0..xs.len() { - if xs[j].starts_with("group_id=") { - group_id = Some(xs[j].after("=").force_usize()); - } - } - let group_id = group_id.unwrap(); - GROUP_ID_CLICKED_ON.store(true, SeqCst); - GROUP_ID.store(group_id, SeqCst); - break; - } - } - _ => {} - } - } - if group_id.is_some() { - Some(Message::GroupClick) - } else { - None - } - } - _ => None, - }; - (event::Status::Captured, message) - } - _ => (event::Status::Captured, None), - }, - _ => (event::Status::Captured, None), - } - } - - fn draw(&self, bounds: Rectangle, cursor: Cursor) -> Vec { - // Suppose there is no geometry. - - if self.state.geometry_value.is_none() { - POS_IS_SOME.store(false, SeqCst); - IN_GEOMETRIES.lock().unwrap().clear(); - return Vec::new(); - } - - // Suppose we have geometries. - - let pos = cursor.position_in(&bounds); - - // Use cached geometries if possible. - // - // Annoyingly, can't do this: - // if pos_changed = POS.lock().unwrap() != pos { - // or - // if IN_GEOMETRIES.lock().unwrap() == self.state.geometry_value.as_ref().unwrap() { - - let mut pos_same = true; - let last_pos_is_some = POS_IS_SOME.load(SeqCst); - if !last_pos_is_some && pos.is_none() { - } else if last_pos_is_some && pos.is_none() { - pos_same = false; - } else if !last_pos_is_some && pos.is_some() { - pos_same = false; - } else if POS.lock().unwrap().x != pos.unwrap().x { - pos_same = false; - } else if POS.lock().unwrap().y != pos.unwrap().y { - pos_same = false; - } - let mut geom_same = true; - let in_geometries = &self.state.geometry_value.as_ref().unwrap(); - if IN_GEOMETRIES.lock().unwrap().len() != in_geometries.len() { - geom_same = false; - } else { - for i in 0..in_geometries.len() { - if IN_GEOMETRIES.lock().unwrap()[i] != in_geometries[i] { - geom_same = false; - break; - } - } - } - let mut size_same = true; - if CURRENT_WIDTH.load(SeqCst) != CURRENT_WIDTH_LAST_SEEN.load(SeqCst) { - size_same = false; - CURRENT_WIDTH_LAST_SEEN.store(CURRENT_WIDTH.load(SeqCst), SeqCst); - } - if CURRENT_HEIGHT.load(SeqCst) != CURRENT_HEIGHT_LAST_SEEN.load(SeqCst) { - size_same = false; - CURRENT_HEIGHT_LAST_SEEN.store(CURRENT_HEIGHT.load(SeqCst), SeqCst); - } - let gmode = GRAPHIC_MODE.load(SeqCst); - if gmode != GRAPHIC_MODE_LAST_SEEN.load(SeqCst) { - size_same = false; - GRAPHIC_MODE_LAST_SEEN.store(gmode, SeqCst); - } - if pos_same && geom_same && size_same { - let mut v = OUT_GEOMETRIES.lock().unwrap().clone(); - v.append(&mut OUT_GEOMETRIES_TOOLTIP.lock().unwrap().clone()); - return v; - } - if !geom_same { - IN_GEOMETRIES.lock().unwrap().clear(); - IN_GEOMETRIES - .lock() - .unwrap() - .append(&mut self.state.geometry_value.as_ref().unwrap().clone()); - } - if pos.is_none() { - POS_IS_SOME.store(false, SeqCst); - } else { - POS.lock().unwrap().x = pos.unwrap().x; - POS.lock().unwrap().y = pos.unwrap().y; - } - - // Compute width and height and scale. - // - // for now not scaling stroke width, not sure what is optimal - // scaling seems to be needed only because .height(SVG_WIDTH) doesn't work on a canvas - // should file bug - // This could be 400.0 but we would need to take account of text width - // in computing the max. - - let g = self.state.geometry_value.as_ref().unwrap(); - let (width, height) = self.dimensions(); - let scale = get_graphic_scale(width, height, g.len() == 1); - - // Rebuild geometries if needed. - - let mut v; - if geom_same && size_same { - v = OUT_GEOMETRIES.lock().unwrap().clone(); - } else { - let mut frame = Frame::new(bounds.size()); - for i in 0..g.len() { - match &g[i] { - crate::geometry::Geometry::Text(o) => { - // rotate not implemented because not a feature yet in iced - let x = Text { - content: o.t.clone(), - size: o.font_size * scale, - color: to_color(&o.c), - position: Point { - x: o.p.x * scale, - // font bit is compensation for vertical alignment issue - // don't understand why / 4.0 makes sense - y: o.p.y * scale + o.font_size * scale / 4.0, - }, - font: match o.font.as_str() { - "DejaVuSansMono" => DEJAVU, - "Arial" => LIBERATION_SANS, - _ => LIBERATION_SANS, - }, - // Center doesn't seem to work, should report bug - // nor does Top - vertical_alignment: alignment::Vertical::Bottom, - horizontal_alignment: match o.halign { - crate::geometry::HorizontalAlignment::Left => { - alignment::Horizontal::Left - } - crate::geometry::HorizontalAlignment::Center => { - alignment::Horizontal::Center - } - crate::geometry::HorizontalAlignment::Right => { - alignment::Horizontal::Right - } - }, - }; - frame.fill_text(x); - } - crate::geometry::Geometry::Rectangle(rect) => { - let r = Path::rectangle( - Point { - x: rect.p.x * scale, - y: rect.p.y * scale, - }, - Size::new(rect.width * scale, rect.height * scale), - ); - frame.fill(&r, to_color(&rect.fill_color)); - let c = to_color(&rect.stroke_color); - frame.stroke( - &r, - Stroke::default() - .with_color(c) - .with_width(rect.stroke_width), - ); - } - crate::geometry::Geometry::PolySegment(segs) => { - for i in 0..segs.p.len() - 1 { - let p = Path::line( - Point { - x: segs.p[i].x * scale, - y: segs.p[i].y * scale, - }, - Point { - x: segs.p[i + 1].x * scale, - y: segs.p[i + 1].y * scale, - }, - ); - let c = to_color(&segs.c); - frame.stroke(&p, Stroke::default().with_color(c).with_width(segs.w)); - } - } - crate::geometry::Geometry::Segment(seg) => { - let p = Path::line( - Point { - x: seg.p1.x * scale, - y: seg.p1.y * scale, - }, - Point { - x: seg.p2.x * scale, - y: seg.p2.y * scale, - }, - ); - let c = to_color(&seg.c); - frame.stroke(&p, Stroke::default().with_color(c).with_width(seg.w)); - } - crate::geometry::Geometry::CircleWithTooltip(circ) => { - let circle = Path::circle( - Point { - x: circ.p.x * scale, - y: circ.p.y * scale, - }, - circ.r * scale, - ); - let c = &circ.c; - frame.fill(&circle, to_color(c)); - } - crate::geometry::Geometry::CircleWithTooltipAndStroke(circ) => { - let circle = Path::circle( - Point { - x: circ.p.x * scale, - y: circ.p.y * scale, - }, - circ.r * scale, - ); - let c = &circ.c; - frame.fill(&circle, to_color(c)); - frame.stroke( - &circle, - Stroke::default() - .with_color(to_color(&circ.s)) - .with_width(circ.w), - ); - } - crate::geometry::Geometry::Circle(circ) => { - let circle = Path::circle( - Point { - x: circ.p.x * scale, - y: circ.p.y * scale, - }, - circ.r * scale, - ); - let c = &circ.c; - frame.fill(&circle, to_color(c)); - } - crate::geometry::Geometry::CircleWithStroke(circ) => { - let circle = Path::circle( - Point { - x: circ.p.x * scale, - y: circ.p.y * scale, - }, - circ.r * scale, - ); - let c = &circ.c; - frame.fill(&circle, to_color(c)); - frame.stroke( - &circle, - Stroke::default() - .with_color(to_color(&circ.s)) - .with_width(circ.w), - ); - } - }; - } - v = vec![frame.into_geometry()]; - OUT_GEOMETRIES.lock().unwrap().clear(); - OUT_GEOMETRIES.lock().unwrap().append(&mut v.clone()); - } - if pos_same && pos.is_some() { - v.append(&mut OUT_GEOMETRIES_TOOLTIP.lock().unwrap().clone()); - } - if !pos_same && pos.is_some() { - let mut frame = Frame::new(bounds.size()); - for i in 0..g.len() { - match &g[i] { - // - // NOTE MASSIVE CODE DUPLICATION HERE. - // - crate::geometry::Geometry::CircleWithTooltip(circ) => { - let xdiff = pos.unwrap().x - circ.p.x * scale; - let ydiff = pos.unwrap().y - circ.p.y * scale; - let dist = (xdiff * xdiff + ydiff * ydiff).sqrt(); - if dist <= circ.r { - let stext = circ.t.clone(); - let xs = stext.split(',').collect::>(); - let mut rows = Vec::>::new(); - for i in 0..xs.len() { - if i > 0 { - rows.push(vec!["\\hline".to_string(); 2]); - } - let mut row = Vec::::new(); - row.push(xs[i].before("=").to_string()); - row.push(xs[i].after("=").to_string()); - rows.push(row); - } - let mut log = String::new(); - print_tabular_vbox(&mut log, &rows, 0, &b"l|r".to_vec(), false, true); - let tooltip_font_size: f32 = 13.5; - let (box_width, box_height) = dejavu_text_dim(&log, tooltip_font_size); - let xpos; - let ypos; - let fudge = 40.0; - let tt = TOOLTIP_POS.load(SeqCst); - if tt == 0 { - xpos = (bounds.x + bounds.width) - box_width - fudge; - ypos = 0.0; - } else if tt == 1 { - xpos = (bounds.x + bounds.width) - box_width - fudge; - ypos = bounds.height - box_height; - } else if tt == 2 { - xpos = 0.0; - ypos = bounds.height - box_height; - } else { - xpos = 0.0; - ypos = 0.0; - } - frame.translate(Vector { x: xpos, y: ypos }); - - TOOLTIP_TEXT.lock().unwrap().clear(); - TOOLTIP_TEXT.lock().unwrap().push(log.clone()); - - let mut logp = String::new(); - for char in log.chars() { - if char == '\n' { - logp.push(char); - } else { - logp.push('█'); - } - } - - // TO UPDATE THIS DOC. - // We put a layer of black below the tooltip text, which is going to - // be white. There are two approaches. First, if the tooltip box lies - // strictly within the canvas (and not to the right of it), we display - // a black rectangle. Otherwise, we contruct the layer out of box - // characters. This is not fully satisfactory because there are small - // gaps between them. - - frame.fill_rectangle( - Point { x: 0.0, y: 0.0 }, - Size { - width: box_width, - height: box_height, - }, - iced::canvas::Fill::from(Color::WHITE), - ); - - // Now display the actual text in the tooltip box. - - let text = canvas::Text { - content: log, - size: tooltip_font_size, - font: DEJAVU_BOLD, - color: Color::from_rgb(0.5, 0.0, 0.5), - ..canvas::Text::default() - }; - frame.fill_text(text); - - frame.translate(Vector { x: -xpos, y: -ypos }); - break; - } - } - crate::geometry::Geometry::CircleWithTooltipAndStroke(circ) => { - let xdiff = pos.unwrap().x - circ.p.x * scale; - let ydiff = pos.unwrap().y - circ.p.y * scale; - let dist = (xdiff * xdiff + ydiff * ydiff).sqrt(); - if dist <= circ.r { - let stext = circ.t.clone(); - let xs = stext.split(',').collect::>(); - let mut rows = Vec::>::new(); - for i in 0..xs.len() { - if i > 0 { - rows.push(vec!["\\hline".to_string(); 2]); - } - let mut row = Vec::::new(); - row.push(xs[i].before("=").to_string()); - row.push(xs[i].after("=").to_string()); - rows.push(row); - } - let mut log = String::new(); - print_tabular_vbox(&mut log, &rows, 0, &b"l|r".to_vec(), false, true); - let tooltip_font_size: f32 = 13.5; - let (box_width, box_height) = dejavu_text_dim(&log, tooltip_font_size); - let xpos; - let ypos; - let fudge = 40.0; - let tt = TOOLTIP_POS.load(SeqCst); - if tt == 0 { - xpos = (bounds.x + bounds.width) - box_width - fudge; - ypos = 0.0; - } else if tt == 1 { - xpos = (bounds.x + bounds.width) - box_width - fudge; - ypos = bounds.height - box_height; - } else if tt == 2 { - xpos = 0.0; - ypos = bounds.height - box_height; - } else { - xpos = 0.0; - ypos = 0.0; - } - frame.translate(Vector { x: xpos, y: ypos }); - - TOOLTIP_TEXT.lock().unwrap().clear(); - TOOLTIP_TEXT.lock().unwrap().push(log.clone()); - - let mut logp = String::new(); - for char in log.chars() { - if char == '\n' { - logp.push(char); - } else { - logp.push('█'); - } - } - - // TO UPDATE THIS DOC. - // We put a layer of black below the tooltip text, which is going to - // be white. There are two approaches. First, if the tooltip box lies - // strictly within the canvas (and not to the right of it), we display - // a black rectangle. Otherwise, we contruct the layer out of box - // characters. This is not fully satisfactory because there are small - // gaps between them. - - frame.fill_rectangle( - Point { x: 0.0, y: 0.0 }, - Size { - width: box_width, - height: box_height, - }, - iced::canvas::Fill::from(Color::WHITE), - ); - - // Now display the actual text in the tooltip box. - - let text = canvas::Text { - content: log, - size: tooltip_font_size, - font: DEJAVU_BOLD, - color: Color::from_rgb(0.5, 0.0, 0.5), - ..canvas::Text::default() - }; - frame.fill_text(text); - - frame.translate(Vector { x: -xpos, y: -ypos }); - break; - } - } - _ => {} - }; - } - let mut w = vec![frame.into_geometry()]; - OUT_GEOMETRIES_TOOLTIP.lock().unwrap().clear(); - OUT_GEOMETRIES_TOOLTIP - .lock() - .unwrap() - .append(&mut w.clone()); - v.append(&mut w); - } - v - } -} diff --git a/enclone_visual/src/client_requests.rs b/enclone_visual/src/client_requests.rs deleted file mode 100644 index b029bfeb5e..0000000000 --- a/enclone_visual/src/client_requests.rs +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Process commands via the server in the background. - -use crate::proto::{analyzer_client::AnalyzerClient, *}; -use crate::summary::*; -use crate::*; -use std::io::Read; -use std::process::Child; -use std::sync::atomic::Ordering::SeqCst; -use std::thread; -use std::time::Duration; -use tonic::transport::Channel; - -pub async fn process_requests( - client: &mut AnalyzerClient, - server_process: &mut Child, - verbose: bool, -) { - loop { - thread::sleep(Duration::from_millis(10)); - if DONE.load(SeqCst) { - cleanup(); - std::process::exit(0); - } - - if GET_MY_COOKBOOKS.load(SeqCst) { - let cookbook_dirs = COOKBOOK_DIRS.lock().unwrap().clone(); - let request = tonic::Request::new(GetMyCookbooksRequest { - cookbook_dirs: cookbook_dirs, - }); - let response = client.get_my_cookbooks(request).await; - if response.is_err() { - eprintln!("Attempt to get cookbooks failed."); - let err = format!("{:?}", response); - eprintln!("err = {}\n", err); - eprintln!("Please ask for help!\n"); - std::process::exit(1); - } - let res = response.unwrap().into_inner(); - for i in 0..res.cookbooks.len() { - REMOTE_COOKBOOKS - .lock() - .unwrap() - .push(res.cookbooks[i].clone()); - } - GET_MY_COOKBOOKS.store(false, SeqCst); - } - - if SENDING_SHARE.load(SeqCst) { - let share_dir = REMOTE_SHARE.lock().unwrap()[0].clone(); - let sender = whoami::username(); - let content = SHARE_CONTENT.lock().unwrap()[0].clone(); - let nrecip = SHARE_RECIPIENTS.lock().unwrap().len(); - let mut recipients = Vec::::new(); - for i in 0..nrecip { - recipients.push(SHARE_RECIPIENTS.lock().unwrap()[i].clone()); - } - let request = tonic::Request::new(SendShareRequest { - share_dir: share_dir, - content: content, - sender: sender, - recipients: recipients, - }); - let response = client.share_session(request).await; - if response.is_err() { - eprintln!("Attempt to share session failed."); - let err = format!("{:?}", response); - eprintln!("err = {}\n", err); - eprintln!("Please ask for help!\n"); - std::process::exit(1); - } - SENDING_SHARE.store(false, SeqCst); - } - - if GET_MY_SHARES.load(SeqCst) { - let share_dir = REMOTE_SHARE.lock().unwrap()[0].clone(); - let request = tonic::Request::new(GetMySharesRequest { - share_dir: share_dir, - me_only: META_TESTING.load(SeqCst), - }); - let response = client.get_my_shares(request).await; - if response.is_err() { - eprintln!("Attempt to retrieve shared sessions failed."); - let err = format!("{:?}", response); - eprintln!("err = {}\n", err); - eprintln!("Please ask for help!\n"); - std::process::exit(1); - } - let res = response.unwrap().into_inner(); - let n = res.content.len(); - for i in 0..n { - RECEIVED_SHARES_CONTENT - .lock() - .unwrap() - .push(res.content[i].clone()); - RECEIVED_SHARES_MESSAGES - .lock() - .unwrap() - .push(res.messages[i].clone()); - RECEIVED_SHARES_FILENAMES - .lock() - .unwrap() - .push(res.filenames[i].clone()); - } - GET_MY_SHARES.store(false, SeqCst); - } - - if RELEASE_MY_SHARES.load(SeqCst) { - let share_dir = REMOTE_SHARE.lock().unwrap()[0].clone(); - let n = RECEIVED_SHARES_FILENAMES.lock().unwrap().len(); - let mut filenames = Vec::::new(); - for i in 0..n { - filenames.push(RECEIVED_SHARES_FILENAMES.lock().unwrap()[i].clone()); - } - let request = tonic::Request::new(ReleaseMySharesRequest { - share_dir: share_dir, - filenames: filenames, - }); - let response = client.release_my_shares(request).await; - if response.is_err() { - eprintln!("Attempt to release shared sessions failed."); - let err = format!("{:?}", response); - eprintln!("err = {}\n", err); - eprintln!("Please ask for help!\n"); - std::process::exit(1); - } - RECEIVED_SHARES_CONTENT.lock().unwrap().clear(); - RECEIVED_SHARES_MESSAGES.lock().unwrap().clear(); - RECEIVED_SHARES_FILENAMES.lock().unwrap().clear(); - RELEASE_MY_SHARES.store(false, SeqCst); - } - - if TESTING_USER_NAME.load(SeqCst) { - let user_name = USER_NAME.lock().unwrap()[0].clone(); - let request = tonic::Request::new(UserNameRequest { - user_name: user_name, - }); - let response = client.test_user_name(request).await; - if response.is_err() { - eprintln!("\nWeird, validity test for user name failed."); - let err = format!("{:?}", response); - eprintln!("err = {}\n", err); - std::process::exit(1); - } - let valid = response.unwrap().into_inner().value; - USER_NAME_VALID.store(valid, SeqCst); - TESTING_USER_NAME.store(false, SeqCst); - } - - if PROCESSING_REQUEST.load(SeqCst) { - let input = USER_REQUEST.lock().unwrap()[0].clone(); - let mut line = input.to_string(); - if verbose { - xprintln!("processing command {}", line); - } - let output; - let mut svg_output = String::new(); - let mut summary = String::new(); - let mut metrics = Vec::::new(); - let mut dataset_names = Vec::::new(); - let mut table_comp = Vec::::new(); - let mut last_widths = Vec::::new(); - if line != "enclone" && !line.starts_with("enclone ") { - if line.starts_with("#") { - output = "unknown tag".to_string(); - } else { - output = - "an actual enclone command needs to start with \"enclone\"".to_string(); - if FAIL_ON_ERROR.load(SeqCst) { - eprintln!("\nFAIL_ON_ERROR: command must start with enclone\n"); - std::process::exit(1); - } - } - } else { - if CONFIG_FILE.lock().unwrap().len() > 0 { - line += &mut format!(" CONFIG={}", CONFIG_FILE.lock().unwrap()[0]); - } - let mut server_logfile = None; - if SERVER_LOGFILE.lock().unwrap().len() > 0 { - server_logfile = Some(SERVER_LOGFILE.lock().unwrap()[0].clone()); - } - let request = tonic::Request::new(EncloneRequest { - args: line, - server_logfile: server_logfile, - }); - let response = client.enclone(request).await; - if response.is_err() { - let left = r###"message: "\n"###; - let right = r###"\n""###; - let mut err = format!("{:?}", response); - if err.contains(&left) && err.after(&left).contains(&right) { - err = err.between(&left, &right).to_string(); - } - err = err.replace("\\n", "\n"); - let crash = err.contains("transport error: connection error: broken pipe"); - if crash { - output = format!( - "\nIt would appear the the enclone server \ - crashed.\nPlease look in the terminal window for a traceback \ - and report it.\n" - ); - } else { - let msg = format!("\nThe enclone server is unhappy. It says:\n\n{}", err); - let mut msg = fold(&msg, 100).join("\n"); - if msg.contains("transport error") { - msg += &mut format!( - "\n\nThe most likely explanation for this particular \ - message \ - is that the server crashed.\nThe stack trace from the crash may be \ - visible in the terminal window from which\n\ - you launched enclone visual.\n" - ); - } else if msg.contains("error trying to connect") { - msg += &mut format!( - "\n\nThe most likely explanation for this particular \ - message \ - is that the server had crashed before you entered\n\ - your last command. The stack trace from the crash may be \ - visible in the terminal window from which\n\ - you launched enclone visual.\n" - ); - } - output = msg.clone(); - xprintln!("{}", msg); - } - let mut ebuffer = [0; 10000]; - let server_stderr = server_process.stderr.as_mut().unwrap(); - server_stderr.read(&mut ebuffer).unwrap(); - let emsg = strme(&ebuffer); - xprint!("server error =\n{}", emsg); - } else { - let response = response.unwrap(); - let r = response.into_inner(); - svg_output = r.plot.clone(); - metrics = r.metrics.clone(); - dataset_names = r.dataset_names.clone(); - output = format!("{}", r.table); - table_comp = r.table_comp.clone(); - for x in r.last_widths.iter() { - last_widths.push(*x as u32); - } - summary = r.summary.clone(); - } - } - SERVER_REPLY_SVG.lock().unwrap().clear(); - SERVER_REPLY_SVG.lock().unwrap().push(svg_output); - SERVER_REPLY_SUMMARY.lock().unwrap().clear(); - SERVER_REPLY_SUMMARY.lock().unwrap().push(summary); - SERVER_REPLY_METRICS.lock().unwrap().clear(); - let n = metrics.len(); - for i in 0..n { - SERVER_REPLY_METRICS - .lock() - .unwrap() - .push(metrics[i].clone()); - } - SERVER_REPLY_DATASET_NAMES.lock().unwrap().clear(); - let n = dataset_names.len(); - for i in 0..n { - SERVER_REPLY_DATASET_NAMES - .lock() - .unwrap() - .push(dataset_names[i].clone()); - } - let summary = form_summary_from_server_response().pack(); - SERVER_REPLY_SUMMARY_PLUS.lock().unwrap().clear(); - SERVER_REPLY_SUMMARY_PLUS.lock().unwrap().push(summary); - SERVER_REPLY_TABLE_COMP.lock().unwrap().clear(); - SERVER_REPLY_TABLE_COMP.lock().unwrap().push(table_comp); - SERVER_REPLY_LAST_WIDTHS.lock().unwrap().clear(); - SERVER_REPLY_LAST_WIDTHS.lock().unwrap().push(last_widths); - SERVER_REPLY_TEXT.lock().unwrap().clear(); - SERVER_REPLY_TEXT.lock().unwrap().push(output.clone()); - PROCESSING_REQUEST.store(false, SeqCst); - } - } -} diff --git a/enclone_visual/src/colors b/enclone_visual/src/colors deleted file mode 100644 index 36a21cfabe..0000000000 --- a/enclone_visual/src/colors +++ /dev/null @@ -1,149 +0,0 @@ -# there are the css4 named colors, from https://www.w3.org/TR/css-color-4/#named-colors -aliceblue #F0F8FF -antiquewhite #FAEBD7 -aqua #00FFFF -aquamarine #7FFFD4 -azure #F0FFFF -beige #F5F5DC -bisque #FFE4C4 -black #000000 -blanchedalmond #FFEBCD -blue #0000FF -blueviolet #8A2BE2 -brown #A52A2A -burlywood #DEB887 -cadetblue #5F9EA0 -chartreuse #7FFF00 -chocolate #D2691E -coral #FF7F50 -cornflowerblue #6495ED -cornsilk #FFF8DC -crimson #DC143C -cyan #00FFFF -darkblue #00008B -darkcyan #008B8B -darkgoldenrod #B8860B -darkgray #A9A9A9 -darkgreen #006400 -darkgrey #A9A9A9 -darkkhaki #BDB76B -darkmagenta #8B008B -darkolivegreen #556B2F -darkorange #FF8C00 -darkorchid #9932CC -darkred #8B0000 -darksalmon #E9967A -darkseagreen #8FBC8F -darkslateblue #483D8B -darkslategray #2F4F4F -darkslategrey #2F4F4F -darkturquoise #00CED1 -darkviolet #9400D3 -deeppink #FF1493 -deepskyblue #00BFFF -dimgray #696969 -dimgrey #696969 -dodgerblue #1E90FF -firebrick #B22222 -floralwhite #FFFAF0 -forestgreen #228B22 -fuchsia #FF00FF -gainsboro #DCDCDC -ghostwhite #F8F8FF -gold #FFD700 -goldenrod #DAA520 -gray #808080 -green #008000 -greenyellow #ADFF2F -grey #808080 -honeydew #F0FFF0 -hotpink #FF69B4 -indianred #CD5C5C -indigo #4B0082 -ivory #FFFFF0 -khaki #F0E68C -lavender #E6E6FA -lavenderblush #FFF0F5 -lawngreen #7CFC00 -lemonchiffon #FFFACD -lightblue #ADD8E6 -lightcoral #F08080 -lightcyan #E0FFFF -lightgoldenrodyellow #FAFAD2 -lightgray #D3D3D3 -lightgreen #90EE90 -lightgrey #D3D3D3 -lightpink #FFB6C1 -lightsalmon #FFA07A -lightseagreen #20B2AA -lightskyblue #87CEFA -lightslategray #778899 -lightslategrey #778899 -lightsteelblue #B0C4DE -lightyellow #FFFFE0 -lime #00FF00 -limegreen #32CD32 -linen #FAF0E6 -magenta #FF00FF -maroon #800000 -mediumaquamarine #66CDAA -mediumblue #0000CD -mediumorchid #BA55D3 -mediumpurple #9370DB -mediumseagreen #3CB371 -mediumslateblue #7B68EE -mediumspringgreen #00FA9A -mediumturquoise #48D1CC -mediumvioletred #C71585 -midnightblue #191970 -mintcream #F5FFFA -mistyrose #FFE4E1 -moccasin #FFE4B5 -navajowhite #FFDEAD -navy #000080 -oldlace #FDF5E6 -olive #808000 -olivedrab #6B8E23 -orange #FFA500 -orangered #FF4500 -orchid #DA70D6 -palegoldenrod #EEE8AA -palegreen #98FB98 -paleturquoise #AFEEEE -palevioletred #DB7093 -papayawhip #FFEFD5 -peachpuff #FFDAB9 -peru #CD853F -pink #FFC0CB -plum #DDA0DD -powderblue #B0E0E6 -purple #800080 -rebeccapurple #663399 -red #FF0000 -rosybrown #BC8F8F -royalblue #4169E1 -saddlebrown #8B4513 -salmon #FA8072 -sandybrown #F4A460 -seagreen #2E8B57 -seashell #FFF5EE -sienna #A0522D -silver #C0C0C0 -skyblue #87CEEB -slateblue #6A5ACD -slategray #708090 -slategrey #708090 -snow #FFFAFA -springgreen #00FF7F -steelblue #4682B4 -tan #D2B48C -teal #008080 -thistle #D8BFD8 -tomato #FF6347 -turquoise #40E0D0 -violet #EE82EE -wheat #F5DEB3 -white #FFFFFF -whitesmoke #F5F5F5 -yellow #FFFF00 -yellowgreen #9ACD32 diff --git a/enclone_visual/src/compare_images.rs b/enclone_visual/src/compare_images.rs deleted file mode 100644 index d644923d51..0000000000 --- a/enclone_visual/src/compare_images.rs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. -// -// Compare two RGB8 images, returning the number of pixel-color positions at which they differ, -// excluding certain expected differences. - -use io_utils::*; -use rayon::prelude::*; -use std::io::Write; -use string_utils::*; -use vector_utils::*; - -pub fn compare_images( - image_data_old: &Vec, - image_data_new: &Vec, - width: usize, - height: usize, - verbose: bool, -) -> usize { - const MAX_DIFF: u8 = 61; - const MAX_GRAY_DIFF: u8 = 134; - let mut results = Vec::<(usize, usize, Vec)>::new(); - for x in 0..width { - results.push((x, 0, Vec::new())); - } - results.par_iter_mut().for_each(|res| { - let x = res.0; - let (mut olds, mut news) = (Vec::::new(), Vec::::new()); - for y in 0..height { - // - // Test for relatively small differences. - - let mut close = true; - for c in 0..3 { - let i = x * (height * 3) + y * 3 + c; - let (old, new) = (image_data_old[i], image_data_new[i]); - let diff = if old <= new { new - old } else { old - new }; - if diff > MAX_DIFF { - close = false; - } - } - if close { - continue; - } - - // Test for relatively small grayscale differences. - - olds.clear(); - news.clear(); - for c in 0..3 { - let i = x * (height * 3) + y * 3 + c; - olds.push(image_data_old[i]); - news.push(image_data_new[i]); - } - unique_sort(&mut olds); - unique_sort(&mut news); - if olds.solo() && news.solo() { - let diff = if olds[0] <= news[0] { - news[0] - olds[0] - } else { - olds[0] - news[0] - }; - if diff <= MAX_GRAY_DIFF { - continue; - } - } - - // Test for other differences. - - for c in 0..3 { - let i = x * (height * 3) + y * 3 + c; - let (vold, vnew) = (image_data_old[i], image_data_new[i]); - if vnew != vold { - if verbose { - fwriteln!( - res.2, - "x = {}, y = {}, c = {}, vold = {}, vnew = {}", - x, - y, - c, - vold, - vnew - ); - } - res.1 += 1; - } - } - } - }); - let mut diffs = 0; - for x in 0..results.len() { - if verbose { - print!("{}", strme(&results[x].2)); - } - diffs += results[x].1; - } - diffs -} diff --git a/enclone_visual/src/cookbook.internal b/enclone_visual/src/cookbook.internal deleted file mode 100644 index 4458cce0cf..0000000000 --- a/enclone_visual/src/cookbook.internal +++ /dev/null @@ -1,14 +0,0 @@ - -This is not used anymore but kept because it includes some interesting commands. - -#4 -enclone BCR=1145040 GEX=1142282 ALLOW_INCONSISTENT NGEX -In this case, because there are not actually any gene expression data, comparing cell calls between GEX (which is actually feature barcode data) and BCR doesn't make sense, and so we need the options ALLOW_INCONSISTENT and NGEX. - -#5 -enclone BCR=1145040 GEX=1142282 ALLOW_INCONSISTENT NGEX LVARSP=fb1,fb1_n,fb2,fb2_n -Show the top two feature barcodes: both their sequences, and per cell counts. This requires preprocessing to get the feature barcodes. - -#6 -enclone BCR=1145040 GEX=1142282 ALLOW_INCONSISTENT NGEX SIM_MAT_PLOT=gui,fb1_n,fb2_n,fb3_n,fb4_n,fb5_n -Display the correlation (cosine similarity of UMI counts across cells) between the top five feature barcodes. Requires preprocessing as above. diff --git a/enclone_visual/src/cookbooks/color_by_var.cb b/enclone_visual/src/cookbooks/color_by_var.cb deleted file mode 100644 index 50558864b8..0000000000 Binary files a/enclone_visual/src/cookbooks/color_by_var.cb and /dev/null differ diff --git a/enclone_visual/src/cookbooks/plot.cb b/enclone_visual/src/cookbooks/plot.cb deleted file mode 100644 index 957ee5879a..0000000000 Binary files a/enclone_visual/src/cookbooks/plot.cb and /dev/null differ diff --git a/enclone_visual/src/copy_image_to_clipboard.rs b/enclone_visual/src/copy_image_to_clipboard.rs deleted file mode 100644 index dc1662db53..0000000000 --- a/enclone_visual/src/copy_image_to_clipboard.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. -// -// This includes code copied with small changes from the pasteboard crate. -// -// The same code presumably works for image types other than PNG, but has only been tested on PNG. - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use cocoa::{ - appkit::{NSImage, NSPasteboard}, - base::nil, - foundation::{NSArray, NSAutoreleasePool, NSData, NSString}, -}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use objc::{msg_send, runtime::Object, sel, sel_impl}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub type Id = *mut Object; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use libc::c_void; - -#[cfg(any(target_os = "linux", target_os = "windows"))] -use arboard::{Clipboard, ImageData}; - -#[cfg(any(target_os = "linux", target_os = "windows"))] -use string_utils::*; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use crate::*; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn copy_png_bytes_to_clipboard(bytes: &[u8]) { - if bytes.len() > 0 { - unsafe { - let pool = NSAutoreleasePool::new(nil); - let data = NSData::dataWithBytes_length_( - pool, - bytes.as_ptr() as *const c_void, - bytes.len() as u64, - ); - let object = NSImage::initWithData_(NSImage::alloc(pool), data); - if object != nil { - let pasteboard = NSPasteboard::generalPasteboard(pool); - pasteboard.clearContents(); - pasteboard.writeObjects(NSArray::arrayWithObject(pool, object)); - } else { - xprintln!("\ncopy to pasteboard failed\n"); - std::process::exit(1); - } - } - } -} - -#[cfg(any(target_os = "linux", target_os = "windows"))] -pub fn copy_png_bytes_to_clipboard(bytes: &[u8]) { - let (header, image_data) = png_decoder::decode(&bytes).unwrap(); - let (width, height) = (header.width as usize, header.height as usize); - let mut clipboard = Clipboard::new().unwrap(); - let img_data = ImageData { - width: width, - height: height, - bytes: image_data.into(), - }; - clipboard.set_image(img_data).unwrap(); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// intended for strings: - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn copy_bytes_to_clipboard(bytes: &[u8]) { - if bytes.len() > 0 { - unsafe { - let pool = NSAutoreleasePool::new(nil); - let data = NSData::dataWithBytes_length_( - pool, - bytes.as_ptr() as *const c_void, - bytes.len() as u64, - ); - let string: Id = msg_send![NSString::alloc(pool), initWithData:data encoding:4]; - let object = string; - if object != nil { - let pasteboard = NSPasteboard::generalPasteboard(pool); - pasteboard.clearContents(); - pasteboard.writeObjects(NSArray::arrayWithObject(pool, object)); - } else { - xprintln!("\ncopy to pasteboard failed\n"); - std::process::exit(1); - } - } - } -} - -#[cfg(any(target_os = "linux", target_os = "windows"))] -pub fn copy_bytes_to_clipboard(bytes: &[u8]) { - if bytes.len() > 0 { - let mut clipboard = Clipboard::new().unwrap(); - let the_string = strme(&bytes); - clipboard.set_text(the_string.into()).unwrap(); - } -} diff --git a/enclone_visual/src/dimensions.rs b/enclone_visual/src/dimensions.rs deleted file mode 100644 index 084c4aede3..0000000000 --- a/enclone_visual/src/dimensions.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use crate::*; -use std::sync::atomic::AtomicUsize; -use std::sync::atomic::Ordering::SeqCst; - -// These are the window dimensions that are requested initially. - -pub const INITIAL_WIDTH: u32 = 1100; -pub const INITIAL_HEIGHT: u32 = 1060; - -// Tracking the actual screen dimensions. - -pub static CURRENT_WIDTH: AtomicUsize = AtomicUsize::new(0); -pub static CURRENT_WIDTH_LAST_SEEN: AtomicUsize = AtomicUsize::new(0); -pub static CURRENT_HEIGHT: AtomicUsize = AtomicUsize::new(0); -pub static CURRENT_HEIGHT_LAST_SEEN: AtomicUsize = AtomicUsize::new(0); - -// The default height of the graphic part of the screen if there is not graphic, and if there -// is a graphic. - -pub const SVG_NULL_HEIGHT: u16 = 190; -pub const SVG_HEIGHT: u16 = 400; - -// The default width of the graphic. - -pub const MAX_WIDTH: f32 = 770.0; - -// The function that determines the scale for the graphic object. - -pub fn get_graphic_scale(width: f32, height: f32, empty: bool) -> f32 { - let current_width = CURRENT_WIDTH.load(SeqCst); - let current_height = CURRENT_HEIGHT.load(SeqCst); - if !GRAPHIC_MODE.load(SeqCst) { - let mut max_height = SVG_HEIGHT as f32; - if empty { - max_height = SVG_NULL_HEIGHT as f32; - } - max_height *= current_height as f32 / INITIAL_HEIGHT as f32; - max_height -= 5.0; - let mut max_width = MAX_WIDTH; - if current_width > INITIAL_WIDTH as usize { - max_width += (current_width - INITIAL_WIDTH as usize) as f32; - } - let scale_x = max_width / width; - let scale_y = max_height / height; - let mut scale = scale_y; - if scale_x < scale_y { - scale = scale_x; - } - scale - } else { - const HBORDER: usize = 45; - const VBORDER: usize = 120; - let target_width = current_width - HBORDER; - let target_height = current_height - VBORDER; - let scale_x = target_width as f32 / width; - let scale_y = target_height as f32 / height; - let mut scale = scale_y; - if scale_x < scale_y { - scale = scale_x; - } - scale - } -} diff --git a/enclone_visual/src/enclone_client.rs b/enclone_visual/src/enclone_client.rs deleted file mode 100644 index f907024844..0000000000 --- a/enclone_visual/src/enclone_client.rs +++ /dev/null @@ -1,813 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// This is a GUI client, work in progress. -// -// This starts enclone in SERVER mode, which can be either local or remote. -// -// For now accepts a single argument, which is VIS=x where x is a "configuration name". It then -// looks for an environment variable ENCLONE_VIS_x, and parses that into blank-separated -// arguments, which may be: -// -// argument interpretation -// -// REMOTE_HOST=... name of remote host for password-free ssh -// REMOTE_IP=... IP number of remote host -// REMOTE_SETUP=... command to be forked to use port through firewall, may include $port -// REMOVE_BIN=... directory on remote host containing the enclone executable -// -// Alternatively, you can define an environment variable ENCLONE_CONFIG=filename or -// ENCLONE_CONFIG=filehost:filename, in which case that file is fetched, and lines are found -// that look like -// vis.x.variable=value -// and in such cases, we use variable=value is the source of variable definitions. -// -// enclone VIS -- run the serve locally -// -// The special argument SERVER_DEBUG causes the server to print debuggin information. However -// you will only see this if you run the server locally using enclone VIS. - -use crate::client_requests::*; -use crate::launch_gui; -use crate::proto::analyzer_client::AnalyzerClient; -use crate::update_restart::*; -use crate::*; -use enclone_build::prepare_for_apocalypse::*; -use enclone_core::parse_bsv; -use enclone_core::REMOTE_HOST; -use enclone_version::*; -use io_utils::*; -use itertools::Itertools; -use libc::atexit; -#[cfg(not(target_os = "windows"))] -use nix::sys::signal::{kill, SIGINT as SIGINT_nix}; -#[cfg(not(target_os = "windows"))] -use nix::unistd::Pid; -#[cfg(not(target_os = "windows"))] -use perf_stats::peak_mem_usage_gb; -use std::env; -use std::io::Read; -use std::process::{Command, Stdio}; -use std::sync::atomic::Ordering::SeqCst; -use std::thread; -use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub async fn enclone_client(t: &Instant) -> Result<(), Box> { - // - // Set up to catch CTRL-C events. Parse arguments. - - let args: Vec = env::args().collect(); - let mut verbose = false; - let mut monitor_threads = false; - let mut config_name = String::new(); - let mut fixed_port = None; - let mut require_compatible = false; - let mut ctrlc = false; - for i in 1..args.len() { - let arg = &args[i]; - - // General options. - - if arg.starts_with("VIS=") { - config_name = arg.after("VIS=").to_string(); - } else if arg == "VIS" { - } else if arg == "VERBOSE" { - verbose = true; - - // Special testing options. - // - } else if arg == "MONITOR_THREADS" { - monitor_threads = true; - } else if arg.starts_with("PORT=") { - fixed_port = Some(arg.after("PORT=").parse::().unwrap()); - assert!(fixed_port.unwrap() >= 1024); - } else if arg == "TEST" { - TEST_MODE.store(true, SeqCst); - } else if arg.starts_with("VISUAL_DIR=") { - let dir = arg.after("VISUAL_DIR=").to_string(); - VISUAL_DIR.lock().unwrap().push(dir); - } else if arg == "PLAYBACK" { - PLAYBACK.store(true, SeqCst); - } else if arg == "FAIL_ON_ERROR" { - FAIL_ON_ERROR.store(true, SeqCst); - } else if arg.starts_with("SERVER_LOGFILE=") { - // don't use tilde because we don't expand it - let server_logfile = arg.after("SERVER_LOGFILE=").to_string(); - SERVER_LOGFILE.lock().unwrap().push(server_logfile); - } else if arg.starts_with("META=") { - META_TESTING.store(true, SeqCst); - META.store(arg.after("META=").force_usize() - 1, SeqCst); - } else if arg.starts_with("EXEC=") { - EXEC.lock().unwrap().push(arg.after("EXEC=").to_string()); - } else if arg == "REQUIRE_COMPATIBLE" { - require_compatible = true; - } else if arg == "CTRLC" { - ctrlc = true; - } else if arg.starts_with("EHOME=") { - let ehome = arg.after("EHOME=").to_string(); - EHOME.lock().unwrap().push(ehome); - } else { - xprintln!( - "\nCurrently the only allowed arguments are VIS, VIS=x where x is a\n\ - configuration name and VERBOSE, and some special testing options.\n" - ); - std::process::exit(1); - } - } - if !ctrlc { - #[cfg(not(target_os = "windows"))] - let _ = install_signal_handler(); - CTRLC.store(true, SeqCst); - } - for (key, _value) in env::vars() { - if key == "ENCLONE_VERBOSE" { - verbose = true; - } - } - if verbose { - VERBOSE.store(true, SeqCst); - } - - // Set enclone visual version. - - let version = "0.001"; - VERSION.lock().unwrap().push(version.to_string()); - - // Monitor threads. - - if monitor_threads { - tokio::spawn(async move { - loop { - thread::sleep(Duration::from_millis(5000)); - xprintln!("[using {} threads", thread_count()); - } - }); - } - - // For Linux, pretest for existence of libXcursor.so. - - if cfg!(target_os = "linux") { - let o = Command::new("/sbin/ldconfig") - .arg("-p") - .output() - .expect("failed to execute /sbin/ldconfig"); - if o.status.code() != Some(0) { - eprintln!("\nCould not run /sbin/ldconfig.\n"); - std::process::exit(1); - } - let mut have_lib = false; - let out = strme(&o.stdout); - for line in out.lines() { - if line.contains("libXcursor.so") { - have_lib = true; - } - } - if !have_lib { - eprintln!("\nThere is a system installation issue, can't find libXcursor.so."); - eprintln!("Please ask someone who knows how to fix this.\n"); - std::process::exit(1); - } - } - - // Announce. - - if !verbose { - xprintln!( - "\nHi! You are using enclone visual {}.\n\n\ - If you get an error \ - message or a window does not pop up, and it's not clear what to do,\nplease \ - rerun the command with the added argument VERBOSE, and then ask for help.", - version, - ); - } - - // Get configuration from environment variable if defined. - - let mut config = HashMap::::new(); - let mut configuration = None; - let mut found = false; - if config_name.len() > 0 { - let env_var = format!("ENCLONE_VIS_{}", config_name); - for (key, value) in env::vars() { - if key == env_var { - configuration = Some(value.clone()); - } - } - if configuration.is_some() { - let configuration = configuration.unwrap(); - found = true; - if verbose { - xprintln!("\nusing configuration\n▓{}▓", configuration); - } - let x = parse_bsv(&configuration); - for arg in x.iter() { - if !arg.contains("=") { - xprintln!( - "\nYour configuration has an argument {} that does not contain =.\n", - arg - ); - std::process::exit(1); - } - config.insert(arg.before("=").to_string(), arg.after("=").to_string()); - } - } - } - - // Get config file if defined. The config file is specified by an environment variable - // of the form ENCLONE_CONFIG=filename or ENCLONE_CONFIG=filehost:filename. - // - // Note that even if ENCLONE_VIS is specified, we still look for ENCLONE_CONFIG. - - let mut filehost = String::new(); - let mut filehost_used = false; - let mut auto_update = false; - let mut internal = false; - let mut config_file_contents = String::new(); - let mut ssh_cat_time = 0.0; - for (key, value) in env::vars() { - if key == "ENCLONE_INTERNAL" { - internal = true; - } - - if key == "ENCLONE_CONFIG" { - CONFIG_FILE.lock().unwrap().push(value.to_string()); - let hf = value.to_string(); - let mut filename = hf.clone(); - if hf.contains(":") { - filehost = hf.before(":").to_string(); - filename = hf.after(":").to_string(); - } - if filehost.len() > 0 { - REMOTE_HOST.lock().unwrap().push(filehost.clone()); - } - - // If filename exists on this server, use it, and ignore filehost. - - if path_exists(&filename) { - config_file_contents = std::fs::read_to_string(&filename).unwrap(); - - // Otherwise, fetch the file from the host. - } else if filehost.len() > 0 && config_name.len() > 0 { - filehost_used = true; - let t = Instant::now(); - let o = Command::new("ssh") - .arg(&filehost) - .arg("cat") - .arg(&filename) - .output() - .expect("failed to execute ssh cat"); - ssh_cat_time = elapsed(&t); - xprintln!("\nssh cat to {} took {:.1} seconds", filehost, ssh_cat_time); - if o.status.code() != Some(0) { - let m = String::from_utf8(o.stderr).unwrap(); - xprintln!("\ntest ssh failed with error message =\n{}", m); - xprintln!( - "Attempt to ssh to {} as specified by environment variable \ - ENCLONE_CONFIG failed.", - filehost, - ); - xprintln!("Here are two possible explanations:"); - xprintln!("1. The host is wrong."); - xprintln!("2. You are not connected to the internet."); - xprintln!( - "3. You first need to do something to enable crossing \ - a firewall. If so, ask a colleague.\n" - ); - std::process::exit(1); - } - config_file_contents = strme(&o.stdout).to_string(); - } - } - } - - // Get configuration. - - for line in config_file_contents.lines() { - if line == "visual_auto_update=true" { - auto_update = true; - } - if line == "internal=true" { - internal = true; - } - if line.starts_with("cookbooks=") { - let cb = line.after("cookbooks=").split(',').collect::>(); - for i in 0..cb.len() { - COOKBOOK_DIRS.lock().unwrap().push(cb[i].to_string()); - } - } - if config_name.len() > 0 { - let prefix = format!("vis.{}.", config_name); - if line.starts_with(&prefix) { - let def = line.after(&prefix); - if def.contains("=") { - config.insert(def.before("=").to_string(), def.after("=").to_string()); - found = true; - } - } - } - } - if config_name.len() > 0 && !found { - xprintln!( - "\nYou specified the configuration name {}, but the content of that configuration \ - was not found.\n", - config_name, - ); - if CONFIG_FILE.lock().unwrap().len() > 0 { - xprintln!( - "The value of ENCLONE_CONFIG is {}.\n", - CONFIG_FILE.lock().unwrap()[0] - ); - } else { - xprintln!("The environment variable ENCLONE_CONFIG is not defined.\n"); - } - xprintln!("Here is what's in your configuration file:\n"); - for line in config_file_contents.lines() { - xprintln!("{}", line); - } - xprintln!(""); - std::process::exit(1); - } - if internal { - INTERNAL.store(true, SeqCst); - } - - // Set up proper tracebacks. - - let mut bug_reports = "enclone@10xgenomics.com".to_string(); - for i in 1..args.len() { - if args[i] == "BUG_REPORTS" { - bug_reports = "".to_string(); - } else if args[i].starts_with("BUG_REPORTS=") { - bug_reports = args[i].after("BUG_REPORTS=").to_string(); - } - } - for (key, value) in env::vars() { - if key == "ENCLONE_BUG_REPORTS" { - bug_reports = value.to_string(); - } - } - prepare_for_apocalypse(&args, internal, &bug_reports); - BUG_REPORTS.lock().unwrap().push(bug_reports); - - // Save remote share. - - if config.contains_key("REMOTE_SHARE") { - REMOTE_SHARE - .lock() - .unwrap() - .push(config["REMOTE_SHARE"].clone()); - } - - // Determine if the server is remote. - - let remote = config.contains_key("REMOTE_HOST") - || config.contains_key("REMOTE_IP") - || config.contains_key("REMOTE_BIN"); - if remote { - if !config.contains_key("REMOTE_HOST") - || !config.contains_key("REMOTE_IP") - || !config.contains_key("REMOTE_BIN") - { - xprintln!( - "\nTo use a remote host, please specify all of REMOTE_HOST, \ - REMOTE_IP, and REMOTE_BIN.\n" - ); - xprintln!("Here is what is specified:"); - for (key, value) in config.iter() { - xprintln!("{}={}", key, value); - } - std::process::exit(1); - } else { - REMOTE.store(true, SeqCst); - } - } - - // If server is remote, see if we can ssh to it. Otherwise, busted. - - if remote { - let host = config["REMOTE_HOST"].clone(); - if !filehost_used || filehost != host { - let t = Instant::now(); - let o = Command::new("ssh") - .arg(&host) - .arg("-n") - .arg("echo") - .output() - .expect("failed to execute initial ssh"); - xprintln!( - "\ninitial test ssh to {} took {:.1} seconds", - host, - elapsed(&t) - ); - if o.status.code() != Some(0) { - let m = String::from_utf8(o.stderr).unwrap(); - xprintln!("\ntest ssh to {} failed with error message =\n{}", host, m); - xprintln!( - "Attempt to ssh to {} as specified by REMOTE_HOST failed.", - host - ); - xprintln!("Here are two possible explanations:"); - xprintln!("1. You have the wrong REMOTE_HOST."); - xprintln!("2. You first need to do something to enable crossing a firewall."); - xprintln!(" If so, ask one of your colleagues how to do this.\n"); - std::process::exit(1); - } - } - } - - // Set exit handler to force cleanup at end of process. - - unsafe { - atexit(exit_handler); - } - - // Loop through random ports until we get one that works. - - loop { - let start = SystemTime::now(); - let since_the_epoch = start - .duration_since(UNIX_EPOCH) - .expect("Time went backwards"); - let nanos = since_the_epoch.subsec_nanos() as u64; - let mut port: u16 = (nanos % 65536) as u16; - if fixed_port.is_some() { - port = fixed_port.unwrap(); - } - if port < 1024 { - continue; - } - - // Attempt to fork the server. - - let server_process; - let mut local_host = "127.0.0.1".to_string(); - xprintln!("\ntrying random port {}", port); - if remote { - let host = config["REMOTE_HOST"].clone(); - HOST.lock().unwrap().push(host.clone()); - let ip = &config["REMOTE_IP"]; - let bin = &config["REMOTE_BIN"]; - if verbose { - xprintln!( - "\nstarting remote server using\nssh {} {}/enclone {}:{} SERVER", - host, - bin, - ip, - port - ); - } - server_process = Command::new("ssh") - .arg("-n") - .arg(&host) - .arg(&format!("{}/enclone", bin)) - .arg("SERVER") - .arg(&format!("{}:{}", ip, port)) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - local_host = "localhost".to_string(); - } else { - let ip = "127.0.0.1"; - let t = Instant::now(); - server_process = Command::new("enclone") - .arg("SERVER") - .arg(&format!("{}:{}", ip, port)) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - xprintln!("used {:.1} seconds launching local server", elapsed(&t)); - } - if verbose { - xprintln!("server forked"); - } - if !server_process.is_ok() { - xprintln!( - "\nfailed to launch server, err =\n{}.\n", - server_process.as_ref().unwrap_err() - ); - xprintln!( - "It is possible that you did not follow the enclone installation \ - instructions on bit.ly/enclone.\nIf so, please try that and see if the problem \ - goes away.\n\nOne specific possibility is that the enclone executable is not \ - in your path.\n" - ); - std::process::exit(1); - } - let mut server_process = server_process.unwrap(); - let server_process_id = server_process.id(); - SERVER_PROCESS_PID.store(server_process_id as usize, SeqCst); - - // Wait until server has printed something. - - let mut buffer = [0; 50]; - let server_stdout = server_process.stdout.as_mut().unwrap(); - let tread = Instant::now(); - if verbose { - xprintln!("waiting for server response"); - } - pub static READ_DONE: AtomicBool = AtomicBool::new(false); - thread::spawn(move || { - // At one time we used a sleep time of 5 seconds, but some people have slower - // connections and this resulted in failures. The heuristic in the next - // line is the solution, but perhaps there is a better way to handle this. - let sleep_time = 5.0_f64.max(2.0 * ssh_cat_time); - thread::sleep(Duration::from_millis((sleep_time * 1000.0).round() as u64)); - if !READ_DONE.load(SeqCst) { - xprintln!("darn, we seem to have hit a bad port, so restarting"); - restart_enclone(); - } - }); - server_stdout.read(&mut buffer).unwrap(); - READ_DONE.store(true, SeqCst); - if verbose { - xprintln!( - "time spent waiting to read bytes from server = {:.1} seconds", - elapsed(&tread) - ); - } - - // Look at stderr. We read exactly 200 bytes. By design, this is enough to know that the - // server succeeded and enough to contain the information that the server is passing to - // the client. - - const BYTES_TO_READ: usize = 200; - let mut ebuffer = [0; BYTES_TO_READ]; - let server_stderr = server_process.stderr.as_mut().unwrap(); - let tread = Instant::now(); - let res = server_stderr.read_exact(&mut ebuffer); - if res.is_err() { - eprintln!( - "\nWeird internal error: {}.\nMaybe the server is not working, ask for help.\n", - res.err().unwrap(), - ); - std::process::exit(1); - } - if ebuffer.len() != BYTES_TO_READ { - xprintln!( - "\nWeird internal error: read {} bytes from server rather than the expected \ - number {}.\n", - ebuffer.len(), - BYTES_TO_READ - ); - std::process::exit(1); - } - if verbose { - xprintln!( - "used {:.1} seconds reading from server stderr", - elapsed(&tread) - ); - } - let emsg = strme(&ebuffer); - if emsg.len() > 0 { - if emsg.contains("RUST PROGRAM PANIC") { - let mut ebuffer2 = Vec::::new(); - server_stderr.read_to_end(&mut ebuffer2).unwrap(); - let mut ebuf = Vec::::new(); - ebuf.append(&mut ebuffer.to_vec()); - ebuf.append(&mut ebuffer2); - let mut scream = String::new(); - for _ in 0..49 { - scream.push('😱'); - } - xprint!( - "\n{}\nThe server crashed upon startup. Here is what it says:\n{}\n{}", - scream, - scream, - strme(&ebuf), - ); - std::process::exit(1); - } - if emsg.contains("already in use") { - xprintln!("oops, that port is in use, trying a different one"); - continue; - } - if verbose { - xprintln!("\nserver says this:\n{}", emsg); - } - if emsg.contains("tput: No value") { - xprintln!( - "\nThat's an odd message that we've observed once and don't \ - understand. When it happened,\nit was associated with setting the \ - environment variable PS1 on the remote server. If it happens\nto you, \ - please contact us at enclone@10xgenomics.com.\n" - ); - } - } - - // Get server process id, possibly remote. - - let mut remote_id = None; - if remote { - if emsg.contains("I am process ") && emsg.after("I am process ").contains(".") { - let id = emsg.between("I am process ", "."); - if id.parse::().is_ok() { - remote_id = Some(id.force_usize()); - REMOTE_SERVER_ID.store(remote_id.unwrap(), SeqCst); - } - } - if remote_id.is_none() { - // This happened once when an initialization command was in the user's ~/.bashrc. - // Unfortunately, the ssh command that this is reading the output of sources - // ~/.bashrc, and it's not clear how to turn that off. The immediate solution for - // the user was to move the initialization command from ~/.bashrc to - // ~/.bash_profile. - - xprintln!("\nUnable to determine remote process id.\n"); - xprintln!("message =\n\"{}\"", emsg); - xprintln!( - "\nOne possibility is that you have something in your ~/.bashrc that \ - should be in your ~/.bash_profile.\n" - ); - std::process::exit(1); - } - let remote_version; - if emsg.contains("enclone version = ") - && emsg.after("enclone version = ").contains("\n") - { - remote_version = emsg.between("enclone version = ", "\n").to_string(); - } else { - xprint!("\nUnable to determine remote enclone version.\n"); - xprintln!("message =\n\"{}\"", emsg); - std::process::exit(1); - } - let remote_version_string; - if emsg.contains("version string = ") && emsg.after("version string = ").contains("\n") - { - remote_version_string = emsg.between("version string = ", "\n").to_string(); - } else { - xprint!("\nUnable to determine remote version string.\n"); - xprintln!("message =\n\"{}\"", emsg); - std::process::exit(1); - } - let local_version = env!("CARGO_PKG_VERSION"); - if local_version != remote_version { - xprintln!("\nremote enclone version = {}", remote_version); - xprintln!("local enclone version = {}", local_version); - xprintln!("\nYour enclone version is not up to date."); - if auto_update { - update_enclone(); - xprintln!("Done, restarting!\n"); - restart_enclone(); - } else { - xprintln!( - "Please update, following \ - the instructions at bit.ly/enclone, then restart. Thank you!\n" - ); - std::process::exit(1); - } - } - - // Check for identity of local and remote enclone versions. This is complicated - // because in general, the version_string() function does not return the current - // value. So we only test for version identity if we're in the directory where - // enclone as compiled. And that same condition is partially tested on the remote. - - let current_dir = std::env::current_dir()?; - let current_dir = current_dir.display(); - let current_executable = std::env::current_exe()?; - let current_executable = current_executable.display(); - println!("current dir = {}", current_dir); - println!("current executable = {}", current_executable); - if format!("{}", current_executable) == format!("{}/target/debug/enclone", current_dir) - { - let local_version_string = current_version_string(); - let local = format!("{} : {}", local_version, local_version_string); - let remote = format!("{} : {}", remote_version, remote_version_string); - let mut xlocal = local.clone(); - xlocal = xlocal.replace(": macos :", ""); - xlocal = xlocal.replace(": linux :", ""); - let mut xremote = remote.clone(); - xremote = xremote.replace(": macos :", ""); - xremote = xremote.replace(": linux :", ""); - if xlocal != xremote && verbose { - xprintln!("\n🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴"); - xprintln!("----------------------------------------------------------------------------------"); - xprintln!("😱 WARNING: INCOMPATIBLE SERVER/CLIENT VERSIONS DETECTED!!! 😱"); - xprintln!("local version = {}", local); - xprintln!("remote version = {}", remote); - xprintln!("THIS CAN CAUSE VERY BAD AND INSCRUTABLE THINGS TO HAPPEN!"); - xprintln!("😱 PROCEED AT RISK.................😱"); - xprintln!("----------------------------------------------------------------------------------"); - xprintln!("🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴🔴"); - xprintln!( - "\nNote that this could be a false positive. If you touch the \ - right local and remote\nfiles, you can ensure that the reported \ - versions are correct." - ); - if require_compatible { - std::process::exit(1); - } - } else if verbose { - xprintln!("local version = {}", local); - xprintln!("remote version = {}", remote); - } - } - } - - // Form local URL. - - let url = format!("http://{}:{}", local_host, port); - - // Fork remote setup command if needed. - - if config.contains_key("REMOTE_SETUP") { - let tremote = Instant::now(); - let mut setup = config["REMOTE_SETUP"].clone(); - if setup.starts_with("\"") && setup.ends_with("\"") { - setup = setup.after("\"").rev_before("\"").to_string(); - } - setup = setup.replace("$port", &format!("{}", port)); - let argsp = setup.split(' ').collect::>(); - let args = argsp[1..].to_vec(); - if verbose { - xprintln!("\nrunning setup command = {}", argsp.iter().format(" ")); - } - let setup_process = Command::new(argsp[0]) - .args(args) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - if !setup_process.is_ok() { - xprintln!( - "\nfailed to launch setup, err =\n{}.\n", - setup_process.as_ref().unwrap_err() - ); - #[cfg(not(target_os = "windows"))] - kill(Pid::from_raw(server_process_id as i32), SIGINT_nix).unwrap(); - cleanup(); - std::process::exit(1); - } - let setup_process = setup_process.unwrap(); - let setup_process_id = setup_process.id(); - SETUP_PID.store(setup_process_id as usize, SeqCst); - USING_SETUP.store(true, SeqCst); - if verbose { - xprintln!("used {:.1} seconds connecting to remote", elapsed(&tremote)); - } - } - - // Connect to client. - - if verbose { - xprintln!("connecting to {}", url); - } - let tconnect = Instant::now(); - const MAX_CONNECT_MS: u64 = 10_000; - const CONNECT_WAIT_MS: u64 = 250; - use tonic::transport::Channel; - let mut client: Result, tonic::transport::Error>; - let mut wait_time = 0; - loop { - thread::sleep(Duration::from_millis(CONNECT_WAIT_MS)); - wait_time += CONNECT_WAIT_MS; - client = AnalyzerClient::connect(url.clone()).await; - if client.is_ok() { - break; - } - if wait_time >= MAX_CONNECT_MS { - xprintln!("\nconnection failed with error\n{:?}\n", client); - if !verbose { - xprintln!("Please retry after adding the VERBOSE argument to your command.\n"); - } - xprintln!("Please report this problem. It is possible that the maximum"); - xprintln!("connection time used by enclone visual needs to be increased.\n"); - cleanup(); - std::process::exit(1); - } - } - if verbose { - xprintln!("used {:.1} seconds connecting", elapsed(&tconnect)); - } - xprintln!("connected"); - #[cfg(not(target_os = "windows"))] - { - xprintln!( - "time since startup = {:.1} seconds, peak mem = {:.1} GB\n", - elapsed(&t), - peak_mem_usage_gb() - ); - } - let mut client = client.unwrap(); - - // Process commands via the server in the background. - - tokio::spawn(async move { - process_requests(&mut client, &mut server_process, verbose).await; - }); - - // /sbin/ldconfig -p | grep libXcursor.so - - // Launch GUI. - - let gui = launch_gui().await; - if gui.is_err() { - eprintln!("\nFailed to launch enclone visual GUI.\n"); - std::process::exit(1); - } - cleanup(); - return Ok(()); - } -} diff --git a/enclone_visual/src/enclone_server.rs b/enclone_visual/src/enclone_server.rs deleted file mode 100644 index efb2f2063e..0000000000 --- a/enclone_visual/src/enclone_server.rs +++ /dev/null @@ -1,675 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::proto::{ - analyzer_client::AnalyzerClient, - analyzer_server::{Analyzer, AnalyzerServer}, - *, -}; -use crate::*; -use chrono::prelude::*; -use enclone_build::version_string; -use enclone_core::combine_group_pics::*; -use enclone_core::enclone_structs::*; -use enclone_core::logging::*; -use enclone_core::parse_bsv; -use enclone_main::main_enclone::*; -use enclone_main::stop::*; -use enclone_stuff::start::main_enclone_start; -// use enclone_version::*; -use flate2::write::GzEncoder; -use flate2::Compression; -use io_utils::*; -use itertools::Itertools; -use log::{error, warn}; -use pretty_trace::*; -use std::env; -use std::fs::File; -use std::io::{Read, Write}; -#[cfg(not(target_os = "windows"))] -use std::os::unix::fs::PermissionsExt; -use std::sync::{Arc, Mutex}; -use std::time::{Duration, Instant}; -use tokio::net::TcpListener; -use tokio_stream::wrappers::TcpListenerStream; -use tonic::{transport::Server, Code, Request, Response, Status}; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub struct EncloneAnalyzer { - enclone_command: Arc>, - enclone_state: Arc>, // caches enclone state -} - -#[tonic::async_trait] -impl Analyzer for EncloneAnalyzer { - async fn ping(&self, _request: Request) -> Result, Status> { - Ok(Response::new(Unit {})) - } - - async fn enclone( - &self, - request: Request, - ) -> Result, Status> { - // TODO: Actually parse the arguments etc - let req: EncloneRequest = request.into_inner(); - - // Override the output file - - let fields: Vec<_> = parse_bsv(&req.args) - .into_iter() - .map(|f| f.replace("\"", "")) - .collect(); - - let mut args = Vec::::new(); - let mut server_debug = false; - for j in 0..fields.len() { - if fields[j].len() > 0 { - if fields[j] == "SERVER_DEBUG" { - server_debug = true; - } else { - args.push(fields[j].to_string()); - } - } - } - let mut g_specified = false; - for j in 0..args.len() { - if args[j].starts_with("G=") { - g_specified = true; - } - } - args.push("SUMMARY".to_string()); - args.push("NOPRINTX".to_string()); - args.push("NOPAGER".to_string()); - args.push("PLAIN".to_string()); // until colored text can be rendered - args.push("VISUAL".to_string()); - if req.server_logfile.is_some() { - if enclone_core::logging::SERVER_LOGFILE - .lock() - .unwrap() - .is_empty() - { - enclone_core::logging::SERVER_LOGFILE - .lock() - .unwrap() - .push(req.server_logfile.as_ref().unwrap().clone()); - } - } - logme(&format!("Running enclone:\n {}", args.join(" "))); - eprintln!("Running enclone:\n {}", args.join(" ")); - let setup = main_enclone_setup(&args); - if setup.is_err() { - let err_msg = format!("{}", setup.err().unwrap()); - let mut msg = format!("enclone failed, here is the error message:\n{}\n", err_msg); - if server_debug { - msg += &mut format!( - "The arguments provided to the server were\n{}.\n", - args.iter().format(" ") - ); - } - let response = EncloneResponse { - args: req.args, - plot: String::new(), - table: msg, - summary: String::new(), - metrics: Vec::::new(), - dataset_names: Vec::::new(), - table_comp: Vec::::new(), - last_widths: Vec::::new(), - }; - return Ok(Response::new(response)); - } - let setup = setup.unwrap(); - if setup.tall.is_none() { - let response = EncloneResponse { - args: req.args, - plot: String::new(), - table: String::new(), - summary: String::new(), - metrics: Vec::::new(), - dataset_names: Vec::::new(), - table_comp: Vec::::new(), - last_widths: Vec::::new(), - }; - return Ok(Response::new(response)); - } - - // Check for change to setup that could change intermediates. We are very conservative - // about this, and only allow changes to: - // * start_time - // * clono_filt_opt or clono_print_opt - // * plot_opt. - // More exceptions could be added. - - let mut changed = false; - { - // last_setup must be scoped or enclone VIS will mysteriously fail - let last_setup = &self.enclone_state.lock().unwrap().inter.setup; - if setup.ctl.perf_opt != last_setup.ctl.perf_opt { - changed = true; - } - if setup.ctl.gen_opt != last_setup.ctl.gen_opt { - changed = true; - } - if setup.ctl.pretty != last_setup.ctl.pretty { - changed = true; - } - if setup.ctl.silent != last_setup.ctl.silent { - changed = true; - } - if setup.ctl.force != last_setup.ctl.force { - changed = true; - } - if setup.ctl.debug_table_printing != last_setup.ctl.debug_table_printing { - changed = true; - } - if setup.ctl.merge_all_impropers != last_setup.ctl.merge_all_impropers { - changed = true; - } - if setup.ctl.heur != last_setup.ctl.heur { - changed = true; - } - if setup.ctl.origin_info != last_setup.ctl.origin_info { - changed = true; - } - if setup.ctl.clono_filt_opt_def != last_setup.ctl.clono_filt_opt_def { - changed = true; - } - if setup.ctl.allele_alg_opt != last_setup.ctl.allele_alg_opt { - changed = true; - } - if setup.ctl.allele_print_opt != last_setup.ctl.allele_print_opt { - changed = true; - } - if setup.ctl.join_alg_opt != last_setup.ctl.join_alg_opt { - changed = true; - } - if setup.ctl.clono_group_opt != last_setup.ctl.clono_group_opt { - changed = true; - } - if setup.ctl.parseable_opt != last_setup.ctl.parseable_opt { - changed = true; - } - if setup.ctl.pathlist != last_setup.ctl.pathlist { - changed = true; - } - if setup.ctl.last_modified != last_setup.ctl.last_modified { - changed = true; - } - } - - // Now proceed with the computation. - - let result; - if !changed { - result = main_enclone_stop(EncloneIntermediates { - setup: setup, - ex: self.enclone_state.lock().unwrap().inter.ex.clone(), - }); - } else { - let inter = main_enclone_start(setup); - if inter.is_err() { - let err_msg = format!("{}", inter.err().unwrap()); - let mut msg = format!("enclone failed, here is the error message:\n{}\n", err_msg); - if server_debug { - msg += &mut format!( - "The arguments provided to the server were\n{}.\n", - args.iter().format(" ") - ); - } - let response = EncloneResponse { - args: req.args, - plot: String::new(), - table: msg, - summary: String::new(), - metrics: Vec::::new(), - dataset_names: Vec::::new(), - table_comp: Vec::::new(), - last_widths: Vec::::new(), - }; - return Ok(Response::new(response)); - } - let inter = inter.unwrap(); - if inter.setup.tall.is_none() { - let response = EncloneResponse { - args: req.args, - plot: String::new(), - table: String::new(), - summary: String::new(), - metrics: Vec::::new(), - dataset_names: Vec::::new(), - table_comp: Vec::::new(), - last_widths: Vec::::new(), - }; - return Ok(Response::new(response)); - } - result = main_enclone_stop(inter); - } - if result.is_err() { - let err_msg = format!("{}", result.err().unwrap()); - let mut msg = format!("enclone failed, here is the error message:\n{}\n", err_msg); - if server_debug { - msg += &mut format!( - "The arguments provided to the server were\n{}.\n", - args.iter().format(" ") - ); - } - let response = EncloneResponse { - args: req.args, - plot: String::new(), - table: msg, - summary: String::new(), - metrics: Vec::::new(), - dataset_names: Vec::::new(), - table_comp: Vec::::new(), - last_widths: Vec::::new(), - }; - return Ok(Response::new(response)); - } - let output = result.unwrap(); - eprintln!("Enclone done, updating in-memory cache"); - // Update stored command - { - let mut enclone_command = self.enclone_command.lock().unwrap(); - *enclone_command = req.args.clone(); - } - // Update stored result - let response; - { - let mut enclone_state = self.enclone_state.lock().unwrap(); - *enclone_state = output; - let mut table = enclone_state.outs.pics.clone(); - let widths = enclone_state.outs.last_widths.clone(); - if !g_specified { - const MAX_TABLE: usize = 50; - if table.len() > MAX_TABLE { - table.truncate(MAX_TABLE); - } - } - let mut last_widths = Vec::::new(); - for i in 0..widths.len() { - last_widths.push(widths[i] as u32); - } - let table_string = combine_group_pics( - &table, - &widths, - enclone_state.outs.parseable_stdouth, - enclone_state.outs.noprint, - enclone_state.outs.noprintx, - enclone_state.outs.html, - enclone_state.outs.ngroup, - enclone_state.outs.pretty, - ); - let mut plot = String::new(); - if enclone_state.outs.svgs.len() > 0 { - plot = enclone_state.outs.svgs[0].clone(); - } - let full_table = enclone_state.outs.pics.clone(); - let serialized = serde_json::to_string(&full_table) - .unwrap() - .as_bytes() - .to_vec(); - let mut e = GzEncoder::new(Vec::new(), Compression::default()); - let _ = e.write_all(&serialized); - let gzipped = e.finish().unwrap(); - logme(&format!("plot=\n{}", plot)); - response = EncloneResponse { - args: req.args, - plot: plot, - table: table_string, - summary: enclone_state.outs.summary.clone(), - metrics: enclone_state.outs.metrics.clone(), - dataset_names: enclone_state.outs.dataset_names.clone(), - table_comp: gzipped, - last_widths: last_widths, - }; - if server_debug { - println!("sending response as follows:"); - println!("args = {}", response.args); - println!("plot = {}", response.plot); - println!("table = {}", response.table); - println!("summary = {}", response.summary); - } - } - if server_debug { - println!("returning response"); - } - Ok(Response::new(response)) - } - - async fn get_clonotype( - &self, - request: Request, - ) -> Result, Status> { - let req: ClonotypeRequest = request.into_inner(); - let id = req.clonotype_number as usize; - let enclone_state = self.enclone_state.lock().unwrap(); - if id >= enclone_state.outs.pics.len() { - return Err(Status::new(Code::Internal, "group id too large")); - } - - // Send back the clonotype picture. - let table = &enclone_state.outs.pics[id]; - Ok(Response::new(ClonotypeResponse { - table: table.to_string(), - })) - } - - async fn test_user_name( - &self, - request: Request, - ) -> Result, Status> { - let req: UserNameRequest = request.into_inner(); - let valid = is_user_name_valid(&req.user_name); - Ok(Response::new(UserNameResponse { value: valid })) - } - - async fn share_session( - &self, - request: Request, - ) -> Result, Status> { - let req: SendShareRequest = request.into_inner(); - for recip in req.recipients.iter() { - let mut bytes = req.content.clone(); - let rbytes = &recip.as_bytes(); - for i in 0..bytes.len() { - bytes[i] = bytes[i].wrapping_add(rbytes[i % rbytes.len()]); - } - let rdir = format!("{}/{}", req.share_dir, recip); - - // Create directory if needed. - - let dir_exists = path_exists(&rdir); - if !dir_exists { - let res = std::fs::create_dir(&rdir); - if res.is_err() { - return Err(Status::new( - Code::Internal, - "unable to create share directory", - )); - } - } - - // Set permissions to allow group and world write on the directory. Note that if the - // directory already existed, this may not work. In such cases group and world write - // should already be enabled, because some other user will have executed this same - // code to create the directory. - - #[cfg(not(target_os = "windows"))] - { - let perms = std::fs::Permissions::from_mode(0o777); - let res = std::fs::set_permissions(&rdir, perms.clone()); - if !dir_exists && res.is_err() { - return Err(Status::new( - Code::Internal, - format!("unable to set permissions on share directory {}", rdir), - )); - } - } - - // Now write the file. - - let mut now = format!("{:?}", Local::now()); - now = now.replace("T", "___"); - now = now.before(".").to_string(); - now = now.replace(":", "-"); - let filename = format!("{}/{}_{}", rdir, now, req.sender); - let res = std::fs::write(&filename, &bytes); - if res.is_err() { - return Err(Status::new(Code::Internal, "unable to write share file")); - } - #[cfg(not(target_os = "windows"))] - { - let perms = std::fs::Permissions::from_mode(0o777); - let res = std::fs::set_permissions(&filename, perms); - if res.is_err() { - return Err(Status::new( - Code::Internal, - format!("unable to set permissions on share file {}", filename), - )); - } - } - } - Ok(Response::new(SendShareResponse { ok: true })) - } - - async fn get_my_shares( - &self, - request: Request, - ) -> Result, Status> { - let req: GetMySharesRequest = request.into_inner(); - let dir = &req.share_dir; - let me_only = req.me_only; - let me = whoami::username(); - if !path_exists(&dir) { - return Err(Status::new( - Code::Internal, - "share directory does not exist", - )); - } - let rdir = format!("{}/{}", dir, me); - if !path_exists(&rdir) { - let res = std::fs::create_dir(&rdir); - if res.is_err() { - return Err(Status::new( - Code::Internal, - format!("unable to create my share directory {}", rdir), - )); - } - } - let all = dir_list(&rdir); - let n = all.len(); - let mut content = vec![Vec::::new(); n]; - let mut messages = vec![String::new(); n]; - let mut filenames = vec![String::new(); n]; - let rbytes = &me.as_bytes(); - for i in 0..n { - let filename = format!("{}/{}", rdir, all[i]); - let f = File::open(&filename); - if f.is_err() { - return Err(Status::new(Code::Internal, "unable to open share file")); - } - let mut f = f.unwrap(); - let mut bytes = Vec::::new(); - let res = f.read_to_end(&mut bytes); - if res.is_err() { - return Err(Status::new(Code::Internal, "unable to read share file")); - } - for i in 0..bytes.len() { - bytes[i] = bytes[i].wrapping_sub(rbytes[i % rbytes.len()]); - } - content[i] = bytes; - filenames[i] = all[i].clone(); - if !all[i].contains("_") { - return Err(Status::new(Code::Internal, "malformed file name")); - } - let sender = all[i].rev_after("_"); - if me_only && sender != me { - continue; - } - let when = all[i].rev_before("_"); - if !when.contains("___") { - return Err(Status::new( - Code::Internal, - format!("ill-formed file name {}", all[i]), - )); - } - let (date, time) = (when.before("___"), when.after("___")); - let msg = format!("session shared by {} on {} at {}", sender, date, time); - messages[i] = msg; - } - Ok(Response::new(GetMySharesResponse { - content: content, - messages: messages, - filenames: filenames, - })) - } - - async fn get_my_cookbooks( - &self, - request: Request, - ) -> Result, Status> { - let req: GetMyCookbooksRequest = request.into_inner(); - let dirs = &req.cookbook_dirs; - let mut cookbooks = Vec::>::new(); - for dir in dirs.iter() { - if path_exists(&*dir) { - let x = std::fs::read_dir(&*dir); - if x.is_ok() { - let x = x.unwrap(); - for f in x { - let s: String = f.unwrap().file_name().into_string().unwrap(); - let cb = format!("{}/{}", dir, s); - let mut f = File::open(&cb).unwrap(); - let mut bytes = Vec::::new(); - f.read_to_end(&mut bytes).unwrap(); - cookbooks.push(bytes); - } - } - } - } - Ok(Response::new(GetMyCookbooksResponse { - cookbooks: cookbooks, - })) - } - - async fn release_my_shares( - &self, - request: Request, - ) -> Result, Status> { - let req: ReleaseMySharesRequest = request.into_inner(); - let me = whoami::username(); - for i in 0..req.filenames.len() { - let path = format!("{}/{}/{}", req.share_dir, me, req.filenames[i]); - if path_exists(&path) { - let res = std::fs::remove_file(&path); - if res.is_err() { - return Err(Status::new(Code::Internal, "unable to remove file")); - } - } else { - return Err(Status::new( - Code::Internal, - format!("file to be removed does not exist: {}", path), - )); - } - } - Ok(Response::new(ReleaseMySharesResponse { ok: true })) - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub async fn enclone_server() -> Result<(), Box> { - PrettyTrace::new().on(); - let args: Vec = env::args().collect(); - let mut ip_port = "127.0.0.1:7000".to_string(); - if args.len() > 2 { - ip_port = args[2].clone(); - } - - // Force exit after 24 hours. Although the client is supposed to kill the server, sometimes - // this doesn't work for users (for unclear reasons). This is the fallback. A more - // sophisticated version would wait for a specified period of time after the last activity, - // and also communicate with the client before exiting. - - tokio::spawn(async move { - std::thread::sleep(Duration::from_secs(60 * 60 * 24)); - std::process::exit(0); - }); - - // Start server. - - let addr = ip_port; - let enclone_command = Arc::new(Mutex::new("".to_string())); - let enclone_state = Arc::new(Mutex::new(EncloneState::default())); - let analyzer = EncloneAnalyzer { - enclone_command: Arc::clone(&enclone_command), - enclone_state: Arc::clone(&enclone_state), - }; - - let listener = TcpListener::bind(addr).await?; - let local_addr = listener.local_addr()?; - - // Thread waits to print PORT for client until we can connect to our own endpoints. - - tokio::spawn(async move { - let dest = format!("http://{}", local_addr); - let tick = Instant::now(); - loop { - tokio::time::sleep(Duration::from_secs(1)).await; - match AnalyzerClient::connect(dest.clone()).await { - Ok(mut client) => match client.ping(Unit {}).await { - Ok(_) => { - println!("using port {}", local_addr.port()); - return; - } - Err(e) => warn!("failed to ping, ({:?}), reattempting in 1s", e), - }, - Err(e) => warn!("failed to connect ({:?}), reattempting in 1s", e), - } - if (Instant::now() - tick).as_secs() > 11 { - error!("Failed to initialize gRPC service, exiting..."); - std::process::exit(1); - } - } - }); - - // Some some info. - - let current_dir = std::env::current_dir()?; - let current_dir = current_dir.display(); - let current_executable = std::env::current_exe()?; - let current_executable = current_executable.display(); - - // Get version. - // - // This is what we had before. It is confusing and unsound: - // 1. current_version_string() can fail when it invokes the git command - // 2. it seems like we set version, and then sometimes set version to the same thing. - // - // Therefore, this code is commented out. But perhaps something in it needs to be salvaged. - // - // let mut version = current_version_string(); - // if format!("{}", current_executable) == format!("{}/target/debug/enclone", current_dir) { - // version = current_version_string(); - // } - // - // Subsequently we changed this to - // - // let version = env!("CARGO_PKG_VERSION"); - // - // but that wasn't right either, because enclone_client.rs would read that back and do - // the wrong thing. - // - // So finally we changed it to what is below. Note that this suffers from the defect that - // it is not properly updated. - - let version = version_string(); - - // Announce. - - let mut emsg = format!("I am process {}.\n", std::process::id()); - emsg += &mut format!("enclone version = {}\n", env!("CARGO_PKG_VERSION")); - emsg += &mut format!("version string = {}\n", version); - emsg += &mut format!( - "Welcome!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" - ); - emsg += &mut format!( - "Welcome!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" - ); - emsg += &mut format!( - "Welcome!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" - ); - emsg += &mut format!( - "Welcome!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" - ); - eprint!("{}", emsg); - - println!("current dir = {}", current_dir); - println!("current executable = {}", current_executable); - Server::builder() - .add_service(AnalyzerServer::new(analyzer)) - .serve_with_incoming(TcpListenerStream::new(listener)) - .await?; - - Ok(()) -} diff --git a/enclone_visual/src/geometry.rs b/enclone_visual/src/geometry.rs deleted file mode 100644 index 1f3d2a0aa3..0000000000 --- a/enclone_visual/src/geometry.rs +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Basic geometric objects, allowing representation of simple SVG files as vectors of such objects. - -#[derive(PartialEq, Clone)] -pub enum Geometry { - Segment(Segment), - Text(Text), - Circle(Circle), - CircleWithStroke(CircleWithStroke), - CircleWithTooltip(CircleWithTooltip), - CircleWithTooltipAndStroke(CircleWithTooltipAndStroke), - Rectangle(Rectangle), - PolySegment(PolySegment), -} - -#[derive(PartialEq, Clone)] -pub struct Color { - pub r: u8, // red - pub g: u8, // green - pub b: u8, // blue - pub t: u8, // transparency (255 = not transparent at all) -} - -impl Color { - pub fn new(r: u8, g: u8, b: u8, t: u8) -> Color { - Color { - r: r, - g: g, - b: b, - t: t, - } - } - - pub fn from_tuple(x: (u8, u8, u8, u8)) -> Color { - Color { - r: x.0, - g: x.1, - b: x.2, - t: x.3, - } - } - - pub fn from_tuple_plus(x: (u8, u8, u8), t: u8) -> Color { - Color { - r: x.0, - g: x.1, - b: x.2, - t: t, - } - } -} - -#[derive(Default, PartialEq, Clone)] -pub struct Point { - pub x: f32, - pub y: f32, -} - -impl Point { - pub fn new(x: f32, y: f32) -> Point { - Point { x: x, y: y } - } -} - -#[derive(PartialEq, Clone)] -pub struct Circle { - pub p: Point, - pub r: f32, - pub c: Color, -} - -#[derive(PartialEq, Clone)] -pub struct CircleWithStroke { - pub p: Point, - pub r: f32, - pub c: Color, - pub w: f32, // stroke width - pub s: Color, // stroke color -} - -#[derive(PartialEq, Clone)] -pub enum HorizontalAlignment { - Left, - Center, - Right, -} - -#[derive(PartialEq, Clone)] -pub struct Text { - pub p: Point, - pub halign: HorizontalAlignment, - pub t: String, - pub font: String, - pub font_size: f32, - pub c: Color, - pub rotate: [f32; 3], -} - -#[derive(PartialEq, Clone)] -pub struct CircleWithTooltip { - pub p: Point, - pub r: f32, - pub c: Color, - pub t: String, -} - -#[derive(PartialEq, Clone)] -pub struct CircleWithTooltipAndStroke { - pub p: Point, - pub r: f32, - pub c: Color, - pub t: String, - pub w: f32, // stroke width - pub s: Color, // stroke color -} - -#[derive(PartialEq, Clone)] -pub struct Segment { - pub p1: Point, // start - pub p2: Point, // stop - pub w: f32, // width - pub c: Color, -} - -#[derive(PartialEq, Clone)] -pub struct PolySegment { - pub p: Vec, // points - pub w: f32, // width - pub c: Color, // color -} - -#[derive(PartialEq, Clone)] -pub struct Rectangle { - pub p: Point, // coordinates of upper left corner - pub width: f32, // width - pub height: f32, // height - pub fill_color: Color, // fill color - pub stroke_width: f32, // stroke width - pub stroke_color: Color, // stroke color -} diff --git a/enclone_visual/src/gui.rs b/enclone_visual/src/gui.rs deleted file mode 100644 index 15ae534352..0000000000 --- a/enclone_visual/src/gui.rs +++ /dev/null @@ -1,822 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::apocalypse::*; -use crate::archive::*; -use crate::dimensions::*; -use crate::help::*; -use crate::history::*; -use crate::popover::*; -use crate::summary::*; -use crate::testsuite::*; -use crate::*; -use gui_structures::ComputeState::*; -use gui_structures::*; -use iced::Length::Units; -use iced::{ - Alignment, Application, Button, Color, Column, Command, Container, Element, Image, Length, Row, - Rule, Scrollable, Space, Subscription, Text, TextInput, -}; -// use iced::Subscription; -// use iced_native::{window, Event}; -use iced_native::{event, subscription, window, Event}; -use io_utils::*; -use messages::Message; -use std::fs::{create_dir, create_dir_all, metadata, remove_file, File}; -use std::io::{Read, Write}; -use std::sync::atomic::Ordering::SeqCst; -use std::thread; -use std::time::Duration; - -fn handle_resize(width: u32, height: u32) -> Option { - Some(Message::Resize(width, height)) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -impl Application for EncloneVisual { - type Executor = iced::executor::Default; - type Message = Message; - type Flags = (); - - fn new(_flags: ()) -> (EncloneVisual, Command) { - prepare_for_apocalypse_visual(); - let mut x = EncloneVisual::default(); - x.inputn = vec![iced::text_input::State::default(); EXTRA_INPUTS]; - x.inputn_value.resize(EXTRA_INPUTS, String::new()); - x.submit_button_text = "Submit".to_string(); - x.compute_state = WaitingForRequest; - x.copy_image_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.graphic_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.command_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.clonotypes_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.summary_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.archive_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.sanity_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.archive_refresh_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.copy_selected_metrics_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.clonotypes_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.tooltip_toggle_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.alluvial_tables_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.alluvial_tables_cr_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.alluvial_tables_crd_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.alluvial_reads_tables_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.alluvial_reads_tables_cr_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.alluvial_reads_tables_crd_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.descrips_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.png_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.graphic_help_title = "Help".to_string(); - x.width = INITIAL_WIDTH; - CURRENT_WIDTH.store(INITIAL_WIDTH as usize, SeqCst); - CURRENT_WIDTH_LAST_SEEN.store(INITIAL_WIDTH as usize, SeqCst); - CURRENT_HEIGHT.store(INITIAL_HEIGHT as usize, SeqCst); - CURRENT_HEIGHT_LAST_SEEN.store(INITIAL_HEIGHT as usize, SeqCst); - x.height = INITIAL_HEIGHT; - - // Find ~/enclone/visual. - - let enclone; - if EHOME.lock().unwrap().len() > 0 { - enclone = EHOME.lock().unwrap()[0].clone(); - } else { - let home = home::home_dir(); - if home.is_none() { - eprintln!( - "Unable to determine home directory. This is unexpected and \ - pathological.\nPlease report this problem!\n" - ); - std::process::exit(1); - } - enclone = format!("{}/enclone", home.unwrap().display()); - } - if !path_exists(&enclone) { - eprintln!( - "Oddly, you do not have a directory {}. Normally this would be\n\ - created by following the installation instructions at bit.ly/enclone. Please do \ - that or at least create the directory.\n", - enclone, - ); - std::process::exit(1); - } - x.visual = format!("{}/visual", enclone); - if VISUAL_DIR.lock().unwrap().len() > 0 { - x.visual = VISUAL_DIR.lock().unwrap()[0].clone(); - } - - // Proceed. - - let history = format!("{}/history", x.visual); - if !path_exists(&history) { - let res = create_dir_all(&history); - if res.is_err() { - eprintln!( - "Unable to create the directory ~/enclone/visual/history. This is odd and \ - unexpected.\nPlease report this problem!\n" - ); - std::process::exit(1); - } - } - x.sharing_enabled = REMOTE_SHARE.lock().unwrap().len() > 0; - x.archive_dir = Some(history.clone()); - - // Read shares. If the file is corrupted, silently ignore it. - - if x.sharing_enabled { - let shares = format!("{}/shares", x.visual); - if path_exists(&shares) { - let share_size = std::fs::metadata(&shares).unwrap().len() as usize; - let n = std::mem::size_of::(); - if share_size % n == 0 { - let mut bytes = Vec::::new(); - let mut f = File::open(&shares).unwrap(); - f.read_to_end(&mut bytes).unwrap(); - assert_eq!(bytes.len(), share_size); - unsafe { - x.shares = bytes.align_to::().1.to_vec(); - } - } - } - } - - // Keep going. - - if x.archive_dir.is_some() { - let arch_dir = &x.archive_dir.as_ref().unwrap(); - if path_exists(&arch_dir) { - if metadata(&arch_dir).unwrap().is_dir() { - x.archive_list = dir_list(&arch_dir); - } - } - } - x.archive_list.reverse(); - let n = x.archive_list.len(); - x.restore_requested = vec![false; n]; - x.delete_requested = vec![false; n]; - x.deleted = vec![false; n]; - x.expand_archive_entry = vec![false; n]; - x.restore_msg = vec![String::new(); n]; - x.archived_command_list = vec![None; n]; - x.archive_name = vec![iced::text_input::State::default(); n]; - x.archive_name_value = vec![String::new(); n]; - x.archive_name_change_button_color = vec![Color::from_rgb(0.0, 0.0, 0.0); n]; - x.copy_archive_narrative_button_color = vec![Color::from_rgb(0.0, 0.0, 0.0); n]; - x.archive_name_change_button = vec![iced::button::State::default(); n]; - x.archive_narrative_button = vec![iced::button::State::default(); n]; - x.copy_archive_narrative_button = vec![iced::button::State::default(); n]; - x.archive_share_requested = vec![false; n]; - x.archive_origin = vec![String::new(); n]; - x.archive_narrative = vec![String::new(); n]; - x.copy_narrative_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.copy_summary_button_color = Color::from_rgb(0.0, 0.0, 0.0); - x.graphic_png_title = "PNG".to_string(); - - // Fetch cookbooks. For remote cookbooks, we keep a local copy, which may or may not - // be current. - - let cookbook_dir = include_dir::include_dir!("src/cookbooks"); - for cookbook in cookbook_dir.find("*.cb").unwrap() { - let f = cookbook_dir.get_file(cookbook.path()).unwrap(); - x.cookbooks.push(f.contents().to_vec()); - } - GET_MY_COOKBOOKS.store(true, SeqCst); - while GET_MY_COOKBOOKS.load(SeqCst) { - thread::sleep(Duration::from_millis(10)); - } - if !META_TESTING.load(SeqCst) && !TEST_MODE.load(SeqCst) { - let local_remote = format!("{}/remote_cookbooks", x.visual); - if REMOTE.load(SeqCst) { - if path_exists(&local_remote) { - let list = dir_list(&local_remote); - for f in list.iter() { - remove_file(&format!("{}/{}", local_remote, f)).unwrap(); - } - } else { - create_dir(&local_remote).unwrap(); - } - let n = REMOTE_COOKBOOKS.lock().unwrap().len(); - for i in 0..n { - let content = &REMOTE_COOKBOOKS.lock().unwrap()[i]; - x.cookbooks.push(content.clone()); - let f = format!("{}/{}", local_remote, i + 1); - let mut file = File::create(&f).unwrap(); - file.write_all(&content).unwrap(); - } - } else if path_exists(&local_remote) { - let list = dir_list(&local_remote); - for f in list.iter() { - let mut h = File::open(&format!("{}/{}", local_remote, f)).unwrap(); - let mut content = Vec::::new(); - h.read_to_end(&mut content).unwrap(); - x.cookbooks.push(content); - } - } - } - let nc = x.cookbooks.len(); - x.expand_cookbook_entry = vec![false; nc]; - x.restore_cookbook_requested = vec![false; nc]; - x.cookbook_narrative_button = vec![iced::button::State::default(); nc]; - x.copy_cookbook_narrative_button = vec![iced::button::State::default(); nc]; - x.copy_cookbook_narrative_button_color = vec![Color::from_rgb(0.0, 0.0, 0.0); nc]; - x.restore_cookbook_msg = vec![String::new(); nc]; - for i in 0..nc { - let evh = EncloneVisualHistory::restore_from_bytes(&x.cookbooks[i]).unwrap(); - x.cookbook_name.push(evh.name_value.clone()); - let mut cc = Vec::::new(); - for j in 0..evh.translated_input_history.len() { - cc.push( - evh.translated_input_hist_uniq[evh.translated_input_history[j] as usize] - .clone(), - ); - } - x.cookbook_command_list.push(Some(cc)); - x.cookbook_narrative.push(evh.narrative.clone()); - } - - // Handle test and meta modes. - - if EXEC.lock().unwrap().len() > 0 { - let cmd = EXEC.lock().unwrap()[0].clone(); - x.input1_value = cmd.clone(); - x.input_value = cmd; - (x, Command::perform(noop(), Message::SubmitButtonPressed)) - } else if !TEST_MODE.load(SeqCst) && !META_TESTING.load(SeqCst) { - (x, Command::none()) - } else if !META_TESTING.load(SeqCst) { - thread::sleep(Duration::from_millis(1000)); - (x, Command::perform(noop(), Message::RunTests)) - } else { - let id = META.load(SeqCst); // id of meta test - x.this_meta = metatests()[id].clone(); - x.meta_pos = 0; - (x, Command::perform(noop0(), Message::Meta)) - } - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - fn title(&self) -> String { - String::from("EncloneVisual") - } - - fn update(&mut self, message: Message) -> Command { - self.process_message(message) - } - - /* - fn should_exit(&self) -> bool { - self.should_exit - } - - fn subscription(&self) -> Subscription { - iced_native::subscription::events().map(Message::EventOccurred) - } - */ - - // The subscription detects window resize events and uses those to reset - // self.width and self.height. - - fn subscription(&self) -> Subscription { - subscription::events_with(|event, status| { - if let event::Status::Captured = status { - return None; - } - match event { - Event::Window(window::Event::Resized { width, height }) => { - handle_resize(width, height) - } - _ => None, - } - }) - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - fn view(&mut self) -> Element { - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Handle popovers. - - if self.summary_mode { - return summary(self); - } - if self.graphic_mode { - return graphic(self); - } - if self.clonotypes_mode { - return clonotypes(self); - } - if self.console_mode { - return console(self); - } - if self.archive_mode { - return archive(self); - } - if self.help_mode { - return help(self); - } - if self.command_mode { - return command(self); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Now do everything else. - - let text_input1 = TextInput::new( - &mut self.input1, - "", - &self.input1_value, - Message::InputChanged1, - ) - .padding(7) - .font(DEJAVU_BOLD) - .size(16); - let text_input2 = TextInput::new( - &mut self.input2, - "", - &self.input2_value, - Message::InputChanged2, - ) - .padding(7) - .font(DEJAVU_BOLD) - .size(16); - let mut text_input_column = Column::new() - .spacing(5) - .width(iced::Length::Fill) - .push(text_input1); - let mut more = false; - for j in 0..self.inputn_value.len() { - if self.inputn_value[j].len() > 0 { - more = true; - } - } - - if !more { - text_input_column = text_input_column.push(text_input2); - } else { - text_input_column = text_input_column.push(Space::with_height(Units(2))).push( - Text::new("(push Cmd to see full command)") - .font(DEJAVU_BOLD) - .size(16) - .color(Color::from_rgb(1.0, 0.0, 0.0)), - ); - } - - let button = Button::new( - &mut self.button, - Text::new(if self.compute_state == WaitingForRequest { - "Submit" - } else { - "thinking" - }) - .font(LIBERATION_SANS) - .color(if self.compute_state == WaitingForRequest { - Color::from_rgb(0.0, 0.0, 0.0) - } else { - Color::from_rgb(1.0, 0.0, 0.0) - }), - ) - .padding(10) - .on_press(Message::SubmitButtonPressed(Ok(()))); - let clear_button = Button::new( - &mut self.clear_button, - Text::new("Clear").font(LIBERATION_SANS), - ) - .padding(10) - .on_press(Message::ClearButtonPressed); - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Define the button complex that is the "control panel". - - let mut blank = false; - if self.h.history_index > 0 { - blank = self.h.is_blank[self.h.history_index as usize - 1]; - } - let command_complex_height; - let mut command_complex = Row::new().spacing(10); - { - const FB_BUTTON_FONT_SIZE: u16 = 45; - let back_button = Button::new( - &mut self.back_button, - Text::new("⇧").font(DEJAVU_BOLD).size(FB_BUTTON_FONT_SIZE), - ) - .on_press(Message::BackButtonPressed(Ok(()))); - - let forward_button = Button::new( - &mut self.forward_button, - Text::new("⇩").font(DEJAVU_BOLD).size(FB_BUTTON_FONT_SIZE), - ) - .on_press(Message::ForwardButtonPressed(Ok(()))); - - const COPY_BUTTON_FONT_SIZE: u16 = 15; - let del_button = Button::new( - &mut self.del_button, - Text::new("Del ") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::DelButtonPressed(Ok(()))); - - let null_button1 = Button::new( - &mut self.null_button1, - Text::new(" ").font(DEJAVU_BOLD).size(FB_BUTTON_FONT_SIZE), - ) - .on_press(Message::DoNothing); - - let null_button2 = Button::new( - &mut self.null_button2, - Text::new(" ").font(DEJAVU_BOLD).size(FB_BUTTON_FONT_SIZE), - ) - .on_press(Message::DoNothing); - let copy_image_button = Button::new( - &mut self.copy_image_button, - Text::new("Copy image") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE) - .color(self.copy_image_button_color), - ) - .on_press(Message::GraphicsCopyButtonPressed); - let null_copy_image_button = Button::new( - &mut self.null_button3, - Text::new(" ") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::GraphicsCopyButtonPressed); - let mut state_pos = format!("{}", self.h.history_index); - if state_pos.len() == 1 { - state_pos += " "; - } else if state_pos.len() == 2 { - state_pos += " "; - } - let state_pos_button = Button::new( - &mut self.state_pos_button_null, - Text::new(&state_pos) - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::DoNothing); - - let mut button_column2 = Column::new().spacing(8); - button_column2 = button_column2.push(state_pos_button); - if self.h.history_index > 1 { - button_column2 = button_column2.push(back_button); - } else { - button_column2 = button_column2.push(null_button1); - } - if (self.h.history_index as usize) < self.h.svg_history.len() { - button_column2 = button_column2.push(forward_button); - } else { - button_column2 = button_column2.push(null_button2); - } - button_column2 = button_column2.push(del_button); - - // Add command box. - - const MAX_LINE: usize = 35; - let mut log_lines = 1; - let mut log = String::new(); - if self.h.history_index >= 1 { - let cmd = self.h.translated_input_hist_uniq - [self.h.translated_input_history[self.h.history_index as usize - 1] as usize] - .clone(); - let mut rows = Vec::>::new(); - let folds = fold(&cmd, MAX_LINE); - log_lines = folds.len(); - for i in 0..folds.len() { - rows.push(vec![folds[i].clone()]); - } - for i in 0..rows.len() { - if i > 0 { - log += "\n"; - } - log += &mut rows[i][0].clone(); - } - } - - // Create some buttons. - - let command_button = Button::new( - &mut self.command_button, - Text::new("Cmd") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::CommandOpen(Ok(()))); - let summary_button = Button::new( - &mut self.summary_button, - Text::new("Summary") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::SummaryOpen(Ok(()))); - let graphic_button = Button::new( - &mut self.graphic_open_button, - Text::new("Pic") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::GraphicOpen(Ok(()))); - let clonotypes_button = Button::new( - &mut self.clonotypes_open_button, - Text::new("Clono") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::ClonotypesOpen(Ok(()))); - let mut summary_buttons_row = Row::new().spacing(8); - if !blank { - summary_buttons_row = summary_buttons_row.push(graphic_button); - } - summary_buttons_row = summary_buttons_row - .push(clonotypes_button) - .push(summary_button) - .push(command_button); - - // Create narrative button. - - let narrative_width; - if !blank { - narrative_width = MAX_LINE; - } else { - narrative_width = 100; - } - let mut logx = String::new(); - let mut logx_lines = 1; - let mut have_narrative = false; - if self.h.history_index >= 1 { - let mut cmd = self.h.narrative_hist_uniq - [self.h.narrative_history[self.h.history_index as usize - 1] as usize] - .clone(); - if cmd.len() == 0 { - cmd = "Narrative: click to paste in clipboard".to_string(); - } else { - have_narrative = true; - } - let mut rows = Vec::>::new(); - let folds = fold(&cmd, narrative_width); - logx_lines = folds.len(); - for i in 0..folds.len() { - rows.push(vec![folds[i].clone()]); - } - for i in 0..rows.len() { - if i > 0 { - logx += "\n"; - } - logx += &mut rows[i][0].clone(); - } - } - let narrative_button = Button::new( - &mut self.narrative_button, - Text::new(&logx) - .font(DEJAVU_BOLD) - .size(12) - .color(Color::from_rgb(1.0, 0.0, 0.5)), - ) - .on_press(Message::Narrative); - - let copy_narrative_button = Button::new( - &mut self.copy_narrative_button, - Text::new("Copy") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE) - .color(self.copy_narrative_button_color), - ) - .on_press(Message::CopyNarrative); - - // Build the command column. - - let mut row = Row::new().spacing(8); - if self.h.history_index >= 1 && !self.h.is_blank[self.h.history_index as usize - 1] { - row = row.push(copy_image_button); - } else { - row = row.push(null_copy_image_button); - } - row = row.push( - Button::new( - &mut self.command_copy_button, - Text::new("Copy command") - .font(LIBERATION_SANS) - .size(COPY_BUTTON_FONT_SIZE), - ) - .on_press(Message::CommandCopyButtonPressed), - ); - let mut col = Column::new().spacing(8).align_items(Alignment::End); - const SMALL_FONT: u16 = 12; - command_complex_height = ((1 + log_lines + logx_lines) * SMALL_FONT as usize) - + (4 * 8) - + (2 * COPY_BUTTON_FONT_SIZE as usize); - col = col.push( - Button::new( - &mut self.null_button, - Text::new(&log).font(DEJAVU_BOLD).size(SMALL_FONT), - ) - .on_press(Message::DoNothing), - ); - col = col.push(row); - col = col.push(summary_buttons_row); - col = col.push(narrative_button); - if have_narrative { - col = col.push(copy_narrative_button); - } - - // Add the command column to the row. - - command_complex = command_complex.push(col); - - // Add up and down arrows. - - command_complex = command_complex.push(button_column2); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Build the scrollable for clonotypes. We truncate lines to prevent wrapping. - - const CLONOTYPE_FONT_SIZE: u16 = 13; - let font_width = CLONOTYPE_FONT_SIZE as f32 * DEJAVU_WIDTH_OVER_HEIGHT; - let available = self.width - (3 * SPACING + SCROLLBAR_WIDTH) as u32; - let nchars = (available as f32 / font_width).round() as usize; - let mut trunc = String::new(); - let failed = self.output_value.contains("enclone failed"); - for line in self.output_value.lines() { - for (i, c) in line.chars().enumerate() { - if i == nchars && !failed { - break; - } - trunc.push(c); - } - trunc.push('\n'); - } - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(SCROLLBAR_WIDTH) - .scroller_width(12) - .style(style::ScrollableStyle) - .push( - Text::new(&trunc) - .font(DEJAVU_BOLD) - .size(CLONOTYPE_FONT_SIZE), - ); - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Fix the height of the SVG. This needs to be set so that there is enough room for - // the clonotype tables. We do not set the width because it's the height that we need - // to control. - - let mut svg_height = SVG_HEIGHT as f32; - if blank { - svg_height = SVG_NULL_HEIGHT as f32; - } - svg_height *= CURRENT_HEIGHT.load(SeqCst) as f32 / INITIAL_HEIGHT as f32; - // 85 is a fudge factor: - svg_height = svg_height.max(command_complex_height as f32 + 85.0); - let svg_height = svg_height.round() as u16; - - // Display the SVG. - - let png_banner = include_bytes!("../../img/enclone_banner.png").to_vec(); - let banner = Image::new(iced::image::Handle::from_memory(png_banner)).width(Units(500)); - - let have_canvas = self.canvas_view.state.geometry_value.is_some(); - let mut graphic_row = Row::new().spacing(10); - if self.svg_value.len() > 0 { - // Show the graphic. - - if have_canvas { - graphic_row = graphic_row - .push( - self.canvas_view - .view() - .map(move |message| Message::GroupClicked(message)), - ) - .height(Units(svg_height)); - } else { - let svg_as_png = - Image::new(iced::image::Handle::from_memory(self.png_value.clone())) - .height(Units(svg_height)); - graphic_row = graphic_row.push(svg_as_png); - } - - // Insert space to push the graphic to the left and the command column to the right. - - if !have_canvas { - graphic_row = graphic_row.push(Space::with_width(Length::Fill)); - } - graphic_row = graphic_row.push(command_complex); - } - - // ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - - // Put it all together. - - let left_buttons = Column::new() - .spacing(8) - .push( - Button::new( - &mut self.exit_state, - Text::new("Exit").font(LIBERATION_SANS), - ) - .on_press(Message::Exit), - ) - .push( - Button::new( - &mut self.open_state, - Text::new("Help").font(LIBERATION_SANS), - ) - .on_press(Message::HelpOpen(Ok(()))), - ); - let console_button = Button::new( - &mut self.console_open_button, - Text::new("Console").font(LIBERATION_SANS), - ) - .on_press(Message::ConsoleOpen); - let _snapshot_button = Button::new( - &mut self.snapshot_button, - Text::new("Snapshot") - .font(LIBERATION_SANS) - .color(self.snapshot_button_color), - ) - .on_press(Message::Snapshot); - let mut console_row = Row::new().spacing(8); - #[cfg(any(target_os = "macos", target_os = "ios"))] - { - console_row = console_row.push(_snapshot_button); - } - console_row = console_row.push(console_button); - let mut save_text = Text::new("Save").font(LIBERATION_SANS); - if self.save_in_progress { - save_text = save_text.color(Color::from_rgb(1.0, 0.0, 0.0)); - } - let save_button = Button::new(&mut self.save_button, save_text).on_press(Message::Save); - let mut save_on_exit_text = Text::new("On Exit").font(LIBERATION_SANS).width(Units(66)); - if self.save_on_exit { - save_on_exit_text = save_on_exit_text.color(Color::from_rgb(1.0, 0.0, 0.0)); - } - let save_on_exit_button = Button::new(&mut self.save_on_exit_button, save_on_exit_text) - .on_press(Message::SaveOnExit); - let save_row = Row::new() - .spacing(8) - .push(save_button) - .push(save_on_exit_button); - let tooltip_button = Button::new( - &mut self.tooltip_toggle_button, - Text::new("Tooltip") - .font(LIBERATION_SANS) - .color(self.tooltip_toggle_button_color), - ) - .on_press(Message::TooltipToggle); - let archive_button = Button::new( - &mut self.archive_open_button, - Text::new("Archive").font(LIBERATION_SANS).width(Units(66)), - ) - .on_press(Message::ArchiveOpen(Ok(()))); - let archive_row = Row::new() - .spacing(8) - .push(tooltip_button) - .push(archive_button); - let mut top_row = Row::new() - .align_items(Alignment::Center) - .push(left_buttons) - .push(Space::with_width(Length::Fill)) - .push(banner) - .push(Space::with_width(Length::Fill)); - let right_col = Column::new() - .align_items(Alignment::End) - .spacing(8) - .push(console_row) - .push(save_row) - .push(archive_row); - top_row = top_row.push(right_col); - let mut content = Column::new() - .spacing(SPACING) - .padding(20) - .push(top_row) - .push( - Row::new() - .spacing(10) - .align_items(Alignment::Center) - .push(text_input_column) - .push(button) - .push(clear_button), - ) - // .push(Row::new().spacing(10).push(svg)) - .push(graphic_row); - if self.h.svg_history.len() > 0 { - content = content.push(Rule::horizontal(10).style(style::RuleStyle)); - } - content = content.push( - Row::new() - .height(Length::Units(1000)) // Height of scrollable window, maybe?? - .align_items(Alignment::Center) - .push(scrollable), - ); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() - } -} diff --git a/enclone_visual/src/gui_structures.rs b/enclone_visual/src/gui_structures.rs deleted file mode 100644 index 1b063424bc..0000000000 --- a/enclone_visual/src/gui_structures.rs +++ /dev/null @@ -1,436 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::history::*; -use crate::messages::*; -use crate::*; -use canvas_view::CanvasView; -use chrono::prelude::*; -use enclone_core::packing::*; -use flate2::read::GzDecoder; -use iced::{button, scrollable, text_input, Color}; -// use iced::Subscription; -// use iced_native::{window, Event}; -use std::io::Read; -use std::time::Instant; - -#[derive(PartialEq)] -pub enum ComputeState { - WaitingForRequest, - Thinking, -} - -impl Default for ComputeState { - fn default() -> ComputeState { - WaitingForRequest - } -} - -pub fn convert_bytes_to_string(bytes: &[u8]) -> String { - base64::encode(&bytes) -} - -pub fn convert_string_to_bytes(s: &str) -> Vec { - base64::decode(&s).unwrap() -} - -pub struct Summary { - pub summary: String, - pub dataset_names: Vec, - pub metrics: Vec>, - pub metric_selected: Vec, - pub metrics_condensed: bool, -} - -impl Summary { - pub fn pack(&self) -> String { - let mut bytes = Vec::::new(); - bytes.append(&mut save_string(&self.summary)); - bytes.append(&mut save_vec_string(&self.dataset_names)); - bytes.append(&mut save_vec_vec_string(&self.metrics)); - bytes.append(&mut save_vec_bool(&self.metric_selected)); - bytes.extend(save_bool(self.metrics_condensed)); - convert_bytes_to_string(&bytes) - } - - pub fn unpack(s: &str) -> Self { - let bytes = convert_string_to_bytes(&s); - let mut pos = 0; - let summary = restore_string(&bytes, &mut pos).unwrap(); - let dataset_names = restore_vec_string(&bytes, &mut pos).unwrap(); - let metrics = restore_vec_vec_string(&bytes, &mut pos).unwrap(); - let metric_selected = restore_vec_bool(&bytes, &mut pos).unwrap(); - let metrics_condensed = restore_bool(&bytes, &mut pos).unwrap(); - Summary { - summary: summary, - dataset_names: dataset_names, - metrics: metrics, - metric_selected: metric_selected, - metrics_condensed: metrics_condensed, - } - } -} - -use ComputeState::*; - -#[derive(Default)] -pub struct EncloneVisual { - pub modified: bool, - pub scroll: scrollable::State, - pub summary_scroll: scrollable::State, - pub clonotypes_scroll: scrollable::State, - pub input1: text_input::State, - pub input2: text_input::State, - pub inputn: Vec, - pub input1_value: String, - pub input2_value: String, - pub inputn_value: Vec, - pub narrative_value: String, - pub input_value: String, - pub translated_input_value: String, - pub output_value: String, - pub svg_value: String, - pub png_value: Vec, - pub summary_value: String, - pub table_comp_value: Vec, - pub last_widths_value: Vec, - pub descrip_value: String, - pub submit_button_text: String, - // pub should_exit: bool, - pub compute_state: ComputeState, - pub copy_image_button_color: Color, - pub snapshot_button_color: Color, - pub graphic_snapshot_button_color: Color, - pub command_snapshot_button_color: Color, - pub clonotypes_snapshot_button_color: Color, - pub summary_snapshot_button_color: Color, - pub archive_snapshot_button_color: Color, - pub sanity_button_color: Color, - pub clonotypes_copy_button_color: Color, - pub tooltip_toggle_button_color: Color, - pub descrips_copy_button_color: Color, - pub png_button_color: Color, - pub canvas_view: CanvasView, - pub window_id: usize, - pub start_command: Option, - pub help_mode: bool, - pub command_mode: bool, - pub summary_mode: bool, - pub console_mode: bool, - pub archive_mode: bool, - pub clonotypes_mode: bool, - pub graphic_mode: bool, - pub graphic_help_mode: bool, - pub save: bool, - pub save_in_progress: bool, - pub save_on_exit: bool, - pub shares: Vec, - pub visual: String, - pub meta_pos: usize, - pub metric_selected: Vec, - pub metrics_condensed: bool, - pub snapshot_start: Option, - pub summary_png_start: Option, - pub graphic_snapshot_start: Option, - pub command_snapshot_start: Option, - pub clonotypes_snapshot_start: Option, - pub summary_snapshot_start: Option, - pub archive_snapshot_start: Option, - pub sanity_check_start: Option, - pub alluvial_tables_for_spreadsheet: String, - pub alluvial_tables_for_spreadsheet_cr: String, - pub alluvial_tables_for_spreadsheet_crd: String, - pub alluvial_tables_copy_button_color: Color, - pub alluvial_tables_cr_copy_button_color: Color, - pub alluvial_tables_crd_copy_button_color: Color, - pub alluvial_reads_tables_for_spreadsheet: String, - pub alluvial_reads_tables_for_spreadsheet_cr: String, - pub alluvial_reads_tables_for_spreadsheet_crd: String, - pub alluvial_reads_tables_copy_button_color: Color, - pub alluvial_reads_tables_cr_copy_button_color: Color, - pub alluvial_reads_tables_crd_copy_button_color: Color, - pub descrips_for_spreadsheet: String, - pub graphic_png_title: String, - pub graphic_help_title: String, - // - // current tables: suboptimal, as it would be better to keep some sort of vector of compressed - // strings (allowing for compression to extend across the vector); see also - // table_comp_hist_uniq[i], which is compressed, but doesn't allow access to individual entries - // - pub current_tables: Vec, - // - // button states: - // - pub button: button::State, - pub back_button: button::State, - pub forward_button: button::State, - pub del_button: button::State, - pub exec_button: button::State, - pub summary_button: button::State, - pub exit_state: button::State, - pub copy_image_button: button::State, - pub command_copy_button: button::State, - pub null_button1: button::State, - pub null_button2: button::State, - pub null_button3: button::State, - pub null_button: button::State, - pub state_pos_button_null: button::State, - pub clear_button: button::State, - pub open_state: button::State, - pub help_button: button::State, - pub cookbook_button: button::State, - pub console_open_button: button::State, - pub console_close_button: button::State, - pub save_button: button::State, - pub save_on_exit_button: button::State, - pub archive_open_button: button::State, - pub archive_close_button: button::State, - pub archive_save_close_button: button::State, - pub archive_refresh_button: button::State, - pub open_archive_doc_button: button::State, - pub close_archive_doc_button: button::State, - pub open_alluvial_reads_doc_button: button::State, - pub close_alluvial_reads_doc_button: button::State, - pub archive_name_change_button: Vec, - pub archive_narrative_button: Vec, - pub copy_archive_narrative_button: Vec, - pub copy_cookbook_narrative_button: Vec, - pub narrative_button: button::State, - pub copy_narrative_button: button::State, - pub cookbook_narrative_button: Vec, - pub summary_copy_button: button::State, - pub copy_summary_button_color: Color, - pub metric_button: Vec, - pub condense_metrics_button: button::State, - pub copy_selected_metrics_button: button::State, - pub copy_selected_metrics_button_color: Color, - pub snapshot_button: button::State, - pub graphic_snapshot_button: button::State, - pub command_snapshot_button: button::State, - pub clonotypes_snapshot_button: button::State, - pub summary_snapshot_button: button::State, - pub archive_snapshot_button: button::State, - pub recompute_button: button::State, - pub sanity_button: button::State, - pub clonotypes_open_button: button::State, - pub clonotypes_close_button: button::State, - pub graphic_open_button: button::State, - pub graphic_close_button: button::State, - pub clonotypes_copy_button: button::State, - pub tooltip_toggle_button: button::State, - pub alluvial_tables_copy_button: button::State, - pub alluvial_tables_cr_copy_button: button::State, - pub alluvial_tables_crd_copy_button: button::State, - pub alluvial_reads_tables_copy_button: button::State, - pub alluvial_reads_tables_cr_copy_button: button::State, - pub alluvial_reads_tables_crd_copy_button: button::State, - pub descrips_copy_button: button::State, - pub graphic_png_button: button::State, - pub graphic_help_button: button::State, - pub command_button: button::State, - pub command_close_button: button::State, - // - // more - // - pub this_meta: Vec, - pub save_name: String, - pub cookbooks: Vec>, - // - // history - // - pub h: EncloneVisualHistory, - // - // archive information and logic - // - pub archive_dir: Option, - pub archive_list: Vec, - pub expand_archive_entry: Vec, - pub expand_cookbook_entry: Vec, - pub restore_requested: Vec, - pub restore_cookbook_requested: Vec, - pub delete_requested: Vec, - pub deleted: Vec, - pub restore_msg: Vec, - pub restore_cookbook_msg: Vec, - pub just_restored: bool, - pub archived_command_list: Vec>>, - pub cookbook_command_list: Vec>>, - pub archive_name: Vec, - pub archive_name_value: Vec, - pub name: text_input::State, - pub name_change_requested: bool, - pub orig_archive_name: Vec, - pub archive_share_requested: Vec, - pub archive_origin: Vec, - pub archive_narrative: Vec, - pub archive_doc_open: bool, - pub alluvial_reads_doc_open: bool, - pub share_start: Option, - pub archive_name_change_button_color: Vec, - pub copy_archive_narrative_button_color: Vec, - pub copy_cookbook_narrative_button_color: Vec, - pub copy_narrative_button_color: Color, - pub cookbook_name: Vec, - pub cookbook_narrative: Vec, - // - // users for sharing - // - pub sharing_enabled: bool, - pub user: Vec, - pub user_value: Vec, - pub user_selected: Vec, - pub user_valid: Vec, - pub do_share: bool, - pub do_share_complete: bool, - pub archive_refresh_button_color: Color, - // - // current window dimensions - // - pub width: u32, - pub height: u32, -} - -impl EncloneVisual { - pub fn hi(&self) -> usize { - self.h.history_index as usize - 1 - } - pub fn state_count(&self) -> usize { - self.h.svg_history.len() - } - pub fn svg_current(&self) -> String { - return self.h.svg_hist_uniq[self.h.svg_history[self.hi()] as usize].clone(); - } - pub fn summary_current(&self) -> String { - return self.h.summary_hist_uniq[self.h.summary_history[self.hi()] as usize].clone(); - } - pub fn input1_current(&self) -> String { - return self.h.input1_hist_uniq[self.h.input1_history[self.hi()] as usize].clone(); - } - pub fn input2_current(&self) -> String { - return self.h.input2_hist_uniq[self.h.input2_history[self.hi()] as usize].clone(); - } - pub fn inputn_current(&self) -> Vec { - return self.h.inputn_hist_uniq[self.h.inputn_history[self.hi()] as usize].clone(); - } - pub fn narrative_current(&self) -> String { - return self.h.narrative_hist_uniq[self.h.narrative_history[self.hi()] as usize].clone(); - } - pub fn translated_input_current(&self) -> String { - return self.h.translated_input_hist_uniq - [self.h.translated_input_history[self.hi()] as usize] - .clone(); - } - pub fn displayed_tables_current(&self) -> String { - return self.h.displayed_tables_hist_uniq - [self.h.displayed_tables_history[self.hi()] as usize] - .clone(); - } - pub fn table_comp_current(&self) -> Vec { - return self.h.table_comp_hist_uniq[self.h.table_comp_history[self.hi()] as usize].clone(); - } - pub fn last_widths_current(&self) -> Vec { - return self.h.last_widths_hist_uniq[self.h.last_widths_history[self.hi()] as usize] - .clone(); - } - pub fn descrip_current(&self) -> String { - return self.h.descrip_hist_uniq[self.h.descrip_history[self.hi()] as usize].clone(); - } - pub fn is_blank_current(&self) -> bool { - return self.h.is_blank[self.hi()]; - } - pub fn sanity_check(&self) { - let n = self.h.svg_history.len(); - assert_eq!(n, self.h.summary_history.len()); - assert_eq!(n, self.h.input1_history.len()); - assert_eq!(n, self.h.input2_history.len()); - assert_eq!(n, self.h.inputn_history.len()); - assert_eq!(n, self.h.narrative_history.len()); - assert_eq!(n, self.h.translated_input_history.len()); - assert_eq!(n, self.h.displayed_tables_history.len()); - assert_eq!(n, self.h.table_comp_history.len()); - assert_eq!(n, self.h.last_widths_history.len()); - assert_eq!(n, self.h.descrip_history.len()); - assert_eq!(n, self.h.is_blank.len()); - } - pub fn update_to_current(&mut self) { - if self.h.history_index == 0 { - self.input1_value.clear(); - self.input2_value.clear(); - self.inputn_value.clear(); - self.svg_value.clear(); - self.png_value.clear(); - self.submit_button_text.clear(); - self.summary_value.clear(); - self.output_value.clear(); - self.table_comp_value.clear(); - self.last_widths_value.clear(); - self.translated_input_value.clear(); - self.current_tables.clear(); - self.descrip_value.clear(); - } else { - let x = self.svg_current(); - self.svg_value = self.svg_current(); - self.post_svg(&x); - self.summary_value = self.summary_current(); - self.output_value = self.displayed_tables_current(); - self.table_comp_value = self.table_comp_current(); - self.last_widths_value = self.last_widths_current(); - self.descrip_value = self.descrip_current(); - self.input1_value = self.input1_current(); - self.input2_value = self.input2_current(); - self.inputn_value = self.inputn_current(); - self.translated_input_value = self.translated_input_current(); - if self.table_comp_value.len() > 0 { - let mut gunzipped = Vec::::new(); - let mut d = GzDecoder::new(&*self.table_comp_value); - d.read_to_end(&mut gunzipped).unwrap(); - self.current_tables = serde_json::from_str(&strme(&gunzipped)).unwrap(); - } else { - self.current_tables.clear(); - } - } - } - pub fn save_as(&mut self, filename: &str, narrative: &str) { - self.h.narrative = narrative.to_string(); - let path = format!("{}/{}", self.archive_dir.as_ref().unwrap(), filename); - let res = write_enclone_visual_history(&self.h, &path); - if res.is_err() { - xprintln!( - "Was unable to write history to the file {}, \ - so Save failed.\n", - path - ); - std::process::exit(1); - } - self.archive_list.insert(0, filename.to_string()); - self.restore_requested.insert(0, false); - self.delete_requested.insert(0, false); - self.deleted.insert(0, false); - self.expand_archive_entry.insert(0, false); - self.restore_msg.insert(0, String::new()); - self.archived_command_list.insert(0, None); - self.archive_name - .insert(0, iced::text_input::State::default()); - self.archive_name_value.insert(0, String::new()); - self.archive_name_change_button_color - .insert(0, Color::from_rgb(0.0, 0.0, 0.0)); - self.copy_archive_narrative_button_color - .insert(0, Color::from_rgb(0.0, 0.0, 0.0)); - self.archive_name_change_button - .insert(0, button::State::default()); - self.archive_narrative_button - .insert(0, button::State::default()); - self.copy_archive_narrative_button - .insert(0, button::State::default()); - self.archive_share_requested.insert(0, false); - self.archive_origin.insert(0, String::new()); - self.archive_narrative.insert(0, narrative.to_string()); - self.orig_archive_name.insert(0, String::new()); - } - pub fn save(&mut self, narrative: &str) { - let mut now = format!("{:?}", Local::now()); - now = now.replace("T", "___"); - now = now.before(".").to_string(); - now = now.replace(":", "-"); - self.save_as(&now, narrative); - } -} diff --git a/enclone_visual/src/help.rs b/enclone_visual/src/help.rs deleted file mode 100644 index f02c02ba30..0000000000 --- a/enclone_visual/src/help.rs +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use crate::*; -use iced::Length::Units; -use iced::{ - Alignment, Button, Column, Container, Element, Image, Length, Row, Rule, Scrollable, Space, - Text, -}; -use messages::Message; - -pub fn help(slf: &mut gui_structures::EncloneVisual) -> Element { - let version = VERSION.lock().unwrap()[0].clone(); - let help_title = Text::new(&format!("Help")).font(LIBERATION_SANS).size(30); - let help_close_button = Button::new( - &mut slf.open_state, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::HelpClose(Ok(()))); - let top_bar = Row::new() - .push(help_title) - .push(Space::with_width(Length::Fill)) - .push(help_close_button); - let max_width = Units((slf.width - 60) as u16); - let max_width2 = Units((slf.width - 250) as u16); - let png_input_region = include_bytes!("../images/input_region.png").to_vec(); - let input_region = - Image::new(iced::image::Handle::from_memory(png_input_region)).width(max_width); - let png_history_region = include_bytes!("../images/history_region.png").to_vec(); - let history_region = - Image::new(iced::image::Handle::from_memory(png_history_region)).height(Units(240)); - let png_right_region = include_bytes!("../images/right_region.png").to_vec(); - let right_region = - Image::new(iced::image::Handle::from_memory(png_right_region)).height(Units(115)); - let png_middle_region = include_bytes!("../images/middle_region.png").to_vec(); - let middle_region = Image::new(iced::image::Handle::from_memory(png_middle_region)) - .height(Units(300)) - .width(Units(290)); - let png_top_region = include_bytes!("../images/top_region.png").to_vec(); - let top_region = Image::new(iced::image::Handle::from_memory(png_top_region)).height(Units(84)); - let help_scrollable = Scrollable::new(&mut slf.scroll) - .width(Length::Fill) - .height(Length::Fill) - .scrollbar_width(SCROLLBAR_WIDTH) - .scroller_width(12) - .style(style::ScrollableStyle) - // - // Intro. - // - .push(Text::new("Introduction").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(20))) - .push( - Text::new(&format!("Welcome to enclone visual version {}!", version,)) - .font(LIBERATION_SANS), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "enclone visual is a semi-graphical \ - version of enclone. You can find out more about enclone at the site", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push(Text::new("bit.ly/enclone.").font(DEJAVU_BOLD)) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "enclone visual simultaneously displays the text and graphical \ - output that enclone can produce.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "This is alpha software: there are many more bugs than there \ - are in enclone.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - // - // Top. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push(Text::new("Top of the page").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(20))) - .push( - Row::new() - .push(top_region) - .push(Space::with_width(Units(15))) - .push( - Column::new() - .push( - Text::new( - "Here are two buttons that appear in the upper left \ - corner of the screen:", - ) - .font(LIBERATION_SANS), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "1. Exit, to leave enclone visual. Note that the \ - circular red button in the extreme upper left corner is busted.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Text::new("2. Help, to get to this page.").font(LIBERATION_SANS)), - ), - ) - .push(Space::with_height(Units(20))) - .push( - Row::new() - .align_items(Alignment::Center) - .push( - Column::new() - .push(Space::with_height(Units(10))) - .push( - Text::new( - "Here are six buttons that appear in the upper right \ - corner of the screen:", - ) - .font(LIBERATION_SANS), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "1. Snapshot, to copy a screenshot of the entire window \ - to the clipboard. This button is only present on Macs.", - ) - .font(LIBERATION_SANS) - .width(max_width2), - ) - .push( - Text::new( - "2. Console, to show what's in the terminal window. \ - At the moment this is mostly of interest to developers.", - ) - .font(LIBERATION_SANS) - .width(max_width2), - ) - .push( - Text::new("3. Save, to cause the session to be saved.") - .font(LIBERATION_SANS) - .width(max_width2), - ) - .push( - Text::new( - "4. On Exit, to cause the session to be saved \ - when the Exit button is pushed.", - ) - .font(LIBERATION_SANS) - .width(max_width2), - ) - .push( - Text::new( - "5. Tooltip, to toggle the position of the tooltip text window. \ - Clicking causes clockwise rotation of the position amongst the \ - four corners of the graphics window. One position may yield a \ - better overall view than another. If you click, you'll see the \ - button flash, but no other change, until you mouse over a cell.", - ) - .font(LIBERATION_SANS) - .width(max_width2), - ) - .push( - Text::new( - "6. Archive. Opens a page to allow restoration or sharing of a \ - previous session.", - ) - .font(LIBERATION_SANS) - .width(max_width2), - ) - .push(Space::with_height(Units(10))) - .push( - Text::new( - "More information about saving and restoring session may be \ - obtained by \ - pushing the Archive button on the main page. The archive page \ - also provides access to cookbooks, which you should work through!", - ) - .font(LIBERATION_SANS) - .width(max_width2), - ), - ) - .push(Space::with_width(Length::Fill)) - .push(right_region) - .push(Space::with_width(Units(20))), - ) - // - // Layout. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push(Text::new("Overall layout").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(20))) - .push( - Text::new("There are input boxes near the top (described next).") - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Once you've typed your first command, the screen will \ - split into two main parts:", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new("1. A graphics subwindow, which may or may not be populated.") - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "2. A text subwindow, which typically has clonotypes in it. \ - To make scrolling manageable, only the first fifty clonotypes are displayed. \ - Please see the special commands section for how to see a different set of \ - clonotypes.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - // - // Input. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push(Text::new("Entering input").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(20))) - .push(input_region) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Above, you can see two boxes. You can type a command into \ - these. The reason for having two boxes is that it allows for longer \ - commands: you can split a command between the two boxes. Pushing the Cmd button \ - (see below) will provide even more boxes.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Except for special cases (see below), every command begins with \ - the word enclone. You can see examples \ - in the cookbooks on the Archive page. You can learn about \ - enclone commands in general by going to the site bit.ly/enclone.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new("Once you've entered your command, push the Submit button.").width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Then wait for the command to finish! Some buttons are disabled during \ - this period.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - // - // Special commands. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push(Text::new("Special commands").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "You can type a number into the text box, where the number \ - is the number of a clonotype group. Things like this", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(10))) - .push(Text::new("1,7,10-15").font(DEJAVU_BOLD).size(20)) - .push(Space::with_height(Units(10))) - .push(Text::new("also work.").font(LIBERATION_SANS)) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "If you've displayed a honeycomb plot (see cookbooks for examples), \ - then positioning your mouse over a cell will cause a \"tooltip\" box to appear that \ - provides some information about that cell. See also the Tooltip button, that \ - controls the position of this box.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Clicking on a cell is the same as typing its number into \ - the input box, thus displaying the corresponding clonotype table. In addition, \ - clicking on a cell will copy the tooltip text to your clipboard.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new("Group ids are converted into a special enclone argument") - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(10))) - .push(Text::new("G=...").font(DEJAVU_BOLD).size(20)) - .push(Space::with_height(Units(10))) - .push( - Text::new("that can also be supplied to enclone. In addition, G=all works.") - .font(LIBERATION_SANS) - .width(max_width), - ) - // - // History. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push( - Text::new("History, AKA the time machine") - .font(LIBERATION_SANS) - .size(24), - ) - .push(Space::with_height(Units(15))) - .push( - Row::new() - .push( - Column::new() - .push(Space::with_height(Units(5))) - .push( - Text::new( - "enclone visual remembers your previous commands and \ - their outputs.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 120) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "On the right, you can see boxes, that will appear on \ - the right of your screen once you've entered your first command.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 120) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Initially, some of the boxes will be blank, meaning \ - that they don't make sense yet and won't do anything.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 120) as u16)), - ) - .push(Space::with_height(Units(20))) - .push(Text::new("There are four boxes:").font(LIBERATION_SANS)) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "• The number at the top is the index of the current \ - state. This is not a button that can be pushed.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 120) as u16)), - ) - .push( - Text::new( - "• Push the up arrow to go back to the previous state, \ - meaning the last command that you typed.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 120) as u16)), - ) - .push( - Text::new("• Push the down arrow to go forward to the next state.") - .font(LIBERATION_SANS) - .width(Units((slf.width - 120) as u16)), - ) - .push( - Text::new( - "• Push the Del button to delete the current state, and go \ - backward, if that makes sense.", - ) - .font(LIBERATION_SANS), - ) - .width(Units((slf.width - 120) as u16)), - ) - .push(Space::with_height(Units(20))) - .push(history_region), - ) - // - // The middle boxes. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push(Text::new("The middle boxes").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(15))) - .push( - Row::new() - .push( - Column::new() - .push(Space::with_height(Units(5))) - .push( - Text::new( - "Just to the left of the history boxes are more, \ - samples of which you can see on the right.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 350) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "The top box is the translated command. It is the same \ - as the command you typed, unless you used a special command.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 350) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Below it there is a button to copy the graphics image to \ - your clipboard, assuming that you have a graphics image. The default width \ - of the image is 2000 pixels. To obtain lower or higher resolution, copy a \ - number between 1000 and 4000 onto your clipboard, before pushing Copy image. \ - Then that number will be used as the width. Note also that direct image copy \ - from the screen can be a good alternative.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 350) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Next to it is a button to copy the command to your \ - clipboard. This copied command can be reentered in enclone visual, \ - or supplied to \"regular\" enclone, so long as you change instances of gui \ - to actual file names. You also need to add double quotes \ - around arguments containing certain characters including < and >.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 350) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Below that is a button to open a window displaying just the \ - graphic, and one for just the clonotypes, \ - a button to display the summary stats for your enclone command, \ - and a button for entering long commands. Each of these four \ - buttons opens a separate page.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 350) as u16)), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "Finally near the bottom is the narrative box. This is text for \ - a given state that you can set by first copying text to your clipboard \ - (outside enclone visual), and then clicking on the narrative box to copy \ - the text into it. Conversely, there is a Copy button below the narrative box \ - that will copy the narrative text onto your clipboard.", - ) - .font(LIBERATION_SANS) - .width(Units((slf.width - 350) as u16)), - ), - ) - .push(Space::with_height(Units(20))) - .push(middle_region), - ) - // - // Smarts. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push(Text::new("Smarts").font(LIBERATION_SANS).size(24)) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "If you run a command, and then run a similar command after it, \ - enclone visual may elide some calculations from the previous command, so as \ - to respond faster. This capability is not pushed as far as it could be.", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - // - // Limitations. - // - .push(Space::with_height(Units(20))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(20))) - .push( - Text::new("Limitations, AKA big bugs") - .font(LIBERATION_SANS) - .size(24), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new( - "There are two main limitations of the current version of enclone \ - visual:", - ) - .font(LIBERATION_SANS) - .width(max_width), - ) - .push(Space::with_height(Units(20))) - .push( - Text::new("1. The clonotype tables are black and white.") - .font(LIBERATION_SANS) - .width(max_width), - ) - .push( - Text::new("2. You can't use the mouse to copy text, except from text input boxes.") - .font(LIBERATION_SANS) - .width(max_width), - ) - // - // Bottom. - // - .push(Space::with_height(Units(20))); - - let content = Column::new() - .spacing(SPACING) - .padding(20) - .push(top_bar) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(help_scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} diff --git a/enclone_visual/src/history.rs b/enclone_visual/src/history.rs deleted file mode 100644 index d3148a51ca..0000000000 --- a/enclone_visual/src/history.rs +++ /dev/null @@ -1,508 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Storage of enclone visual history, and functions to save and restore. - -use crate::EXTRA_INPUTS; -use enclone_core::packing::*; -use io_utils::*; -use std::fs::{File, OpenOptions}; -use std::io::{Error, ErrorKind, Read, Seek, SeekFrom, Write}; -use string_utils::*; - -#[derive(Default, PartialEq, Clone)] -pub struct EncloneVisualHistory { - // - // more or less uniqued history: - // - pub svg_hist_uniq: Vec, // each entry is an SVG - pub summary_hist_uniq: Vec, // each entry is a summary - pub input1_hist_uniq: Vec, // each entry is the originating command 1 - pub input2_hist_uniq: Vec, // each entry is the originating command 2 - pub inputn_hist_uniq: Vec>, // each entry is the originating command n - pub narrative_hist_uniq: Vec, // each entry is the narrative - pub translated_input_hist_uniq: Vec, // each entry is the translated originating command - pub displayed_tables_hist_uniq: Vec, // each entry is the tables that are displayed - pub table_comp_hist_uniq: Vec>, // each entry is the compressed list of all tables - pub last_widths_hist_uniq: Vec>, - pub descrip_hist_uniq: Vec, // descriptions (not used yet) - // - // parallel vectors, with one entry for each command entered in the text box: - // - pub svg_history: Vec, // each entry is an SVG - pub summary_history: Vec, // each entry is a summary - pub input1_history: Vec, // each entry is the originating command 1 - pub input2_history: Vec, // each entry is the originating command 2 - pub inputn_history: Vec, // each entry is the originating command n - pub narrative_history: Vec, // each entry is the narrative - pub translated_input_history: Vec, // each entry is the translated originating command - pub displayed_tables_history: Vec, // each entry is the tables that are displayed - pub table_comp_history: Vec, // each entry is the compressed list of all tables - pub last_widths_history: Vec, // last widths for clonotype pictures - pub is_blank: Vec, // set if the SVG is empty - pub descrip_history: Vec, // each entry is the description (not used yet) - // - // index of "current" position in those vectors, plus one: - // - pub history_index: u32, // this is saved but we ignore it, which seems better - // - // name of this session and narrative - // - pub name_value: String, - pub orig_name_value: String, - pub narrative: String, // not used yet - // - // origin of this session (if shared) - // - pub origin: String, -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// clean: remove unused elements of hist_uniq vectors - -pub fn clean_history(hist_uniq: &mut Vec, history: &mut Vec) { - let mut used = vec![false; hist_uniq.len()]; - for i in 0..history.len() { - used[history[i] as usize] = true; - } - let mut to_new = vec![0; hist_uniq.len()]; - let mut j = 0; - for i in 0..hist_uniq.len() { - if used[i] { - if i != j { - hist_uniq[j] = hist_uniq[i].clone(); - } - to_new[i] = j; - j += 1; - } - } - hist_uniq.truncate(j); - for i in 0..history.len() { - history[i] = to_new[history[i] as usize] as u32; - } -} - -impl EncloneVisualHistory { - pub fn clean_history(&mut self) { - clean_history(&mut self.svg_hist_uniq, &mut self.svg_history); - clean_history(&mut self.summary_hist_uniq, &mut self.summary_history); - clean_history(&mut self.input1_hist_uniq, &mut self.input1_history); - clean_history(&mut self.input2_hist_uniq, &mut self.input2_history); - clean_history(&mut self.inputn_hist_uniq, &mut self.inputn_history); - clean_history(&mut self.narrative_hist_uniq, &mut self.narrative_history); - clean_history( - &mut self.translated_input_hist_uniq, - &mut self.translated_input_history, - ); - clean_history( - &mut self.displayed_tables_hist_uniq, - &mut self.displayed_tables_history, - ); - clean_history(&mut self.table_comp_hist_uniq, &mut self.table_comp_history); - clean_history( - &mut self.last_widths_hist_uniq, - &mut self.last_widths_history, - ); - clean_history(&mut self.descrip_hist_uniq, &mut self.descrip_history); - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -const ENCLONE_VISUAL_HISTORY_VERSION: usize = 2; -const HEADER_LENGTH: usize = 40; -const NAME_BYTES: usize = 160; - -impl EncloneVisualHistory { - // - // requirements for saving and restoring history - // - // 1. File structure must not change, except when we explicitly change it. - // 2. Must be able to read old files. - // 3. Must be versioned. - // 4. Must have text header. - // 5. Must store reasonably efficiently. - // 6. Must be able to extract command list and name without reading entire file. - // 7. Name can be changed without rewriting entire file. - // 8. File structure must be guaranteed the same across environments (so, e.g., no usize). - // - // structure description - // - // 1. text header = 40 bytes = "enclone visual history file version ***\n", - // where *** is a positive integer, padded on the right with blanks - // 2. total bytes in file (u32) - // 3. total bytes in narrative (u32) - // 4. total bytes up through translated_hist_uniq (u32) - // 5. data for each of the fields in EncloneVisualHistory, with translated_input_history and - // translated_input_hist_uniq stored first, and narrative stored last (as raw bytes). - - pub fn save_as_bytes(&self) -> Vec { - let mut bytes = format!( - "enclone visual history file version{:<4}\n", - ENCLONE_VISUAL_HISTORY_VERSION - ) - .as_bytes() - .to_vec(); - bytes.append(&mut vec![0 as u8; 12]); - let mut name_bytes = vec![0 as u8; NAME_BYTES]; - for i in 0..std::cmp::min(NAME_BYTES, self.name_value.as_bytes().len()) { - name_bytes[i] = self.name_value.as_bytes()[i]; - } - bytes.append(&mut name_bytes); - bytes.append(&mut save_vec_u32(&self.translated_input_history)); - bytes.append(&mut save_vec_string(&self.translated_input_hist_uniq)); - bytes.append(&mut save_string(&self.origin)); - let b = u32_bytes(bytes.len()); - for i in 0..4 { - bytes[HEADER_LENGTH + 4 + i] = b[i]; - } - bytes.append(&mut save_vec_string_comp(&self.svg_hist_uniq)); - bytes.append(&mut save_vec_string(&self.summary_hist_uniq)); - bytes.append(&mut save_vec_string(&self.input1_hist_uniq)); - bytes.append(&mut save_vec_string(&self.input2_hist_uniq)); - if ENCLONE_VISUAL_HISTORY_VERSION >= 2 { - bytes.append(&mut save_vec_vec_string(&self.inputn_hist_uniq)); - } - bytes.append(&mut save_vec_string(&self.narrative_hist_uniq)); - bytes.append(&mut save_vec_string_comp(&self.displayed_tables_hist_uniq)); - bytes.append(&mut save_vec_vec_u8(&self.table_comp_hist_uniq)); - bytes.append(&mut save_vec_vec_u32(&self.last_widths_hist_uniq)); - bytes.append(&mut save_vec_string(&self.descrip_hist_uniq)); - bytes.append(&mut save_vec_u32(&self.svg_history)); - bytes.append(&mut save_vec_u32(&self.summary_history)); - bytes.append(&mut save_vec_u32(&self.input1_history)); - bytes.append(&mut save_vec_u32(&self.input2_history)); - if ENCLONE_VISUAL_HISTORY_VERSION >= 2 { - bytes.append(&mut save_vec_u32(&self.inputn_history)); - } - bytes.append(&mut save_vec_u32(&self.narrative_history)); - bytes.append(&mut save_vec_u32(&self.displayed_tables_history)); - bytes.append(&mut save_vec_u32(&self.table_comp_history)); - bytes.append(&mut save_vec_u32(&self.last_widths_history)); - bytes.append(&mut save_vec_bool(&self.is_blank)); - bytes.append(&mut save_vec_u32(&self.descrip_history)); - bytes.extend(save_u32(self.history_index)); - bytes.append(&mut self.narrative.as_bytes().to_vec()); - let b = u32_bytes(bytes.len()); - for i in 0..4 { - bytes[HEADER_LENGTH + i] = b[i]; - } - let b = u32_bytes(self.narrative.len()); - for i in 0..4 { - bytes[HEADER_LENGTH + 8 + i] = b[i]; - } - bytes - } - - pub fn restore_from_bytes(bytes: &Vec) -> Result { - if bytes.len() < HEADER_LENGTH + 12 { - return Err(()); - } - let expected_header = b"enclone visual history file version".to_vec(); - if bytes[0..HEADER_LENGTH - 5].to_vec() != expected_header { - return Err(()); - } - let mut version_string = stringme(&bytes[HEADER_LENGTH - 5..HEADER_LENGTH - 1]); - while version_string.ends_with(' ') { - version_string = version_string.rev_before(" ").to_string(); - } - if !version_string.parse::().is_ok() { - return Err(()); - } - let version = version_string.force_usize(); - let narrative_len = u32_from_bytes(&bytes[HEADER_LENGTH + 8..HEADER_LENGTH + 12]) as usize; - let mut pos = HEADER_LENGTH + 12; - let mut name_value_bytes = Vec::::new(); - for i in 0..NAME_BYTES { - if bytes[pos + i] == 0 { - break; - } - name_value_bytes.push(bytes[pos + i]); - } - let res = String::from_utf8(name_value_bytes); - if res.is_err() { - return Err(()); - } - let name_value = res.unwrap(); - pos += NAME_BYTES; - let translated_input_history = restore_vec_u32(&bytes, &mut pos)?; - let translated_input_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let origin = restore_string(&bytes, &mut pos)?; - let svg_hist_uniq = restore_vec_string_comp(&bytes, &mut pos)?; - let summary_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let input1_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let input2_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let inputn_hist_uniq; - if version >= 2 { - inputn_hist_uniq = restore_vec_vec_string(&bytes, &mut pos)?; - } else { - let null_hist = vec![String::new(); EXTRA_INPUTS]; - inputn_hist_uniq = vec![null_hist]; - } - let narrative_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let displayed_tables_hist_uniq = restore_vec_string_comp(&bytes, &mut pos)?; - let table_comp_hist_uniq = restore_vec_vec_u8(&bytes, &mut pos)?; - let last_widths_hist_uniq = restore_vec_vec_u32(&bytes, &mut pos)?; - let descrip_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let svg_history = restore_vec_u32(&bytes, &mut pos)?; - let summary_history = restore_vec_u32(&bytes, &mut pos)?; - let input1_history = restore_vec_u32(&bytes, &mut pos)?; - let input2_history = restore_vec_u32(&bytes, &mut pos)?; - let inputn_history; - if version >= 2 { - inputn_history = restore_vec_u32(&bytes, &mut pos)?; - } else { - inputn_history = vec![0; input2_history.len()]; - } - let narrative_history = restore_vec_u32(&bytes, &mut pos)?; - let displayed_tables_history = restore_vec_u32(&bytes, &mut pos)?; - let table_comp_history = restore_vec_u32(&bytes, &mut pos)?; - let last_widths_history = restore_vec_u32(&bytes, &mut pos)?; - let is_blank = restore_vec_bool(&bytes, &mut pos)?; - let descrip_history = restore_vec_u32(&bytes, &mut pos)?; - let history_index = restore_u32(&bytes, &mut pos)?; - if pos + narrative_len != bytes.len() { - return Err(()); - } - let narrative = String::from_utf8(bytes[pos..].to_vec()); - if narrative.is_err() { - return Err(()); - } - Ok(EncloneVisualHistory { - translated_input_history: translated_input_history, - translated_input_hist_uniq: translated_input_hist_uniq, - svg_hist_uniq: svg_hist_uniq, - summary_hist_uniq: summary_hist_uniq, - input1_hist_uniq: input1_hist_uniq, - input2_hist_uniq: input2_hist_uniq, - inputn_hist_uniq: inputn_hist_uniq, - narrative_hist_uniq: narrative_hist_uniq, - displayed_tables_hist_uniq: displayed_tables_hist_uniq, - table_comp_hist_uniq: table_comp_hist_uniq, - last_widths_hist_uniq: last_widths_hist_uniq, - descrip_hist_uniq: descrip_hist_uniq, - svg_history: svg_history, - summary_history: summary_history, - input1_history: input1_history, - input2_history: input2_history, - inputn_history: inputn_history, - narrative_history: narrative_history, - displayed_tables_history: displayed_tables_history, - table_comp_history: table_comp_history, - last_widths_history: last_widths_history, - is_blank: is_blank, - descrip_history: descrip_history, - history_index: history_index, - name_value: name_value.clone(), - orig_name_value: name_value, - origin: origin, - narrative: narrative.unwrap(), - }) - } -} - -pub fn rewrite_name(filename: &str, name: &str) -> Result<(), std::io::Error> { - let mut f = OpenOptions::new().write(true).read(true).open(&filename)?; - f.seek(SeekFrom::Start((HEADER_LENGTH + 12) as u64))?; - let mut name_bytes = vec![0 as u8; NAME_BYTES]; - for i in 0..std::cmp::min(NAME_BYTES, name.as_bytes().len()) { - name_bytes[i] = name.as_bytes()[i]; - } - f.write_all(&name_bytes)?; - Ok(()) -} - -pub fn rewrite_narrative(filename: &str, narrative: &str) -> Result<(), std::io::Error> { - let mut f = OpenOptions::new().write(true).read(true).open(&filename)?; - let mut buf = vec![0 as u8; HEADER_LENGTH + 12]; - let res = f.read_exact(&mut buf); - if res.is_err() { - return Err(Error::new(ErrorKind::Other, "file appears truncated")); - } - let total = u32_from_bytes(&buf[HEADER_LENGTH..HEADER_LENGTH + 4]) as usize; - let narrative_length = u32_from_bytes(&buf[HEADER_LENGTH + 8..HEADER_LENGTH + 12]) as usize; - if narrative_length > total { - return Err(Error::new( - ErrorKind::Other, - "narrative length exceeds total length", - )); - } - let total_less_narrative = (total - narrative_length) as u64; - f.seek(SeekFrom::Start(total_less_narrative))?; - write!(f, "{}", narrative)?; - let new_total = total + narrative.len() - narrative_length; - if new_total < total { - f.set_len(new_total as u64)?; - } - let new_narrative_length = narrative.len(); - f.seek(SeekFrom::Start(0))?; - let x = u32_bytes(new_total); - for i in 0..4 { - buf[HEADER_LENGTH + i] = x[i]; - } - let x = u32_bytes(new_narrative_length); - for i in 0..4 { - buf[HEADER_LENGTH + 8 + i] = x[i]; - } - f.write_all(&buf)?; - Ok(()) -} - -pub fn read_metadata(filename: &str) -> Result<(Vec, String, String, String), ()> { - let total; - let n; - let narrative_length; - let narrative; - { - let mut f = open_for_read![&filename]; - let mut buf = vec![0 as u8; HEADER_LENGTH + 12]; - let res = f.read_exact(&mut buf); - if res.is_err() { - return Err(()); - } - total = u32_from_bytes(&buf[HEADER_LENGTH..HEADER_LENGTH + 4]) as usize; - n = u32_from_bytes(&buf[HEADER_LENGTH + 4..HEADER_LENGTH + 8]) as usize; - narrative_length = u32_from_bytes(&buf[HEADER_LENGTH + 8..HEADER_LENGTH + 12]) as usize; - if narrative_length > total { - return Err(()); - } - let total_less_narrative = (total - narrative_length) as u64; - let res = f.seek(SeekFrom::Start(total_less_narrative)); - if res.is_err() { - return Err(()); - } - let mut buf = vec![0 as u8; narrative_length]; - let res = f.read_exact(&mut buf); - if res.is_err() { - return Err(()); - } - let s = String::from_utf8(buf); - if s.is_err() { - return Err(()); - } - narrative = s.unwrap(); - } - let mut bytes = vec![0 as u8; n]; - let mut f = open_for_read![&filename]; - let res = f.read_exact(&mut bytes); - if res.is_err() { - return Err(()); - } - let mut pos = HEADER_LENGTH + 12; - let mut name_value_bytes = Vec::::new(); - for i in 0..NAME_BYTES { - if bytes[pos + i] == 0 { - break; - } - name_value_bytes.push(bytes[pos + i]); - } - let name = String::from_utf8(name_value_bytes); - if name.is_err() { - return Err(()); - } - let name = name.unwrap(); - pos += NAME_BYTES; - let translated_input_history = restore_vec_u32(&bytes, &mut pos)?; - let translated_input_hist_uniq = restore_vec_string(&bytes, &mut pos)?; - let mut commands = Vec::::new(); - for i in translated_input_history.iter() { - let i = *i as usize; - if i >= translated_input_hist_uniq.len() { - return Err(()); - } - commands.push(translated_input_hist_uniq[i].clone()); - } - let origin = restore_string(&bytes, &mut pos)?; - Ok((commands, name, origin, narrative)) -} - -pub fn read_enclone_visual_history(filename: &str) -> Result { - let n; - { - let mut f = open_for_read![&filename]; - let mut buf = vec![0 as u8; HEADER_LENGTH + 4]; - let res = f.read_exact(&mut buf); - if res.is_err() { - return Err(()); - } - n = u32_from_bytes(&buf[HEADER_LENGTH..HEADER_LENGTH + 4]); - } - let mut bytes = vec![0 as u8; n as usize]; - let mut f = open_for_read![&filename]; - let res = f.read_exact(&mut bytes); - if res.is_err() { - return Err(()); - } - EncloneVisualHistory::restore_from_bytes(&bytes) -} - -pub fn write_enclone_visual_history(evh: &EncloneVisualHistory, filename: &str) -> Result<(), ()> { - let mut evh = evh.clone(); - evh.clean_history(); - let f = File::create(&filename); - if f.is_err() { - return Err(()); - } - let bytes = evh.save_as_bytes(); - let res = f.unwrap().write_all(&bytes); - if res.is_err() { - return Err(()); - } - Ok(()) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Testing functions. - -impl EncloneVisualHistory { - pub fn save_restore_works(&self) -> bool { - let bytes = self.save_as_bytes(); - let new = EncloneVisualHistory::restore_from_bytes(&bytes); - if new.is_err() { - return false; - } - *self == new.unwrap() - } -} - -pub fn test_evh_read_write(evh: &EncloneVisualHistory, filename: &str) { - write_enclone_visual_history(&evh, &filename).unwrap(); - let mut evh = evh.clone(); - evh.clean_history(); - let evh2 = read_enclone_visual_history(&filename).unwrap(); - if evh != evh2 { - eprintln!(""); - if evh.svg_hist_uniq != evh2.svg_hist_uniq { - eprintln!("svg_hist_uniq changed"); - if evh.svg_hist_uniq.len() != evh2.svg_hist_uniq.len() { - eprintln!( - "length changed from {} to {}", - evh.svg_hist_uniq.len(), - evh2.svg_hist_uniq.len() - ); - } - } - if evh.history_index != evh2.history_index { - eprintln!("history index changed"); - } - if evh.orig_name_value != evh2.orig_name_value { - eprintln!("orig name changed"); - } - if evh.name_value != evh2.name_value { - eprintln!("name changed"); - } - if evh.narrative != evh2.narrative { - eprintln!("narrative changed"); - } - if evh.origin != evh2.origin { - eprintln!("origin changed"); - } - panic!("evh != evh2 for {}", filename); - } - for name in ["gerbilspit the great".to_string(), "shorter".to_string()].iter() { - rewrite_name(&filename, &*name).unwrap(); - let evh2 = read_enclone_visual_history(&filename).unwrap(); - assert_eq!(evh2.name_value, *name); - } -} diff --git a/enclone_visual/src/lib.rs b/enclone_visual/src/lib.rs deleted file mode 100644 index 484741040a..0000000000 --- a/enclone_visual/src/lib.rs +++ /dev/null @@ -1,742 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use crate::copy_image_to_clipboard::*; -use crate::dimensions::*; -use crate::gui_structures::EncloneVisual; -#[cfg(not(target_os = "windows"))] -use anyhow::Error; -use enclone_tail::convert_svg_to_png::*; -use iced::{Application, Font, Settings}; -use itertools::Itertools; -use lazy_static::lazy_static; -#[cfg(not(target_os = "windows"))] -use libc::SIGINT; -#[cfg(not(target_os = "windows"))] -use nix::sys::signal::{kill, Signal, SIGINT as SIGINT_nix}; -#[cfg(not(target_os = "windows"))] -use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet}; -#[cfg(not(target_os = "windows"))] -use nix::unistd::Pid; -use perf_stats::*; -use std::collections::HashMap; -#[cfg(not(target_os = "windows"))] -use std::convert::TryInto; -use std::fs::{remove_file, File}; -use std::io::Read; -#[cfg(not(target_os = "windows"))] -use std::process::{Command, Stdio}; -use std::sync::atomic::Ordering::SeqCst; -use std::sync::atomic::{AtomicBool, AtomicUsize}; -use std::sync::Mutex; -use std::thread; -use std::time::{Duration, Instant}; -use string_utils::*; -use svg_to_geometry::*; -use tables::*; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use core_foundation::number::CFNumber; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use core_foundation::string::CFString; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use core_graphics::window::{create_description_from_array, create_window_list}; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use std::ops::Deref; - -#[cfg(any(target_os = "macos", target_os = "ios"))] -use clipboard::{ClipboardContext, ClipboardProvider}; - -#[cfg(any(target_os = "linux", target_os = "windows"))] -use arboard::Clipboard; - -pub mod apocalypse; -pub mod archive; -pub mod canvas_view; -pub mod client_requests; -pub mod compare_images; -pub mod copy_image_to_clipboard; -pub mod dimensions; -pub mod enclone_client; -pub mod enclone_server; -pub mod geometry; -pub mod gui; -pub mod gui_structures; -pub mod help; -pub mod history; -pub mod messages; -pub mod popover; -pub mod proc1; -pub mod proc2; -pub mod process_messages; -pub mod share; -pub mod snapshot; -pub mod style; -pub mod summary; -pub mod svg_to_geometry; -pub mod testsuite; -pub mod update_restart; - -const LIBERATION_SANS: Font = Font::External { - name: "LIBERATION_SANS", - bytes: include_bytes!("../../fonts/LiberationSans-Regular.ttf"), -}; - -const DEJAVU_WIDTH_OVER_HEIGHT: f32 = 0.5175; // there's another different value at one point - -pub fn dejavu_text_dim(t: &str, font_size: f32) -> (f32, f32) { - let mut width_in_chars = 0; - let mut height_in_chars = 0; - for line in t.lines() { - let mut nchars = 0; - for _char in line.chars() { - nchars += 1; - } - width_in_chars = std::cmp::max(width_in_chars, nchars); - height_in_chars += 1; - } - let box_width = width_in_chars as f32 * font_size * DEJAVU_WIDTH_OVER_HEIGHT; - let box_height = height_in_chars as f32 * font_size; - (box_width, box_height) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Fold strings to put them in boxes. This is more delicate than it might appear. - -pub fn fold(all: &str, max_line: usize) -> Vec { - let mut pieces = Vec::::new(); - let lines = all.split('\n').collect::>(); - for line in lines.iter() { - if line.len() == 0 { - pieces.push(String::new()); - } else { - let words = line.split(' ').collect::>(); - let mut current = String::new(); - let mut i = 0; - while i < words.len() { - if current.len() > 0 - && current.chars().count() + 1 + words[i].chars().count() > max_line - { - pieces.push(current.clone()); - current.clear(); - i -= 1; - } else if words[i].chars().count() >= max_line { - let mut w = words[i].to_string(); - loop { - let n = std::cmp::min(max_line, w.chars().count()); - let sub = w[0..n].to_string(); - if n < w.chars().count() { - pieces.push(sub); - w = w[n..w.len()].to_string(); - } else { - current = w.clone(); - break; - } - } - } else if current.len() == 0 && words[i].len() > 0 { - current += &mut words[i].clone(); - } else { - current += &mut format!(" {}", words[i]); - } - i += 1; - } - if current.starts_with(" ") { - current = current.after(" ").to_string(); - } - if current.len() > 0 { - pieces.push(current); - } - } - } - pieces -} - -pub fn test_fold() { - let input1 = r###"This and next state allows one to deduce: - -whatever - - positive negative -xx yyyyyy zzzzzzzzzzzzzzz ....................................................... - -Those four gerbils acids stand out. But of course just traversing columns and looking for differences is going to miss a lot. Also note that the controls typically have very little wobble, forcing no change for the first three whatevers."###; - - let output1 = r###"This and next state allows one to deduce: - -whatever - - positive negative -xx yyyyyy zzzzzzzzzzzzzzz ....................................................... - -Those four gerbils acids stand out. But of course just traversing columns and looking for -differences is going to miss a lot. Also note that the controls typically have very little wobble, -forcing no change for the first three whatevers."###; - - let folded1 = fold(&input1, 100); - let out1 = format!("{}", folded1.iter().format("\n")); - assert_eq!(&out1, &output1); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -const EXTRA_INPUTS: usize = 8; - -pub fn compressed_message_history() -> Vec { - let mut messages = Vec::::new(); - let n = MESSAGE_HISTORY.lock().unwrap().len(); - for i in 0..n { - messages.push(MESSAGE_HISTORY.lock().unwrap()[i].clone()); - } - let mut messages2 = Vec::::new(); - for i in 0..messages.len() { - if i == messages.len() - 1 - || !messages[i].starts_with("InputChanged1(") - || !messages[i + 1].starts_with("InputChanged1(") - { - messages2.push(messages[i].clone()); - } - } - messages = messages2; - let mut messages2 = Vec::::new(); - for i in 0..messages.len() { - if i == messages.len() - 1 - || !messages[i].starts_with("ArchiveName(") - || !messages[i + 1].starts_with("ArchiveName(") - { - messages2.push(messages[i].clone()); - } - } - messages2 -} - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn get_clipboard_content() -> Option { - let ctx: Result = ClipboardProvider::new(); - if ctx.is_err() { - xprintln!("\nSomething went wrong accessing clipboard."); - xprintln!("This is weird so please ask for help."); - std::process::exit(1); - } - let mut ctx = ctx.unwrap(); - let copy = ctx.get_contents(); - if copy.is_err() { - None - } else { - Some(format!("{}", ctx.get_contents().unwrap())) - } -} - -#[cfg(any(target_os = "linux", target_os = "windows"))] -pub fn get_clipboard_content() -> Option { - let clipboard = Clipboard::new(); - if clipboard.is_err() { - xprintln!("\nSomething went wrong accessing clipboard."); - xprintln!("This is weird so please ask for help."); - std::process::exit(1); - } - Some(clipboard.unwrap().get_text().unwrap()) -} - -pub fn prepend_to_vec(x: &mut Vec, y: &Vec) { - let mut x_copy = x.clone(); - *x = y.to_vec(); - x.append(&mut x_copy); -} - -const SPACING: u16 = 20; -const SCROLLBAR_WIDTH: u16 = 12; - -// is_user_name_valid: we don't know how to test this for Windows, so we always return true - -#[cfg(not(target_os = "windows"))] -pub fn is_user_name_valid(name: &str) -> bool { - users::get_user_by_name(&name).is_some() -} - -#[cfg(target_os = "windows")] -pub fn is_user_name_valid(_name: &str) -> bool { - true -} - -#[derive(Clone)] -pub struct Share { - pub days_since_ce: i32, - pub user_id: [u8; 32], -} - -type MsgFn = fn(Result<(), String>) -> messages::Message; - -async fn noop() -> Result<(), String> { - // Increasing this time to 2000ms will prevent the screen from going dark on initialization - // in test mode. - thread::sleep(Duration::from_millis(100)); - Ok(()) -} - -async fn noop0() -> Result<(), String> { - Ok(()) -} - -async fn noop1() -> Result<(), String> { - // Do not change this sleep amount. It is the length of time that a button flashes red. - // If a different amount is needed, create a different function. - thread::sleep(Duration::from_millis(400)); - Ok(()) -} - -async fn compute() -> Result<(), String> { - let t = Instant::now(); - while PROCESSING_REQUEST.load(SeqCst) { - thread::sleep(Duration::from_millis(10)); - } - xprintln!("time used processing command = {:.1} seconds", elapsed(&t)); - Ok(()) -} - -async fn compute_share() -> Result<(), String> { - while SENDING_SHARE.load(SeqCst) { - thread::sleep(Duration::from_millis(10)); - } - Ok(()) -} - -async fn flash_copy_image_button() -> Result<(), String> { - Ok(()) -} - -const DEJAVU: Font = Font::External { - name: "DEJAVU", - bytes: include_bytes!("../../fonts/DejaVuLGCSansMono.ttf"), -}; - -const DEJAVU_BOLD: Font = Font::External { - name: "DEJAVU_BOLD", - bytes: include_bytes!("../../fonts/DejaVuLGCSansMono-Bold.ttf"), -}; - -impl EncloneVisual { - pub fn post_svg(&mut self, svg: &str) { - self.png_value.clear(); - let geometry = svg_to_geometry(&svg, false); - let mut using_geometry = false; - if geometry.is_some() { - let mut ok = true; - for i in 0..geometry.as_ref().unwrap().len() { - match &geometry.as_ref().unwrap()[i] { - crate::geometry::Geometry::Text(ttt) => { - if ttt.rotate != [0.0; 3] { - ok = false; - } - } - _ => {} - } - } - if ok { - using_geometry = true; - self.canvas_view.state.geometry_value = geometry; - } - } else if VERBOSE.load(SeqCst) { - xprintln!("translation from svg to geometries failed"); - } - if !using_geometry { - self.canvas_view.state.geometry_value = None; - self.png_value = convert_svg_to_png(&svg.as_bytes(), 2000); - } - } -} - -pub fn blank_svg() -> String { - let s = r###" - - -"### - .to_string(); - s.replace("400", &format!("{}", SVG_NULL_HEIGHT)) -} - -pub mod proto { - tonic::include_proto!("enclone"); -} - -pub async fn launch_gui() -> iced::Result { - let mut settings = Settings::default(); - let mut window_settings = iced::window::Settings::default(); - window_settings.size = (INITIAL_WIDTH, INITIAL_HEIGHT); // reasonable minimum size - settings.window = window_settings; - settings.exit_on_close_request = false; - let result = EncloneVisual::run(settings); - if result.is_err() { - eprintln!("\nLaunch failed.\n"); - eprintln!("error = {}\n", result.err().unwrap()); - eprintln!( - "If the error is something like\n\ - a suitable graphics adapter or device could not be found\n\ - then the problem may be that your system is not properly set up to use\n\ - GPU acceleration. OpenGL or Vulkan needs to be set up for this to work.\n\ - A good test case is the program glxgears. If you can run it and it displays\n\ - some moving gears, then your system is likely set up properly. Otherwise you\n\ - should get that to work, and then see if this program will work.\n" - ); - std::process::exit(1); - } - result -} - -pub fn capture(testname: &str, window_id: usize) { - if testname.len() > 0 { - thread::sleep(Duration::from_millis(50)); - let o = std::process::Command::new("screencapture") - .arg("-x") - .arg(&format!("-l{}", window_id)) - .arg(&format!("enclone_visual/outputs/{}.png", testname)) - .output() - .expect("failed to execute screencapture"); - if o.status.code() != Some(0) { - xprintln!("\nCall to screencapture failed."); - xprintln!("stderr =\n{}\n", strme(&o.stderr)); - std::process::exit(1); - } - } -} - -pub fn capture_as_file(filename: &str, window_id: usize) { - thread::sleep(Duration::from_millis(50)); - let o = std::process::Command::new("screencapture") - .arg("-x") - .arg(&format!("-l{}", window_id)) - .arg(&filename) - .output() - .expect("failed to execute screencapture"); - if o.status.code() != Some(0) { - xprintln!("\nCall to screencapture failed."); - xprintln!("stderr =\n{}\n", strme(&o.stderr)); - std::process::exit(1); - } -} - -pub fn capture_as_bytes() -> Vec { - let filename = "/tmp/enclone_visual_snapshot.png"; - capture_as_file(&filename, get_window_id()); - let mut bytes = Vec::::new(); - { - let mut f = File::open(&filename).unwrap(); - f.read_to_end(&mut bytes).unwrap(); - } - remove_file(&filename).unwrap(); - bytes -} - -#[cfg(any(target_os = "macos", target_os = "ios"))] -pub fn get_window_id() -> usize { - let windows = create_window_list(0 as u32, 0 as u32); - if windows.is_none() { - eprintln!("\nattempty to create window list failed.\n"); - std::process::exit(1); - } - let descrips = create_description_from_array(windows.unwrap()); - if descrips.is_none() { - eprintln!("\nattempty to create window descriptions failed.\n"); - std::process::exit(1); - } - let descrips = descrips.unwrap(); - let this_pid = std::process::id() as i64; - for d in descrips.iter() { - if d.contains_key(&CFString::from("kCGWindowOwnerPID")) { - let pid = d.get(&CFString::from("kCGWindowOwnerPID")); - let pid = pid.deref().downcast::().unwrap(); - let pid = pid.to_i64().unwrap(); - if pid == this_pid { - if d.contains_key(&CFString::from("kCGWindowName")) { - let window_name = d.get(&CFString::from("kCGWindowName")); - let window_name = window_name.deref().downcast::().unwrap(); - if window_name == "EncloneVisual" { - if d.contains_key(&CFString::from("kCGWindowNumber")) { - let window_number = d.get(&CFString::from("kCGWindowNumber")); - let window_number = - window_number.deref().downcast::().unwrap(); - let window_number = window_number.to_i64().unwrap() as usize; - return window_number; - } - } - } - } - } - } - panic!("\nUnable to determine window id.\n"); -} - -#[cfg(not(any(target_os = "macos", target_os = "ios")))] -pub fn get_window_id() -> usize { - panic!("Unimplemented!"); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Global variables for client. - -pub static REMOTE: AtomicBool = AtomicBool::new(false); -pub static USING_SETUP: AtomicBool = AtomicBool::new(false); -pub static CLEANED_UP: AtomicBool = AtomicBool::new(false); -pub static VERBOSE: AtomicBool = AtomicBool::new(false); -pub static CTRLC: AtomicBool = AtomicBool::new(false); -pub static COOKBOOK: AtomicBool = AtomicBool::new(false); -pub static SUMMARY: AtomicBool = AtomicBool::new(false); -pub static INTERNAL: AtomicBool = AtomicBool::new(false); -pub static TEST_MODE: AtomicBool = AtomicBool::new(false); -pub static PROCESSING_REQUEST: AtomicBool = AtomicBool::new(false); -pub static TESTING_USER_NAME: AtomicBool = AtomicBool::new(false); -pub static SENDING_SHARE: AtomicBool = AtomicBool::new(false); -pub static USER_NAME_VALID: AtomicBool = AtomicBool::new(false); -pub static DONE: AtomicBool = AtomicBool::new(false); -pub static GROUP_ID_CLICKED_ON: AtomicBool = AtomicBool::new(false); -pub static GET_MY_SHARES: AtomicBool = AtomicBool::new(false); -pub static RELEASE_MY_SHARES: AtomicBool = AtomicBool::new(false); -pub static PLAYBACK: AtomicBool = AtomicBool::new(false); -pub static FAIL_ON_ERROR: AtomicBool = AtomicBool::new(false); -pub static META_TESTING: AtomicBool = AtomicBool::new(false); -pub static PSEUDO_META: AtomicBool = AtomicBool::new(false); -pub static GET_MY_COOKBOOKS: AtomicBool = AtomicBool::new(false); -pub static GRAPHIC_MODE: AtomicBool = AtomicBool::new(false); -pub static GRAPHIC_MODE_LAST_SEEN: AtomicBool = AtomicBool::new(false); - -pub static REMOTE_SERVER_ID: AtomicUsize = AtomicUsize::new(0); -pub static SERVER_PROCESS_PID: AtomicUsize = AtomicUsize::new(0); -pub static SETUP_PID: AtomicUsize = AtomicUsize::new(0); -pub static COUNT: AtomicUsize = AtomicUsize::new(0); -pub static GROUP_ID: AtomicUsize = AtomicUsize::new(0); -pub static META: AtomicUsize = AtomicUsize::new(0); -pub static TOOLTIP_POS: AtomicUsize = AtomicUsize::new(0); - -lazy_static! { - pub static ref SERVER_LOGFILE: Mutex> = Mutex::new(Vec::::new()); - pub static ref MESSAGE_HISTORY: Mutex> = Mutex::new(Vec::::new()); - pub static ref BUG_REPORTS: Mutex> = Mutex::new(Vec::::new()); - pub static ref REMOTE_SHARE: Mutex> = Mutex::new(Vec::::new()); - pub static ref SHARE_RECIPIENTS: Mutex> = Mutex::new(Vec::::new()); - pub static ref VERSION: Mutex> = Mutex::new(Vec::::new()); - pub static ref VISUAL_DIR: Mutex> = Mutex::new(Vec::::new()); - pub static ref HOST: Mutex> = Mutex::new(Vec::::new()); - pub static ref USER_REQUEST: Mutex> = Mutex::new(Vec::::new()); - pub static ref SERVER_REPLY_TEXT: Mutex> = Mutex::new(Vec::::new()); - pub static ref SERVER_REPLY_SVG: Mutex> = Mutex::new(Vec::::new()); - pub static ref SERVER_REPLY_SUMMARY: Mutex> = Mutex::new(Vec::::new()); - pub static ref SERVER_REPLY_SUMMARY_PLUS: Mutex> = Mutex::new(Vec::::new()); - pub static ref SERVER_REPLY_METRICS: Mutex> = Mutex::new(Vec::::new()); - pub static ref SERVER_REPLY_DATASET_NAMES: Mutex> = - Mutex::new(Vec::::new()); - pub static ref CONFIG_FILE: Mutex> = Mutex::new(Vec::::new()); - pub static ref CONSOLE: Mutex> = Mutex::new(Vec::::new()); - pub static ref USER_NAME: Mutex> = Mutex::new(Vec::::new()); - pub static ref RECEIVED_SHARES_CONTENT: Mutex>> = Mutex::new(Vec::>::new()); - pub static ref RECEIVED_SHARES_MESSAGES: Mutex> = Mutex::new(Vec::::new()); - pub static ref RECEIVED_SHARES_FILENAMES: Mutex> = Mutex::new(Vec::::new()); - pub static ref TOOLTIP_TEXT: Mutex> = Mutex::new(Vec::::new()); - pub static ref COOKBOOK_DIRS: Mutex> = Mutex::new(Vec::::new()); - pub static ref EXEC: Mutex> = Mutex::new(Vec::::new()); - pub static ref EHOME: Mutex> = Mutex::new(Vec::::new()); -} - -lazy_static! { - pub static ref SHARE_CONTENT: Mutex>> = Mutex::new(Vec::>::new()); - pub static ref SERVER_REPLY_TABLE_COMP: Mutex>> = Mutex::new(Vec::>::new()); - pub static ref REMOTE_COOKBOOKS: Mutex>> = Mutex::new(Vec::>::new()); -} - -lazy_static! { - pub static ref SERVER_REPLY_LAST_WIDTHS: Mutex>> = - Mutex::new(Vec::>::new()); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Write line to stdout and to CONSOLE. - -#[macro_export] -macro_rules! xprint { - ($u:expr) => { - eprint!( $u ); - CONSOLE.lock().unwrap().push( format!( $u ) ); - }; - ($u:expr, $($x:tt)*) => { - eprint!( $u, $($x)* ); - CONSOLE.lock().unwrap().push( format!( $u, $($x)* ) ); - }; -} - -#[macro_export] -macro_rules! xprintln { - ($u:expr) => { - eprintln!( $u ); - CONSOLE.lock().unwrap().push( format!( $u ) ); - }; - ($u:expr, $($x:tt)*) => { - eprintln!( $u, $($x)* ); - CONSOLE.lock().unwrap().push( format!( $u, $($x)* ) ); - }; -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn _truncate(s: &str) -> String { - const MAX_LINES: usize = 10; - let mut t = String::new(); - let mut extra = 0; - for (i, line) in s.lines().enumerate() { - if i < MAX_LINES { - t += &mut format!("{}\n", line); - } else { - extra += 1; - } - } - if extra > 0 { - t += &mut format!("(+ {} more lines)", extra); - } - t -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Cleanup code to make sure processes are killed. - -#[cfg(not(target_os = "windows"))] -pub fn cleanup() { - if !CLEANED_UP.load(SeqCst) { - CLEANED_UP.store(true, SeqCst); - if REMOTE.load(SeqCst) { - if USING_SETUP.load(SeqCst) { - kill(Pid::from_raw(SETUP_PID.load(SeqCst) as i32), SIGINT_nix).unwrap(); - } - if HOST.lock().unwrap().len() > 0 { - let host = &HOST.lock().unwrap()[0]; - let _ = Command::new("ssh") - .arg(&host) - .arg("kill") - .arg("-9") - .arg(&format!("{}", REMOTE_SERVER_ID.load(SeqCst))) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn(); - } - } else { - kill( - Pid::from_raw(SERVER_PROCESS_PID.load(SeqCst) as i32), - SIGINT_nix, - ) - .unwrap(); - } - } -} - -#[cfg(target_os = "windows")] -pub fn cleanup() {} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Redirect SIGINT interrupts to the function "handler". There may be issues with reliablity, -// since a CTRL-C could happen at any point, including in the memory manager. -// -// When we tested this, we observed that under Linux, the signal handler is called, but on CTRL-C, -// the handler is not called, and instead one gets a traceback. This is a bug. - -#[cfg(not(target_os = "windows"))] -pub fn install_signal_handler() -> Result<(), Error> { - let handler = SigHandler::Handler(handler); - let action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty()); - unsafe { - sigaction(Signal::SIGINT, &action)?; - } - Ok(()) -} - -#[cfg(not(target_os = "windows"))] -extern "C" fn handler(sig: i32) { - if sig == SIGINT { - cleanup(); - std::process::exit(0); - } -} - -pub extern "C" fn exit_handler() { - cleanup(); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// This is copied from the palaver crate 0.3.0. We copied it because it had not been updated -// recently and was causing crate duplication. - -// Count the number of threads of the current process. Uses -// [`/proc/self/stat`](http://man7.org/linux/man-pages/man5/proc.5.html):`num_threads` on Linux, -// [`task_threads`](http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_threads.html) -// on macOS. - -pub fn thread_count() -> usize { - #[cfg(any(target_os = "android", target_os = "linux"))] - { - // This pulls in the procfs crate. Not really sure this is necessary. - - procfs::process::Process::myself() - .unwrap() - .stat - .num_threads - .try_into() - .unwrap() - } - #[cfg(any(target_os = "macos", target_os = "ios"))] - { - use mach::{ - kern_return::{kern_return_t, KERN_SUCCESS}, - mach_types::thread_act_array_t, - message::mach_msg_type_number_t, - task::task_threads, - traps::mach_task_self, - vm_types::{vm_address_t, vm_map_t, vm_size_t}, - }; - use std::{mem, ptr}; - extern "C" { - pub fn vm_deallocate( - target_task: vm_map_t, - address: vm_address_t, - size: vm_size_t, - ) -> kern_return_t; - } - - let this_task = unsafe { mach_task_self() }; - - let mut thread_list: thread_act_array_t = ptr::null_mut(); - let mut thread_count: mach_msg_type_number_t = 0; - let kret = unsafe { task_threads(this_task, &mut thread_list, &mut thread_count) }; - assert_eq!(kret, KERN_SUCCESS); - let thread_count: usize = thread_count.try_into().unwrap(); - - for i in 0..thread_count { - let kret = unsafe { - mach::mach_port::mach_port_deallocate( - this_task, - *thread_list.offset(i.try_into().unwrap()), - ) - }; - assert_eq!(kret, KERN_SUCCESS); - } - let kret = unsafe { - vm_deallocate( - this_task, - thread_list as usize, - mem::size_of_val(&*thread_list) * thread_count, - ) - }; - assert_eq!(kret, KERN_SUCCESS); - thread_count - } - #[cfg(not(any( - target_os = "android", - target_os = "linux", - target_os = "macos", - target_os = "ios" - )))] - unimplemented!() -} diff --git a/enclone_visual/src/messages.rs b/enclone_visual/src/messages.rs deleted file mode 100644 index 191d30f26e..0000000000 --- a/enclone_visual/src/messages.rs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -#[derive(Debug, Clone)] -pub enum Message { - InputChanged1(String), - InputChanged2(String), - InputChangedN(String, usize), - SubmitButtonPressed(Result<(), String>), - BackButtonPressed(Result<(), String>), - ForwardButtonPressed(Result<(), String>), - DelButtonPressed(Result<(), String>), - ComputationDone(Result<(), String>), - // EventOccurred(iced_native::Event), - GraphicsCopyButtonPressed, - GraphicsCopyButtonFlashed(Result<(), String>), - CommandCopyButtonPressed, - DoNothing, - Exit, - ClearButtonPressed, - RunTests(Result<(), String>), - Capture(Result<(), String>), - GroupClicked(crate::canvas_view::Message), - Resize(u32, u32), - HelpOpen(Result<(), String>), - HelpClose(Result<(), String>), - CommandOpen(Result<(), String>), - CommandClose, - SummaryOpen(Result<(), String>), - SummaryClose(Result<(), String>), - ClonotypesOpen(Result<(), String>), - ClonotypesClose, - GraphicOpen(Result<(), String>), - GraphicClose, - ConsoleOpen, - ConsoleClose, - ArchiveOpen(Result<(), String>), - ArchiveClose, - ArchiveSaveClose, - Save, - SaveAs(String), - CompleteSave(Result<(), String>), - SaveOnExit, - Restore(bool, usize), - RestoreCookbook(bool, usize), - ExpandArchiveEntry(bool, usize), - ExpandCookbookEntry(bool, usize), - DeleteArchiveEntry(bool, usize), - ArchiveName(String, usize), - ArchiveNameChange(usize), - CompleteArchiveNameChange(Result<(), String>), - Name(String), - NameChange(bool), - ArchiveShare(bool, usize), - UserSelected(bool, usize), - UserName(String, usize), - DoShare(bool), - CompleteDoShare(Result<(), String>), - ArchiveRefresh, - ArchiveRefreshComplete(Result<(), String>), - OpenArchiveDoc, - CloseArchiveDoc, - OpenAlluvialReadsDoc, - CloseAlluvialReadsDoc, - ArchiveNarrative(usize), - CopyArchiveNarrative(usize), - CompleteCopyArchiveNarrative(Result<(), String>), - CopyCookbookNarrative(usize), - CompleteCopyCookbookNarrative(Result<(), String>), - Narrative, - Meta(Result<(), String>), - CompleteMeta(Result<(), String>), - NullMeta(Result<(), String>), - Snap(&'static str), - SetName(&'static str), - CopyNarrative, - CompleteCopyNarrative(Result<(), String>), - CopySummary, - CompleteCopySummary(Result<(), String>), - WaitCommand(Result<(), String>), - MetricButton(usize), - CondenseMetrics, - CopySelectedMetrics, - CompleteCopySelectedMetrics(Result<(), String>), - Snapshot, - CompleteSnapshot(Result<(), String>), - GraphicSnapshot, - CompleteGraphicSnapshot(Result<(), String>), - CommandSnapshot, - CompleteCommandSnapshot(Result<(), String>), - ClonotypesSnapshot, - CompleteClonotypesSnapshot(Result<(), String>), - SummarySnapshot, - CompleteSummarySnapshot(Result<(), String>), - ArchiveSnapshot, - CompleteArchiveSnapshot(Result<(), String>), - Recompute, - CopyLastNarrative, - Sleep(u64), - SanityCheck, - CompleteSanityCheck(Result<(), String>), - ClonotypesCopy, - CompleteClonotypesCopy(Result<(), String>), - TooltipToggle, - CompleteTooltipToggle(Result<(), String>), - CopyAlluvialTables, - CompleteCopyAlluvialTables(Result<(), String>), - CopyAlluvialReadsTables, - CompleteCopyAlluvialReadsTables(Result<(), String>), - CopyAlluvialTablesCR, - CompleteCopyAlluvialTablesCR(Result<(), String>), - CopyAlluvialReadsTablesCR, - CompleteCopyAlluvialReadsTablesCR(Result<(), String>), - CopyAlluvialTablesCRD, - CompleteCopyAlluvialTablesCRD(Result<(), String>), - CopyAlluvialReadsTablesCRD, - CompleteCopyAlluvialReadsTablesCRD(Result<(), String>), - SetSummaryScrollablePos(f32), - CopyDescrips, - CompleteCopyDescrips(Result<(), String>), - GraphicPng, - CompleteGraphicPng(Result<(), String>), - GraphicHelp, -} diff --git a/enclone_visual/src/popover.rs b/enclone_visual/src/popover.rs deleted file mode 100644 index 44a4bd0599..0000000000 --- a/enclone_visual/src/popover.rs +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use crate::gui_structures::ComputeState::*; -use crate::*; -use iced::Length::Units; -use iced::{ - Alignment, Button, Column, Container, Element, Image, Length, Row, Rule, Scrollable, Space, - Text, TextInput, -}; -use itertools::izip; -use messages::Message; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn command(slf: &mut gui_structures::EncloneVisual) -> Element { - let command_title = Text::new(&format!("Command")) - .font(LIBERATION_SANS) - .size(30); - - // Buttons. - - let _command_snapshot_button = Button::new( - &mut slf.command_snapshot_button, - Text::new("Snapshot") - .font(LIBERATION_SANS) - .color(slf.command_snapshot_button_color), - ) - .on_press(Message::CommandSnapshot); - let command_close_button = Button::new( - &mut slf.command_close_button, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::CommandClose); - - // Help text. - - let help_text = - Text::new("The purpose of this page is to allow entry and display of a long command."); - - // Top bar. - - let mut top_bar = Row::new() - .push(command_title) - .push(Space::with_width(Length::Fill)); - #[cfg(any(target_os = "macos", target_os = "ios"))] - { - top_bar = top_bar - .push(_command_snapshot_button) - .push(Space::with_width(Units(8))); - } - top_bar = top_bar.push(command_close_button); - - // Text input column. - - let mut text_input_column = Column::new() - .spacing(8) - .width(iced::Length::Fill) - .push( - TextInput::new( - &mut slf.input1, - "", - &slf.input1_value, - Message::InputChanged1, - ) - .padding(7) - .font(DEJAVU_BOLD) - .size(16), - ) - .push( - TextInput::new( - &mut slf.input2, - "", - &slf.input2_value, - Message::InputChanged2, - ) - .padding(7) - .font(DEJAVU_BOLD) - .size(16), - ); - let n = slf.inputn.len(); - for (i, y, z) in izip!(0..n, slf.inputn.iter_mut(), slf.inputn_value.iter_mut()) { - text_input_column = text_input_column.push( - TextInput::new(y, "", &z, move |x: String| Message::InputChangedN(x, i)) - .padding(7) - .font(DEJAVU_BOLD) - .size(16), - ); - } - - // Buttons beside it. - - let button = Button::new( - &mut slf.button, - Text::new(if slf.compute_state == WaitingForRequest { - "Submit" - } else { - "thinking" - }) - .font(LIBERATION_SANS), - ) - .padding(10) - .on_press(Message::SubmitButtonPressed(Ok(()))); - let clear_button = Button::new( - &mut slf.clear_button, - Text::new("Clear").font(LIBERATION_SANS), - ) - .padding(10) - .on_press(Message::ClearButtonPressed); - - // Complete the display. - - let mut content = Column::new().spacing(SPACING).padding(20).push(top_bar); - content = content.push(help_text); - content = content - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push( - Row::new() - .spacing(10) - .align_items(Alignment::Center) - .push(text_input_column) - .push(button) - .push(clear_button), - ); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn graphic(slf: &mut gui_structures::EncloneVisual) -> Element { - let graphic_title = Text::new(&format!("Graphic")) - .font(LIBERATION_SANS) - .size(30); - - // Buttons. - - let tooltip_button = Button::new( - &mut slf.tooltip_toggle_button, - Text::new("Tooltip") - .font(LIBERATION_SANS) - .color(slf.tooltip_toggle_button_color), - ) - .on_press(Message::TooltipToggle); - let help_button = Button::new( - &mut slf.graphic_help_button, - Text::new(&slf.graphic_help_title).font(LIBERATION_SANS), - ) - .on_press(Message::GraphicHelp); - let _graphic_snapshot_button = Button::new( - &mut slf.graphic_snapshot_button, - Text::new("Snapshot") - .font(LIBERATION_SANS) - .color(slf.graphic_snapshot_button_color), - ) - .on_press(Message::GraphicSnapshot); - let png_button = Button::new( - &mut slf.graphic_png_button, - Text::new(&slf.graphic_png_title) - .font(LIBERATION_SANS) - .color(slf.png_button_color), - ) - .on_press(Message::GraphicPng); - let graphic_close_button = Button::new( - &mut slf.graphic_close_button, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::GraphicClose); - - // Help text. - - let help_text = Text::new( - "The purpose of this page is to allow the graphics object to \ - occupy the entire window.\n\n\ - \ - The default behavior is to render the graphics from the SVG representation. Sometimes \ - converting to PNG first renders better. To get to this, push the PNG button. Note that \ - tooltip text cannot be displayed in this mode.\n\n\ - \ - The Tooltip button may be used to move the tooltip box that is seen when hovering over \ - a cell. Each push of the button causes a rotation of the box location between the four \ - corners.", - ) - .font(LIBERATION_SANS); - - // Top bar. - - let mut top_bar = Row::new() - .push(graphic_title) - .push(Space::with_width(Length::Fill)) - .push(help_button) - .push(Space::with_width(Units(8))) - .push(tooltip_button) - .push(Space::with_width(Units(8))); - #[cfg(any(target_os = "macos", target_os = "ios"))] - { - top_bar = top_bar - .push(_graphic_snapshot_button) - .push(Space::with_width(Units(8))) - } - top_bar = top_bar - .push(png_button) - .push(Space::with_width(Units(8))) - .push(graphic_close_button); - - // Complete the display. - - let svg_height = CURRENT_HEIGHT.load(SeqCst) as u16; - let have_canvas = slf.canvas_view.state.geometry_value.is_some(); - let mut graphic_row = Row::new().spacing(10); - if slf.svg_value.len() > 0 { - if have_canvas && slf.graphic_png_title != "SVG" { - graphic_row = graphic_row - .push( - slf.canvas_view - .view() - .map(move |message| Message::GroupClicked(message)), - ) - .height(Units(svg_height)); - } else { - let svg_as_png = Image::new(iced::image::Handle::from_memory(slf.png_value.clone())) - .height(Units(svg_height)); - graphic_row = graphic_row.push(svg_as_png); - } - } - let mut content = Column::new().spacing(SPACING).padding(20).push(top_bar); - if slf.graphic_help_title == "Close help" { - content = content.push(help_text); - } - content = content - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(graphic_row); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn clonotypes(slf: &mut gui_structures::EncloneVisual) -> Element { - let clonotypes_title = Text::new(&format!("Clonotypes")) - .font(LIBERATION_SANS) - .size(30); - - // Buttons. - - let _clonotypes_snapshot_button = Button::new( - &mut slf.clonotypes_snapshot_button, - Text::new("Snapshot") - .font(LIBERATION_SANS) - .color(slf.clonotypes_snapshot_button_color), - ) - .on_press(Message::ClonotypesSnapshot); - let copy_button = Button::new( - &mut slf.clonotypes_copy_button, - Text::new("Copy text") - .font(LIBERATION_SANS) - .color(slf.clonotypes_copy_button_color), - ) - .on_press(Message::ClonotypesCopy); - let clonotypes_close_button = Button::new( - &mut slf.clonotypes_close_button, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::ClonotypesClose); - - // The rest. - - const CLONOTYPE_FONT_SIZE: u16 = 13; - let font_width = CLONOTYPE_FONT_SIZE as f32 * DEJAVU_WIDTH_OVER_HEIGHT; - let available = slf.width - (3 * SPACING + SCROLLBAR_WIDTH) as u32; - let nchars = (available as f32 / font_width).round() as usize; - let mut trunc = String::new(); - let failed = slf.output_value.contains("enclone failed"); - for line in slf.output_value.lines() { - for (i, c) in line.chars().enumerate() { - if i == nchars && !failed { - break; - } - trunc.push(c); - } - trunc.push('\n'); - } - let mut top_bar = Row::new() - .push(clonotypes_title) - .push(Space::with_width(Length::Fill)); - #[cfg(any(target_os = "macos", target_os = "ios"))] - { - top_bar = top_bar - .push(_clonotypes_snapshot_button) - .push(Space::with_width(Units(8))); - } - top_bar = top_bar - .push(copy_button) - .push(Space::with_width(Units(8))) - .push(clonotypes_close_button); - let clonotypes_scrollable = Scrollable::new(&mut slf.clonotypes_scroll) - .width(Length::Fill) - .height(Length::Fill) - .scrollbar_width(SCROLLBAR_WIDTH) - .scroller_width(12) - .style(style::ScrollableStyle) - .push( - Text::new(&trunc) - .font(DEJAVU_BOLD) - .size(CLONOTYPE_FONT_SIZE), - ); - let content = Column::new() - .spacing(SPACING) - .padding(20) - .push(top_bar) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(clonotypes_scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn console(slf: &mut gui_structures::EncloneVisual) -> Element { - let console_title = Text::new(&format!("Console")) - .font(LIBERATION_SANS) - .size(30); - let mut console = String::new(); - let n = CONSOLE.lock().unwrap().len(); - for i in 0..n { - console += &mut format!("{}\n", CONSOLE.lock().unwrap()[i]); - } - console += " \n\n\n"; - let console_close_button = Button::new( - &mut slf.console_close_button, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::ConsoleClose); - let intro_text = "This console is mostly for developers. It shows some logging and provides \ - some tools for tracing bugs and maintaining cookbooks."; - let sanity_text = "The sanity check button is for debugging. It causes some sanity checks \ - to be run on the current enclone visual state."; - let sanity_button = Button::new( - &mut slf.sanity_button, - Text::new("Sanity check") - .font(LIBERATION_SANS) - .color(slf.sanity_button_color), - ) - .on_press(Message::SanityCheck); - let console_text = "The current console output is shown below."; - let recompute_text = "The recompute button causes each state within the given session to be \ - recomputed. The purpose of this is to update the session to reflect the results of the \ - current enclone visual code, in the event that it has changed. The recompute button will \ - cause the screen to flash as it recapitulates each computation. When done, it will return \ - to this page.\n\n\ - Typically the way you would use this is to go to archive page, restore a session, then \ - come here and push Recompute, then exit this page. If the recomputed session looks right, \ - then you would push Save, and finally go to the archive page and delete the original \ - version."; - let recompute_button = Button::new( - &mut slf.recompute_button, - Text::new("Recompute").font(LIBERATION_SANS), - ) - .on_press(Message::Recompute); - let top_bar = Row::new() - .push(console_title) - .push(Space::with_width(Length::Fill)) - .push(console_close_button); - let font_size = 15; - let console_scrollable = Scrollable::new(&mut slf.scroll) - .width(Length::Fill) - .height(Length::Fill) - .scrollbar_width(SCROLLBAR_WIDTH) - .scroller_width(12) - .style(style::ScrollableStyle) - .push( - Text::new(&format!("{}", console)) - .font(DEJAVU_BOLD) - .size(font_size as u16), - ); - let content = Column::new() - .spacing(SPACING) - .padding(20) - .push(top_bar) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Text::new(intro_text).font(LIBERATION_SANS)) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Text::new(sanity_text).font(LIBERATION_SANS)) - .push(sanity_button) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Text::new(recompute_text).font(LIBERATION_SANS)) - .push(recompute_button) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Text::new(console_text).font(LIBERATION_SANS)) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(console_scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} diff --git a/enclone_visual/src/proc1.rs b/enclone_visual/src/proc1.rs deleted file mode 100644 index 5e0c17fd1c..0000000000 --- a/enclone_visual/src/proc1.rs +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::gui_structures::ComputeState::WaitingForRequest; -use crate::history::*; -use crate::messages::*; -use crate::share::*; -use crate::*; -use iced::{Color, Command}; -use io_utils::*; -use std::time::Duration; -use vector_utils::*; - -pub fn do_recompute(slf: &mut EncloneVisual) -> Command { - let n = slf.state_count(); - if n == 0 { - return Command::none(); - } - let mut messages = Vec::::new(); - messages.push(Message::ConsoleClose); - let k = slf.hi(); - for _ in 0..k { - messages.push(Message::BackButtonPressed(Ok(()))); - } - for i in 0..n { - messages.push(Message::SubmitButtonPressed(Ok(()))); - messages.push(Message::CopyLastNarrative); - messages.push(Message::BackButtonPressed(Ok(()))); - messages.push(Message::DelButtonPressed(Ok(()))); - if i < n - 1 { - messages.push(Message::ForwardButtonPressed(Ok(()))); - if i > 0 { - messages.push(Message::ForwardButtonPressed(Ok(()))); - } - } - } - if n >= 2 { - for _ in 0..n - 2 { - messages.push(Message::BackButtonPressed(Ok(()))); - } - } - messages.push(Message::ConsoleOpen); - slf.meta_pos = 0; - slf.this_meta = messages; - META_TESTING.store(true, SeqCst); - PSEUDO_META.store(true, SeqCst); - Command::perform(noop0(), Message::Meta) -} - -pub fn do_archive_close(slf: &mut EncloneVisual, save: bool) -> Command { - let mut index = None; - for i in 0..slf.restore_requested.len() { - if slf.restore_requested[i] { - index = Some(i); - } - } - if index.is_some() { - let mut index = index.unwrap(); - if save { - slf.save("(saved upon restore)"); - index += 1; - } - let filename = format!( - "{}/{}", - slf.archive_dir.as_ref().unwrap(), - slf.archive_list[index] - ); - let res = read_enclone_visual_history(&filename); - if res.is_ok() { - slf.h = res.unwrap(); - // Ignore history index and instead rewind. - if slf.h.history_index > 1 { - slf.h.history_index = 1; - } - slf.update_to_current(); - } else { - slf.restore_msg[index] = format!( - "Oh dear, restoration of the file {} \ - failed.", - filename - ); - } - } - let mut index = None; - for i in 0..slf.restore_cookbook_requested.len() { - if slf.restore_cookbook_requested[i] { - index = Some(i); - } - } - if index.is_some() { - let index = index.unwrap(); - if save { - slf.save("(saved upon restore)"); - } - let res = EncloneVisualHistory::restore_from_bytes(&slf.cookbooks[index]); - slf.h = res.unwrap(); - // Ignore history index and instead rewind. - if slf.h.history_index > 1 { - slf.h.history_index = 1; - } - slf.update_to_current(); - } - for i in 0..slf.archive_name_value.len() { - slf.archive_name_value[i] = slf.orig_archive_name[i].clone(); - } - slf.archive_mode = false; - slf.do_share = false; - slf.do_share_complete = false; - slf.user.clear(); - slf.user_value.clear(); - slf.user_selected.clear(); - slf.user_valid.clear(); - for i in 0..slf.archive_share_requested.len() { - slf.archive_share_requested[i] = false; - } - for i in 0..slf.expand_archive_entry.len() { - slf.expand_archive_entry[i] = false; - } - for i in 0..slf.cookbooks.len() { - slf.expand_cookbook_entry[i] = false; - slf.restore_cookbook_requested[i] = false; - } - for i in 0..slf.restore_msg.len() { - slf.restore_msg[i].clear(); - slf.restore_requested[i] = false; - if slf.delete_requested[i] { - let filename = format!( - "{}/{}", - slf.archive_dir.as_ref().unwrap(), - slf.archive_list[i] - ); - if path_exists(&filename) { - std::fs::remove_file(&filename).unwrap(); - } - slf.deleted[i] = true; - } - } - for i in 0..slf.restore_cookbook_msg.len() { - slf.restore_cookbook_msg[i].clear(); - } - slf.just_restored = false; - Command::none() -} - -pub fn do_meta(slf: &mut EncloneVisual) -> Command { - if slf.meta_pos == slf.this_meta.len() { - if PSEUDO_META.load(SeqCst) { - PSEUDO_META.store(false, SeqCst); - META_TESTING.store(false, SeqCst); - return Command::none(); - } - std::process::exit(0); - } - let mut done = false; - let mut null = false; - let mut submit = false; - let mut wait = false; - for i in slf.meta_pos..slf.this_meta.len() { - if i == 0 { - slf.window_id = get_window_id(); - } - - match slf.this_meta[i] { - Message::SubmitButtonPressed(_) => { - slf.meta_pos = i + 1; - submit = true; - break; - } - Message::WaitCommand(_) => { - slf.meta_pos = i + 1; - wait = true; - break; - } - _ => {} - } - - // slf.update(slf.this_meta[i].clone(), clipboard); - slf.update(slf.this_meta[i].clone()); - match slf.this_meta[i] { - Message::SetName(_) => { - slf.meta_pos = i + 1; - done = true; - break; - } - Message::WaitCommand(_) => { - slf.meta_pos = i + 1; - null = true; - break; - } - _ => {} - } - if i == slf.this_meta.len() - 1 { - slf.meta_pos = i + 1; - done = true; - } - } - if submit { - Command::perform(noop0(), Message::SubmitButtonPressed) - } else if wait { - Command::perform(noop0(), Message::WaitCommand) - } else if null { - Command::perform(noop0(), Message::NullMeta) - } else if done { - Command::perform(noop0(), Message::CompleteMeta) - } else { - Command::none() - } -} - -pub fn do_del_button_pressed(slf: &mut EncloneVisual) -> Command { - if slf.compute_state != WaitingForRequest { - Command::none() - } else { - slf.modified = true; - let h = slf.h.history_index - 1; - slf.h.svg_history.remove(h as usize); - slf.h.summary_history.remove(h as usize); - slf.h.input1_history.remove(h as usize); - slf.h.input2_history.remove(h as usize); - slf.h.inputn_history.remove(h as usize); - slf.h.narrative_history.remove(h as usize); - slf.h.translated_input_history.remove(h as usize); - slf.h.displayed_tables_history.remove(h as usize); - slf.h.table_comp_history.remove(h as usize); - slf.h.last_widths_history.remove(h as usize); - slf.h.is_blank.remove(h as usize); - slf.h.descrip_history.remove(h as usize); - if slf.state_count() == 0 { - slf.h.history_index -= 1; - slf.input1_value.clear(); - slf.input2_value.clear(); - slf.inputn_value.clear(); - slf.svg_value.clear(); - slf.png_value.clear(); - slf.submit_button_text.clear(); - slf.summary_value.clear(); - slf.output_value.clear(); - slf.table_comp_value.clear(); - slf.last_widths_value.clear(); - slf.descrip_value.clear(); - slf.translated_input_value.clear(); - slf.current_tables.clear(); - } else { - if h > 0 { - slf.h.history_index -= 1; - } - slf.update_to_current(); - } - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop0(), Message::Capture) - } - } -} - -pub fn do_archive_share( - slf: &mut EncloneVisual, - check_val: bool, - index: usize, -) -> Command { - if !check_val { - slf.do_share = false; - slf.do_share_complete = false; - } - let mut already_sharing = false; - for i in 0..slf.archive_share_requested.len() { - if i != index && slf.archive_share_requested[i] { - already_sharing = true; - } - } - if !already_sharing { - slf.archive_share_requested[index] = check_val; - if !check_val { - slf.user.clear(); - slf.user_value.clear(); - slf.user_selected.clear(); - slf.user_valid.clear(); - } else { - let mut names = Vec::::new(); - for i in 0..slf.shares.len() { - let mut j = 0; - while j < slf.shares[i].user_id.len() { - if slf.shares[i].user_id[j] == 0 { - break; - } - j += 1; - } - names.push(stringme(&slf.shares[i].user_id[0..j])); - } - names.sort(); - let mut freq = Vec::<(u32, String)>::new(); - make_freq(&names, &mut freq); - const MAX_USERS_TO_SHOW: usize = 6; - let show = std::cmp::min(MAX_USERS_TO_SHOW, freq.len()); - for i in 0..show { - slf.user.push(iced::text_input::State::new()); - slf.user_value.push(freq[i].1.clone()); - slf.user_selected.push(false); - slf.user_valid.push(false); - } - slf.user.push(iced::text_input::State::new()); - slf.user_value.push(String::new()); - slf.user_selected.push(false); - slf.user_valid.push(false); - } - } - Command::none() -} - -pub fn do_archive_refresh_complete(slf: &mut EncloneVisual) -> Command { - update_shares(slf); - let n = slf.archive_name.len(); - for i in 0..n { - if slf.delete_requested[i] { - let filename = format!( - "{}/{}", - slf.archive_dir.as_ref().unwrap(), - slf.archive_list[i] - ); - if path_exists(&filename) { - std::fs::remove_file(&filename).unwrap(); - } - } - } - slf.orig_archive_name = slf.archive_name_value.clone(); - slf.h.orig_name_value = slf.h.name_value.clone(); - slf.archive_refresh_button_color = Color::from_rgb(0.0, 0.0, 0.0); - - // Sleep so that total time for updating of shares is at least 0.4 seconds. This - // keeps the Refresh button red for at least that amount of time. - - const MIN_SLEEP: f64 = 0.4; - let used = elapsed(&slf.share_start.unwrap()); - if used < MIN_SLEEP { - let ms = ((MIN_SLEEP - used) * 1000.0).round() as u64; - thread::sleep(Duration::from_millis(ms)); - } - for i in 0..n { - if slf.archived_command_list[i].is_none() { - let x = &slf.archive_list[i]; - let path = format!("{}/{}", slf.archive_dir.as_ref().unwrap(), x); - let res = read_metadata(&path); - if res.is_err() { - panic!( - "Unable to read the history file at\n{}\n\ - This could either be a bug in enclone or it could be that \ - the file is corrupted.\n", - path, - ); - } - let (command_list, name, origin, narrative) = res.unwrap(); - slf.archived_command_list[i] = Some(command_list); - slf.archive_name_value[i] = name; - slf.archive_origin[i] = origin; - slf.archive_narrative[i] = narrative; - } - } - slf.do_share = false; - slf.do_share_complete = false; - slf.user.clear(); - slf.user_value.clear(); - slf.user_selected.clear(); - slf.user_valid.clear(); - for i in 0..slf.archive_share_requested.len() { - slf.archive_share_requested[i] = false; - } - for i in 0..slf.expand_archive_entry.len() { - slf.expand_archive_entry[i] = false; - } - for i in 0..slf.cookbooks.len() { - slf.expand_cookbook_entry[i] = false; - slf.restore_cookbook_requested[i] = false; - } - for i in 0..slf.restore_msg.len() { - slf.restore_msg[i].clear(); - slf.restore_requested[i] = false; - if slf.delete_requested[i] { - slf.deleted[i] = true; - } - } - for i in 0..slf.restore_cookbook_msg.len() { - slf.restore_cookbook_msg[i].clear(); - } - slf.just_restored = false; - for i in 0..n { - slf.archive_name_value[i] = slf.orig_archive_name[i].clone(); - slf.archive_name_change_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - slf.copy_archive_narrative_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - } - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop1(), Message::Capture) - } -} - -pub fn do_archive_open(slf: &mut EncloneVisual) -> Command { - slf.archive_mode = true; - update_shares(slf); - let n = slf.archive_name.len(); - for i in 0..n { - slf.archive_name_change_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - slf.copy_archive_narrative_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - // This is a dorky way of causing loading of command lists, etc. from disk - // occurs just once per session, and only if the archive button is pushed. - if slf.archived_command_list[i].is_none() { - let x = &slf.archive_list[i]; - let path = format!("{}/{}", slf.archive_dir.as_ref().unwrap(), x); - let res = read_metadata(&path); - if res.is_err() { - panic!( - "Unable to read the history file at\n{}\n\ - This could either be a bug in enclone or it could be that \ - the file is corrupted.\n", - path, - ); - } - let (command_list, name, origin, narrative) = res.unwrap(); - slf.archived_command_list[i] = Some(command_list); - slf.archive_name_value[i] = name; - slf.archive_origin[i] = origin; - slf.archive_narrative[i] = narrative; - } - } - slf.orig_archive_name = slf.archive_name_value.clone(); - slf.h.orig_name_value = slf.h.name_value.clone(); - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop1(), Message::Capture) - } -} diff --git a/enclone_visual/src/proc2.rs b/enclone_visual/src/proc2.rs deleted file mode 100644 index 0162c8b341..0000000000 --- a/enclone_visual/src/proc2.rs +++ /dev/null @@ -1,434 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::history::*; -use crate::messages::*; -use crate::*; -use chrono::prelude::*; -use enclone_core::combine_group_pics::*; -use flate2::read::GzDecoder; -use gui_structures::ComputeState::*; -use iced::Command; -use io_utils::*; -use std::fs::File; -use std::io::Read; -use std::time::{Duration, Instant}; -use vector_utils::*; - -pub fn do_computation_done(slf: &mut EncloneVisual) -> Command { - let mut reply_text = SERVER_REPLY_TEXT.lock().unwrap()[0].clone(); - if reply_text.contains("enclone failed") { - reply_text = format!("enclone failed{}", reply_text.after("enclone failed")); - } - if reply_text.len() == 0 { - if slf.translated_input_value.contains(" NOPRINT") { - reply_text = "You used the NOPRINT option, so there are no \ - clonotypes to see." - .to_string(); - } else { - reply_text = "There are no clonotypes. Please have a look at the summary.".to_string(); - } - } - - // Start storing values. - - let reply_table_comp = SERVER_REPLY_TABLE_COMP.lock().unwrap()[0].clone(); - slf.table_comp_value = reply_table_comp.clone(); - let hi = slf.h.history_index; - let len = slf.h.table_comp_hist_uniq.len(); - if len > 0 && slf.h.table_comp_hist_uniq[len - 1] == reply_table_comp { - slf.h - .table_comp_history - .insert(hi as usize, (len - 1) as u32); - } else { - slf.h.table_comp_history.insert(hi as usize, len as u32); - slf.h.table_comp_hist_uniq.push(reply_table_comp.clone()); - if slf.table_comp_value.len() > 0 { - let mut gunzipped = Vec::::new(); - let mut d = GzDecoder::new(&*reply_table_comp); - d.read_to_end(&mut gunzipped).unwrap(); - slf.current_tables = serde_json::from_str(&strme(&gunzipped)).unwrap(); - } else { - slf.current_tables.clear(); - } - } - - // Get the summary, and stuff the dataset names and metrics into it. The reason for this - // grotesque operation was to avoid updating the history data structure. - - let reply_summary = SERVER_REPLY_SUMMARY_PLUS.lock().unwrap()[0].clone(); - - // Keep going. - - reply_text += "\n \n \n"; // papering over truncation bug in display - let reply_last_widths = SERVER_REPLY_LAST_WIDTHS.lock().unwrap()[0].clone(); - let mut reply_svg = String::new(); - let mut blank = false; - if SERVER_REPLY_SVG.lock().unwrap().len() > 0 { - reply_svg = SERVER_REPLY_SVG.lock().unwrap()[0].clone(); - if reply_svg.len() == 0 { - reply_svg = blank_svg(); - blank = true; - } - } - - // Continue storing values. - // - // We want to push as little as possible onto the hist_uniq vectors, - // and we want to do this as rapidly as possible. The code here is not - // optimal, for two reasons: - // 1. We only compare to the last entry. - // 2. We make comparisons in cases where we should already know the answer. - - let len = slf.h.last_widths_hist_uniq.len(); - if len > 0 && slf.h.last_widths_hist_uniq[len - 1] == reply_last_widths { - slf.h - .last_widths_history - .insert(hi as usize, (len - 1) as u32); - } else { - slf.h.last_widths_history.insert(hi as usize, len as u32); - slf.h.last_widths_hist_uniq.push(reply_last_widths.clone()); - } - let len = slf.h.svg_hist_uniq.len(); - if len > 0 && slf.h.svg_hist_uniq[len - 1] == reply_svg { - slf.h.svg_history.insert(hi as usize, (len - 1) as u32); - } else { - slf.h.svg_history.insert(hi as usize, len as u32); - slf.h.svg_hist_uniq.push(reply_svg.clone()); - } - let len = slf.h.summary_hist_uniq.len(); - if len > 0 && slf.h.summary_hist_uniq[len - 1] == reply_summary { - slf.h.summary_history.insert(hi as usize, (len - 1) as u32); - } else { - slf.h.summary_history.insert(hi as usize, len as u32); - slf.h.summary_hist_uniq.push(reply_summary.clone()); - } - slf.narrative_value.clear(); - let len = slf.h.narrative_hist_uniq.len(); - if len > 0 && slf.h.narrative_hist_uniq[len - 1] == slf.narrative_value { - slf.h - .narrative_history - .insert(hi as usize, (len - 1) as u32); - } else { - slf.h.narrative_history.insert(hi as usize, len as u32); - slf.h.narrative_hist_uniq.push(slf.narrative_value.clone()); - } - let len = slf.h.displayed_tables_hist_uniq.len(); - if len > 0 && slf.h.displayed_tables_hist_uniq[len - 1] == reply_text { - slf.h - .displayed_tables_history - .insert(hi as usize, (len - 1) as u32); - } else { - slf.h - .displayed_tables_history - .insert(hi as usize, len as u32); - slf.h.displayed_tables_hist_uniq.push(reply_text.clone()); - } - let len = slf.h.input1_hist_uniq.len(); - if len > 0 && slf.h.input1_hist_uniq[len - 1] == slf.input1_value { - slf.h.input1_history.insert(hi as usize, (len - 1) as u32); - } else { - slf.h.input1_history.insert(hi as usize, len as u32); - slf.h.input1_hist_uniq.push(slf.input1_value.clone()); - } - let len = slf.h.input2_hist_uniq.len(); - if len > 0 && slf.h.input2_hist_uniq[len - 1] == slf.input2_value { - slf.h.input2_history.insert(hi as usize, (len - 1) as u32); - } else { - slf.h.input2_history.insert(hi as usize, len as u32); - slf.h.input2_hist_uniq.push(slf.input2_value.clone()); - } - let len = slf.h.inputn_hist_uniq.len(); - if len > 0 && slf.h.inputn_hist_uniq[len - 1] == slf.inputn_value { - slf.h.inputn_history.insert(hi as usize, (len - 1) as u32); - } else { - slf.h.inputn_history.insert(hi as usize, len as u32); - slf.h.inputn_hist_uniq.push(slf.inputn_value.clone()); - } - let len = slf.h.descrip_hist_uniq.len(); - if len > 0 && slf.h.descrip_hist_uniq[len - 1] == slf.descrip_value { - slf.h.descrip_history.insert(hi as usize, (len - 1) as u32); - } else { - slf.h.descrip_history.insert(hi as usize, len as u32); - slf.h.descrip_hist_uniq.push(slf.descrip_value.clone()); - } - let len = slf.h.translated_input_hist_uniq.len(); - if len > 0 && slf.h.translated_input_hist_uniq[len - 1] == slf.translated_input_value { - slf.h - .translated_input_history - .insert(hi as usize, (len - 1) as u32); - } else { - slf.h - .translated_input_history - .insert(hi as usize, len as u32); - slf.h - .translated_input_hist_uniq - .push(slf.translated_input_value.clone()); - } - slf.h.is_blank.insert(hi as usize, blank); - slf.h.history_index += 1; - slf.output_value = reply_text.to_string(); - slf.svg_value = reply_svg.to_string(); - slf.summary_value = reply_summary.to_string(); - slf.last_widths_value = reply_last_widths.clone(); - if slf.svg_value.len() > 0 { - slf.post_svg(&reply_svg); - } - slf.compute_state = WaitingForRequest; - xprintln!( - "total time to run command = {:.1} seconds", - elapsed(&slf.start_command.unwrap()) - ); - #[cfg(not(target_os = "windows"))] - { - let peak_mem_mb = peak_mem_usage_bytes() as f64 / ((1024 * 1024) as f64); - xprintln!( - "all time peak mem of this process is {:.1} MB\n", - peak_mem_mb - ); - } - if VERBOSE.load(SeqCst) { - let mb = (1024 * 1024) as f64; - let mut total_svg = 0; - for x in slf.h.svg_hist_uniq.iter() { - total_svg += x.len(); - } - xprintln!("stored svgs = {:.1} MB", total_svg as f64 / mb); - let mut total_tables = 0; - for x in slf.h.table_comp_hist_uniq.iter() { - total_tables += x.len(); - } - xprintln!("stored tables = {:.1} MB", total_tables as f64 / mb); - xprintln!(""); - } - - if META_TESTING.load(SeqCst) { - Command::perform(noop0(), Message::Meta) - } else if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - slf.sanity_check(); - assert!(slf.h.save_restore_works()); - test_evh_read_write(&slf.h, "/tmp/evh_test"); - std::fs::remove_file("/tmp/evh_test").unwrap(); - Command::perform(noop0(), Message::Capture) - } -} - -pub fn do_share_button_pressed(slf: &mut EncloneVisual, check_val: bool) -> Command { - slf.do_share = check_val; - if !check_val { - slf.do_share_complete = false; - } else { - let mut recipients = Vec::::new(); - for i in 0..slf.user_value.len() { - if slf.user_valid[i] { - recipients.push(slf.user_value[i].clone()); - } - } - let mut index = 0; - for i in 0..slf.archive_share_requested.len() { - if slf.archive_share_requested[i] { - index = i; - } - } - let path = format!( - "{}/{}", - slf.archive_dir.as_ref().unwrap(), - slf.archive_list[index] - ); - if !path_exists(&path) { - xprintln!("could not find path for archive file\n"); - std::process::exit(1); - } - let mut content = Vec::::new(); - let f = File::open(&path); - if f.is_err() { - xprintln!("could not open archive file\n"); - std::process::exit(1); - } - let mut f = f.unwrap(); - let res = f.read_to_end(&mut content); - if res.is_err() { - xprintln!("could not read archive file\n"); - std::process::exit(1); - } - SHARE_CONTENT.lock().unwrap().clear(); - SHARE_CONTENT.lock().unwrap().push(content); - SHARE_RECIPIENTS.lock().unwrap().clear(); - let days = Utc::now().num_days_from_ce(); - for i in 0..recipients.len() { - SHARE_RECIPIENTS.lock().unwrap().push(recipients[i].clone()); - let mut user_name = [0 as u8; 32]; - for j in 0..recipients[i].len() { - user_name[j] = recipients[i].as_bytes()[j]; - } - slf.shares.push(Share { - days_since_ce: days, - user_id: user_name, - }); - } - SENDING_SHARE.store(true, SeqCst); - } - Command::perform(compute_share(), Message::CompleteDoShare) -} - -pub fn do_submit_button_pressed(slf: &mut EncloneVisual) -> Command { - slf.modified = true; - let mut values = Vec::::new(); - if slf.input1_value.len() > 0 { - values.push(slf.input1_value.clone()); - } - if slf.input2_value.len() > 0 { - values.push(slf.input2_value.clone()); - } - for j in 0..slf.inputn_value.len() { - if slf.inputn_value[j].len() > 0 { - values.push(slf.inputn_value[j].clone()); - } - } - slf.input_value = format!("{}", values.iter().format(" ")); - let mut group_spec = true; - let mut group_ids = Vec::::new(); - let s = slf.input_value.split(',').collect::>(); - for i in 0..s.len() { - let mut ok = false; - if s[i].parse::().is_ok() { - let n = s[i].force_usize(); - if n >= 1 { - group_ids.push(n); - ok = true; - } - } else if s[i].contains("-") { - let (a, b) = (s[i].before("-"), s[i].after("-")); - if a.parse::().is_ok() && b.parse::().is_ok() { - let (a, b) = (a.force_usize(), b.force_usize()); - if 1 <= a && a <= b { - for j in a..=b { - group_ids.push(j); - } - ok = true; - } - } - } - if !ok { - group_spec = false; - } - } - if group_ids.is_empty() { - group_spec = false; - } - unique_sort(&mut group_ids); - if slf.compute_state != WaitingForRequest { - Command::none() - } else { - if group_spec { - if slf.h.input1_history.is_empty() & slf.h.input2_history.is_empty() - && slf.h.inputn_history.is_empty() - { - // This is flaky, as it does not create a history entry. However it's a weird - // rare case. - slf.output_value = "Group identifier can only be supplied if another \ - command has already been run." - .to_string(); - return Command::none(); - } - slf.translated_input_value = slf.input_value.clone(); - let mut reply_text; - let new = slf.translated_input_current(); - let args = new.split(' ').collect::>(); - if group_ids[group_ids.len() - 1] > slf.current_tables.len() { - reply_text = "Group identifier is too large.".to_string(); - } else { - let mut group_pics = Vec::::new(); - let mut last_widths = Vec::::new(); - for x in group_ids.iter() { - group_pics.push(slf.current_tables[*x - 1].clone()); - last_widths.push(slf.last_widths_value[*x - 1]); - } - reply_text = combine_group_pics( - &group_pics, - &last_widths, - args.contains(&"NOPRINT"), - args.contains(&"POUT=stdouth"), - true, // .noprintx - args.contains(&"HTML"), - args.contains(&"NGROUP"), - false, // .pretty - ); - reply_text += "\n \n \n"; // papering over truncation bug in display - } - let mut args2 = Vec::::new(); - for x in args.iter() { - if x.len() > 0 && !x.starts_with("G=") { - args2.push(x.to_string()); - } - } - args2.push(format!("G={}", slf.translated_input_value)); - slf.output_value = reply_text.to_string(); - let hi = slf.h.history_index; - slf.h - .input1_history - .insert(hi as usize, slf.h.input1_hist_uniq.len() as u32); - slf.h.input1_hist_uniq.push(slf.input1_value.clone()); - slf.h - .input2_history - .insert(hi as usize, slf.h.input2_hist_uniq.len() as u32); - slf.h.input2_hist_uniq.push(slf.input2_value.clone()); - slf.h - .inputn_history - .insert(hi as usize, slf.h.inputn_hist_uniq.len() as u32); - slf.h.inputn_hist_uniq.push(slf.inputn_value.clone()); - slf.h - .narrative_history - .insert(hi as usize, slf.h.narrative_hist_uniq.len() as u32); - slf.h.narrative_hist_uniq.push(slf.narrative_value.clone()); - slf.h - .translated_input_history - .insert(hi as usize, slf.h.translated_input_hist_uniq.len() as u32); - slf.h - .translated_input_hist_uniq - .push(args2.iter().format(" ").to_string()); - slf.h - .svg_history - .insert(hi as usize, slf.h.svg_history[(hi - 1) as usize]); - slf.h - .summary_history - .insert(hi as usize, slf.h.summary_history[(hi - 1) as usize]); - slf.h - .displayed_tables_history - .insert(hi as usize, slf.h.displayed_tables_hist_uniq.len() as u32); - slf.h - .displayed_tables_hist_uniq - .push(reply_text.to_string()); - slf.h - .table_comp_history - .insert(hi as usize, slf.h.table_comp_history[(hi - 1) as usize]); - slf.h - .last_widths_history - .insert(hi as usize, slf.h.last_widths_history[(hi - 1) as usize]); - slf.h.is_blank.insert(hi as usize, slf.is_blank_current()); - slf.h - .descrip_history - .insert(hi as usize, slf.h.descrip_history[(hi - 1) as usize]); - slf.h.history_index += 1; - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop0(), Message::Capture) - } - } else { - slf.compute_state = Thinking; - slf.start_command = Some(Instant::now()); - // The following sleep is needed for button text to consistenly update. - thread::sleep(Duration::from_millis(20)); - slf.translated_input_value = slf.input_value.clone(); - USER_REQUEST.lock().unwrap().clear(); - USER_REQUEST - .lock() - .unwrap() - .push(slf.translated_input_value.clone()); - PROCESSING_REQUEST.store(true, SeqCst); - Command::perform(compute(), Message::ComputationDone) - } - } -} diff --git a/enclone_visual/src/process_messages.rs b/enclone_visual/src/process_messages.rs deleted file mode 100644 index 5d09607830..0000000000 --- a/enclone_visual/src/process_messages.rs +++ /dev/null @@ -1,995 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::copy_image_to_clipboard::copy_bytes_to_clipboard; -use crate::gui_structures::ComputeState::WaitingForRequest; -use crate::history::*; -use crate::messages::*; -use crate::proc1::*; -use crate::proc2::*; -use crate::snapshot::snapshot; -use crate::summary::*; -use crate::testsuite::TESTS; -use crate::*; -use chrono::prelude::*; -use iced::{Color, Command}; -use itertools::Itertools; -use std::time::{Duration, Instant}; - -impl EncloneVisual { - pub fn process_message(&mut self, message: Message) -> Command { - MESSAGE_HISTORY - .lock() - .unwrap() - .push(format!("{:?}", message)); - match message { - Message::ArchiveSnapshot => { - self.archive_snapshot_start = Some(Instant::now()); - self.archive_snapshot_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteArchiveSnapshot) - } - - Message::CompleteArchiveSnapshot(_) => { - snapshot(&self.archive_snapshot_start); - self.archive_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::ClonotypesSnapshot => { - self.clonotypes_snapshot_start = Some(Instant::now()); - self.clonotypes_snapshot_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteClonotypesSnapshot) - } - - Message::CompleteClonotypesSnapshot(_) => { - snapshot(&self.clonotypes_snapshot_start); - self.clonotypes_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CommandSnapshot => { - self.command_snapshot_start = Some(Instant::now()); - self.command_snapshot_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteCommandSnapshot) - } - - Message::CompleteCommandSnapshot(_) => { - snapshot(&self.command_snapshot_start); - self.command_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CommandOpen(_) => { - self.command_mode = true; - Command::none() - } - - Message::CommandClose => { - self.command_mode = false; - Command::none() - } - - Message::GraphicHelp => { - if self.graphic_help_title == "Help" { - self.graphic_help_title = "Close help".to_string(); - } else { - self.graphic_help_title = "Help".to_string(); - } - Command::none() - } - - Message::GraphicPng => { - self.summary_png_start = Some(Instant::now()); - self.png_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteGraphicPng) - } - - Message::CompleteGraphicPng(_) => { - if self.graphic_png_title == "PNG" { - if self.png_value.len() == 0 { - self.png_value = convert_svg_to_png(&self.svg_value.as_bytes(), 2000); - } - } - const MIN_SLEEP: f64 = 0.4; - let used = elapsed(&self.summary_png_start.unwrap()); - if used < MIN_SLEEP { - let ms = ((MIN_SLEEP - used) * 1000.0).round() as u64; - thread::sleep(Duration::from_millis(ms)); - } - if self.graphic_png_title == "PNG" { - self.graphic_png_title = "SVG".to_string(); - } else { - self.graphic_png_title = "PNG".to_string(); - } - self.png_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyDescrips => { - self.descrips_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.descrips_for_spreadsheet.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyDescrips) - } - - Message::CompleteCopyDescrips(_) => { - self.descrips_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::OpenAlluvialReadsDoc => { - self.alluvial_reads_doc_open = true; - Command::none() - } - - Message::CloseAlluvialReadsDoc => { - self.alluvial_reads_doc_open = false; - Command::none() - } - - Message::SetSummaryScrollablePos(p) => { - self.summary_scroll.snap_to(p); - Command::none() - } - - Message::SummarySnapshot => { - self.summary_snapshot_start = Some(Instant::now()); - self.summary_snapshot_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteSummarySnapshot) - } - - Message::CompleteSummarySnapshot(_) => { - snapshot(&self.summary_snapshot_start); - self.summary_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyAlluvialReadsTables => { - self.alluvial_reads_tables_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.alluvial_reads_tables_for_spreadsheet.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyAlluvialReadsTables) - } - - Message::CompleteCopyAlluvialReadsTables(_) => { - self.alluvial_reads_tables_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyAlluvialTables => { - self.alluvial_tables_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.alluvial_tables_for_spreadsheet.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyAlluvialTables) - } - - Message::CompleteCopyAlluvialTables(_) => { - self.alluvial_tables_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyAlluvialReadsTablesCR => { - self.alluvial_reads_tables_cr_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.alluvial_reads_tables_for_spreadsheet_cr.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyAlluvialReadsTablesCR) - } - - Message::CompleteCopyAlluvialReadsTablesCR(_) => { - self.alluvial_reads_tables_cr_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyAlluvialTablesCR => { - self.alluvial_tables_cr_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.alluvial_tables_for_spreadsheet_cr.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyAlluvialTablesCR) - } - - Message::CompleteCopyAlluvialTablesCR(_) => { - self.alluvial_tables_cr_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyAlluvialReadsTablesCRD => { - self.alluvial_reads_tables_crd_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.alluvial_reads_tables_for_spreadsheet_crd.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyAlluvialReadsTablesCRD) - } - - Message::CompleteCopyAlluvialReadsTablesCRD(_) => { - self.alluvial_reads_tables_crd_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyAlluvialTablesCRD => { - self.alluvial_tables_crd_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.alluvial_tables_for_spreadsheet_crd.as_bytes()); - Command::perform(noop1(), Message::CompleteCopyAlluvialTablesCRD) - } - - Message::CompleteCopyAlluvialTablesCRD(_) => { - self.alluvial_tables_crd_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::TooltipToggle => { - self.tooltip_toggle_button_color = Color::from_rgb(1.0, 0.0, 0.0); - let pos = (TOOLTIP_POS.load(SeqCst) + 1) % 4; - TOOLTIP_POS.store(pos, SeqCst); - Command::perform(noop1(), Message::CompleteTooltipToggle) - } - - Message::CompleteTooltipToggle(_) => { - self.tooltip_toggle_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::GraphicSnapshot => { - self.graphic_snapshot_start = Some(Instant::now()); - self.graphic_snapshot_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteGraphicSnapshot) - } - - Message::CompleteGraphicSnapshot(_) => { - snapshot(&self.graphic_snapshot_start); - self.graphic_snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::GraphicOpen(_) => { - self.graphic_mode = true; - GRAPHIC_MODE.store(true, SeqCst); - Command::none() - } - - Message::GraphicClose => { - self.graphic_mode = false; - self.graphic_help_mode = true; - self.graphic_help_title = "Help".to_string(); - GRAPHIC_MODE.store(false, SeqCst); - self.graphic_png_title = "PNG".to_string(); - Command::none() - } - - Message::ClonotypesCopy => { - self.clonotypes_copy_button_color = Color::from_rgb(1.0, 0.0, 0.0); - let mut s = String::new(); - for line in self.output_value.lines() { - let t = line.replace(" ", ""); - if t.len() > 0 { - s += &mut format!("{}\n", line); - } - } - copy_bytes_to_clipboard(&s.as_bytes()); - Command::perform(noop1(), Message::CompleteClonotypesCopy) - } - - Message::CompleteClonotypesCopy(_) => { - self.clonotypes_copy_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::SanityCheck => { - self.sanity_check_start = Some(Instant::now()); - self.sanity_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteSanityCheck) - } - - Message::CompleteSanityCheck(_) => { - self.sanity_check(); - let used = elapsed(&self.sanity_check_start.unwrap()); - const MIN_SLEEP: f64 = 0.4; - if used < MIN_SLEEP { - let ms = ((MIN_SLEEP - used) * 1000.0).round() as u64; - thread::sleep(Duration::from_millis(ms)); - } - self.sanity_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::Sleep(ms) => { - thread::sleep(Duration::from_millis(ms)); - Command::none() - } - - Message::CopyLastNarrative => { - let index = self.h.narrative_history[(self.h.history_index - 2) as usize]; - let last = self.h.narrative_hist_uniq[index as usize].clone(); - let len = self.h.narrative_hist_uniq.len(); - self.h.narrative_hist_uniq.push(last); - self.h.narrative_history[(self.h.history_index - 1) as usize] = len as u32; - Command::none() - } - - Message::Recompute => do_recompute(self), - - Message::Snapshot => { - self.snapshot_start = Some(Instant::now()); - self.snapshot_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop0(), Message::CompleteSnapshot) - } - - Message::CompleteSnapshot(_) => { - snapshot(&self.snapshot_start); - self.snapshot_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopySelectedMetrics => { - self.copy_selected_metrics_button_color = Color::from_rgb(1.0, 0.0, 0.0); - let show = &self.metric_selected; - copy_bytes_to_clipboard( - &expand_summary_as_csv(&self.summary_current(), &show).as_bytes(), - ); - Command::perform(noop1(), Message::CompleteCopySelectedMetrics) - } - - Message::CompleteCopySelectedMetrics(_) => { - self.copy_selected_metrics_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CondenseMetrics => { - self.metrics_condensed = !self.metrics_condensed; - Command::none() - } - - Message::MetricButton(index) => { - self.metric_selected[index] = !self.metric_selected[index]; - Command::none() - } - - Message::WaitCommand(_) => { - while PROCESSING_REQUEST.load(SeqCst) { - thread::sleep(Duration::from_millis(10)); - } - Command::perform(noop1(), Message::Meta) - } - - Message::CopySummary => { - self.copy_summary_button_color = Color::from_rgb(1.0, 0.0, 0.0); - let show; - if !self.metrics_condensed { - show = vec![true; self.metric_selected.len()]; - } else { - show = self.metric_selected.clone(); - } - copy_bytes_to_clipboard( - &expand_summary(&self.summary_current(), true, &show).as_bytes(), - ); - Command::perform(noop1(), Message::CompleteCopySummary) - } - - Message::CompleteCopySummary(_) => { - self.copy_summary_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyNarrative => { - self.copy_narrative_button_color = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.narrative_current().as_bytes()); - Command::perform(noop1(), Message::CompleteCopyNarrative) - } - - Message::CompleteCopyNarrative(_) => { - self.copy_narrative_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CopyArchiveNarrative(i) => { - self.copy_archive_narrative_button_color[i] = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.archive_narrative[i].as_bytes()); - Command::perform(noop1(), Message::CompleteCopyArchiveNarrative) - } - - Message::CompleteCopyArchiveNarrative(_) => { - for i in 0..self.copy_archive_narrative_button_color.len() { - self.copy_archive_narrative_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - } - Command::none() - } - - Message::CopyCookbookNarrative(i) => { - self.copy_cookbook_narrative_button_color[i] = Color::from_rgb(1.0, 0.0, 0.0); - copy_bytes_to_clipboard(&self.cookbook_narrative[i].as_bytes()); - Command::perform(noop1(), Message::CompleteCopyCookbookNarrative) - } - - Message::CompleteCopyCookbookNarrative(_) => { - for i in 0..self.copy_cookbook_narrative_button_color.len() { - self.copy_cookbook_narrative_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - } - Command::none() - } - - Message::Snap(x) => { - capture(&x, self.window_id); - Command::none() - } - - Message::SetName(x) => { - self.save_name = x.to_string(); - Command::none() - } - - Message::Meta(_) => do_meta(self), - - Message::CompleteMeta(_) => { - capture(&self.save_name, self.window_id); - if self.meta_pos == self.this_meta.len() { - if PSEUDO_META.load(SeqCst) { - PSEUDO_META.store(false, SeqCst); - META_TESTING.store(false, SeqCst); - return Command::none(); - } - if PLAYBACK.load(SeqCst) { - println!("message history:\n"); - let messages = compressed_message_history(); - for i in 0..messages.len() { - println!("[{}] {}", i + 1, messages[i]); - } - } - println!(""); - std::process::exit(0); - } - Command::perform(noop0(), Message::Meta) - } - - Message::NullMeta(_) => Command::perform(noop0(), Message::Meta), - - Message::Narrative => { - self.modified = true; - let copy = get_clipboard_content(); - if copy.is_some() { - let copy = copy.unwrap(); - self.narrative_value = copy.clone(); - let len = self.h.narrative_hist_uniq.len(); - self.h.narrative_hist_uniq.push(copy); - self.h.narrative_history[(self.h.history_index - 1) as usize] = len as u32; - } - Command::none() - } - - Message::ArchiveNarrative(i) => { - self.modified = true; - let copy = get_clipboard_content(); - if copy.is_some() { - let copy = copy.unwrap(); - self.archive_narrative[i] = copy.clone(); - let filename = format!( - "{}/{}", - self.archive_dir.as_ref().unwrap(), - &self.archive_list[i] - ); - let res = rewrite_narrative(&filename, ©); - if res.is_err() { - xprintln!( - "\nSomething went wrong changing the narrative of\n{}\n\ - Possibly the file has been corrupted.\n", - filename, - ); - std::process::exit(1); - } - } - Command::none() - } - - Message::OpenArchiveDoc => { - self.archive_doc_open = true; - Command::none() - } - - Message::CloseArchiveDoc => { - self.archive_doc_open = false; - Command::none() - } - - Message::DoShare(check_val) => do_share_button_pressed(self, check_val), - - Message::CompleteDoShare(_) => { - self.do_share_complete = true; - Command::none() - } - - Message::Restore(check_val, index) => { - if !self.just_restored && !self.delete_requested[index] { - self.restore_requested[index] = check_val; - self.restore_msg[index] = - "Restore scheduled! Now click Dismiss or Save and dismiss at top." - .to_string(); - self.just_restored = true; - self.modified = false; - } - Command::none() - } - - Message::RestoreCookbook(check_val, index) => { - if !self.just_restored { - self.restore_cookbook_requested[index] = check_val; - self.restore_cookbook_msg[index] = - "Restore scheduled! Now click Dismiss or Save and dismiss at top." - .to_string(); - self.just_restored = true; - self.modified = false; - } - Command::none() - } - - Message::Save => { - self.save_in_progress = true; - self.save(""); - Command::perform(noop1(), Message::CompleteSave) - } - - Message::SaveAs(x) => { - self.save_in_progress = true; - self.save_as(&x, ""); - Command::perform(noop1(), Message::CompleteSave) - } - - Message::CompleteSave(_) => { - self.save_in_progress = false; - Command::none() - } - - Message::Exit => { - if true { - if self.sharing_enabled { - let share_bytes = unsafe { self.shares.align_to::().1.to_vec() }; - let share_file = format!("{}/shares", self.visual); - std::fs::write(&share_file, &share_bytes).unwrap(); - } - if self.save_on_exit { - let mut now = format!("{:?}", Local::now()); - now = now.replace("T", "___"); - now = now.before(".").to_string(); - now = now.replace(":", "-"); - let filename = format!("{}/{}", self.archive_dir.as_ref().unwrap(), now); - let res = write_enclone_visual_history(&self.h, &filename); - if res.is_err() { - xprintln!( - "Was unable to write history to the file {}, \ - so Save on Exit failed.\n", - filename - ); - std::process::exit(1); - } - } - if PLAYBACK.load(SeqCst) { - println!("message history:\n"); - let messages = compressed_message_history(); - for i in 0..messages.len() { - println!("[{}] {}", i + 1, messages[i]); - } - } - println!(""); - std::process::exit(0); - } - Command::none() - } - - Message::UserName(x, index) => { - self.user_value[index] = x.to_string(); - Command::none() - } - - Message::UserSelected(check_val, index) => { - self.user_selected[index] = check_val; - if check_val { - let user = &self.user_value[index]; - USER_NAME.lock().unwrap().clear(); - USER_NAME.lock().unwrap().push(user.to_string()); - TESTING_USER_NAME.store(true, SeqCst); - loop { - thread::sleep(Duration::from_millis(10)); - if !TESTING_USER_NAME.load(SeqCst) { - self.user_valid[index] = USER_NAME_VALID.load(SeqCst); - break; - } - } - if self.user_valid[index] { - if self.user_value[self.user_value.len() - 1].len() > 0 { - self.user.push(iced::text_input::State::new()); - self.user_value.push(String::new()); - self.user_selected.push(false); - self.user_valid.push(false); - } - } - } - Command::none() - } - - Message::ArchiveShare(check_val, index) => do_archive_share(self, check_val, index), - - Message::NameChange(check_val) => { - self.name_change_requested = check_val; - if !check_val { - self.h.name_value = self.h.orig_name_value.clone(); - } - Command::none() - } - - Message::Name(x) => { - self.h.name_value = x.to_string(); - Command::none() - } - - Message::ArchiveNameChange(i) => { - self.archive_name_change_button_color[i] = Color::from_rgb(1.0, 0.0, 0.0); - if self.archive_name_value[i] != self.orig_archive_name[i] { - let filename = format!( - "{}/{}", - self.archive_dir.as_ref().unwrap(), - &self.archive_list[i] - ); - let res = rewrite_name(&filename, &self.archive_name_value[i]); - if res.is_err() { - xprintln!( - "Something went wrong changing the name of\n{}\n\ - Possibly the file has been corrupted.\n", - filename, - ); - std::process::exit(1); - } - self.orig_archive_name[i] = self.archive_name_value[i].clone(); - } - Command::perform(noop1(), Message::CompleteArchiveNameChange) - } - - Message::CompleteArchiveNameChange(_) => { - for i in 0..self.archive_name_change_button_color.len() { - self.archive_name_change_button_color[i] = Color::from_rgb(0.0, 0.0, 0.0); - } - Command::none() - } - - Message::ArchiveName(x, index) => { - let mut y = String::new(); - for (i, char) in x.chars().enumerate() { - if i == 30 { - break; - } - y.push(char); - } - self.archive_name_value[index] = y; - Command::none() - } - - Message::DeleteArchiveEntry(check_val, index) => { - if !self.just_restored { - self.delete_requested[index] = check_val; - if check_val { - self.expand_archive_entry[index] = false; - self.restore_msg[index] = "Will be deleted upon refresh or dismissal of \ - this page. Before then, you can change your mind \ - and unclick!" - .to_string(); - } else { - self.restore_msg[index].clear(); - } - } - Command::none() - } - - Message::ExpandArchiveEntry(check_val, index) => { - if !self.delete_requested[index] { - self.expand_archive_entry[index] = check_val; - } - Command::none() - } - - Message::ExpandCookbookEntry(check_val, index) => { - self.expand_cookbook_entry[index] = check_val; - Command::none() - } - - Message::Resize(width, height) => { - self.width = width; - CURRENT_WIDTH.store(width as usize, SeqCst); - self.height = height; - CURRENT_HEIGHT.store(height as usize, SeqCst); - Command::none() - } - - Message::GroupClicked(_message) => { - if GROUP_ID_CLICKED_ON.load(SeqCst) { - GROUP_ID_CLICKED_ON.store(false, SeqCst); - if TOOLTIP_TEXT.lock().unwrap().is_empty() { - // This case happens rarely, and we don't know why, but haven't - // studied the problem. - return Command::none(); - } - self.modified = true; - let group_id = GROUP_ID.load(SeqCst); - self.input_value = format!("{}", group_id); - self.input1_value = format!("{}", group_id); - self.input2_value.clear(); - for i in 0..self.inputn_value.len() { - self.inputn_value[i].clear(); - } - let tt = TOOLTIP_TEXT.lock().unwrap()[0].clone(); - copy_bytes_to_clipboard(&tt.as_bytes()); - Command::perform(noop0(), Message::SubmitButtonPressed) - } else { - Command::none() - } - } - - Message::SubmitButtonPressed(_) => do_submit_button_pressed(self), - - Message::DelButtonPressed(_) => do_del_button_pressed(self), - - Message::BackButtonPressed(_) => { - if self.compute_state != WaitingForRequest { - Command::none() - } else { - self.h.history_index -= 1; - self.update_to_current(); - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop0(), Message::Capture) - } - } - } - - Message::ForwardButtonPressed(_) => { - if self.compute_state != WaitingForRequest { - Command::none() - } else { - self.h.history_index += 1; - self.update_to_current(); - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop0(), Message::Capture) - } - } - } - - Message::RunTests(_) => { - let count = COUNT.load(SeqCst); - if count == 0 { - self.window_id = get_window_id(); - } - if count < TESTS.len() { - if TESTS[count].0.len() > 0 { - if TESTS[count].0.contains(" + ") { - self.input1_value = TESTS[count].0.before(" + ").to_string(); - self.input2_value = TESTS[count].0.after(" + ").to_string(); - self.input_value = - format!("{} {}", self.input1_value, self.input2_value); - } else { - self.input_value = TESTS[count].0.to_string(); - self.input1_value = TESTS[count].0.to_string(); - self.input2_value.clear(); - } - for i in 0..self.inputn_value.len() { - self.inputn_value[i].clear(); - } - } - } else { - std::process::exit(0); - } - COUNT.store(COUNT.load(SeqCst) + 1, SeqCst); - Command::perform(noop(), TESTS[count].1) - } - - Message::HelpOpen(_) => { - self.help_mode = true; - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop1(), Message::Capture) - } - } - - Message::HelpClose(_) => { - self.help_mode = false; - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop1(), Message::Capture) - } - } - - Message::ClonotypesOpen(_) => { - self.clonotypes_mode = true; - Command::none() - } - - Message::ClonotypesClose => { - self.clonotypes_mode = false; - Command::none() - } - - Message::SummaryOpen(_) => { - self.summary_mode = true; - let summaryx = unpack_summary(&self.summary_value); - self.metric_selected = summaryx.metric_selected.clone(); - self.metrics_condensed = summaryx.metrics_condensed; - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop1(), Message::Capture) - } - } - - Message::SummaryClose(_) => { - self.summary_mode = false; - let mut summaryx = unpack_summary(&self.summary_value); - summaryx.metric_selected = self.metric_selected.clone(); - summaryx.metrics_condensed = self.metrics_condensed; - self.summary_value = summaryx.pack(); - self.h.summary_hist_uniq - [self.h.summary_history[self.h.history_index as usize - 1] as usize] = - self.summary_value.clone(); - if !TEST_MODE.load(SeqCst) { - Command::none() - } else { - Command::perform(noop1(), Message::Capture) - } - } - - Message::ConsoleOpen => { - self.console_mode = true; - Command::none() - } - - Message::ConsoleClose => { - self.console_mode = false; - Command::none() - } - - Message::ArchiveRefresh => { - self.share_start = Some(Instant::now()); - self.archive_refresh_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform(noop(), Message::ArchiveRefreshComplete) - } - - Message::ArchiveRefreshComplete(_) => do_archive_refresh_complete(self), - - Message::ArchiveClose => do_archive_close(self, false), - - Message::ArchiveSaveClose => do_archive_close(self, true), - - Message::ArchiveOpen(_) => do_archive_open(self), - - Message::SaveOnExit => { - self.save_on_exit = !self.save_on_exit; - Command::none() - } - - Message::InputChanged1(ref value) => { - self.modified = true; - self.input1_value = value.to_string(); - self.input_value = self.input1_value.clone(); - if self.input1_value.len() > 0 && self.input2_value.len() > 0 { - self.input_value += " "; - } - self.input_value += &mut self.input2_value.clone(); - Command::none() - } - - Message::InputChanged2(ref value) => { - self.modified = true; - self.input2_value = value.to_string(); - self.input_value = self.input1_value.clone(); - if self.input1_value.len() > 0 && self.input2_value.len() > 0 { - self.input_value += " "; - } - self.input_value += &mut self.input2_value.clone(); - Command::none() - } - - Message::InputChangedN(ref value, i) => { - self.modified = true; - self.inputn_value[i] = value.to_string(); - let mut values = Vec::::new(); - if self.input1_value.len() > 0 { - values.push(self.input1_value.clone()); - } - if self.input2_value.len() > 0 { - values.push(self.input2_value.clone()); - } - for j in 0..self.inputn_value.len() { - if self.inputn_value[j].len() > 0 { - values.push(self.inputn_value[j].clone()); - } - } - self.input_value = format!("{}", values.iter().format(" ")); - Command::none() - } - - Message::ClearButtonPressed => { - self.modified = true; - self.input1_value.clear(); - self.input2_value.clear(); - for j in 0..self.inputn_value.len() { - self.inputn_value[j].clear(); - } - Command::none() - } - - Message::ComputationDone(_) => do_computation_done(self), - - Message::Capture(_) => { - let verbose = false; - if verbose { - xprintln!("\ncapturing, input history:"); - for i in 0..self.h.input1_history.len() { - let mark = if i + 1 == self.h.history_index as usize { - "*" - } else { - "" - }; - xprintln!( - "[{}] {} {} {}", - i + 1, - self.h.input1_hist_uniq[self.h.input1_history[i] as usize], - self.h.input2_hist_uniq[self.h.input2_history[i] as usize], - mark - ); - // note not showing inputn - } - } - let count = COUNT.load(SeqCst); - if count >= 1 { - capture(&TESTS[count - 1].2, self.window_id); - } - Command::perform(noop0(), Message::RunTests) - } - - // Catch exit (when the upper left red button is pushed) and store DONE to make - // the server thread exit gracefully. Otherwise you will get a an error message - // and a traceback. - /* - Message::EventOccurred(ref event) => { - if let Event::Window(window::Event::CloseRequested) = event { - DONE.store(true, SeqCst); - thread::sleep(Duration::from_millis(50)); - self.should_exit = true; - } - Command::none() - } - */ - Message::GraphicsCopyButtonPressed => { - self.copy_image_button_color = Color::from_rgb(1.0, 0.0, 0.0); - Command::perform( - flash_copy_image_button(), - Message::GraphicsCopyButtonFlashed, - ) - } - - Message::GraphicsCopyButtonFlashed(_) => { - // Convert to PNG and copy to clipboard, and flash the button for the maximum of - // the conversion time and MIN_FLASH_SECONDS. - const MIN_FLASH_SECONDS: f64 = 0.4; - let t = Instant::now(); - let mut width = 2000; - let copy = get_clipboard_content(); - if copy.is_some() { - let copy = copy.unwrap(); - if copy.parse::().is_ok() { - let w = copy.force_usize(); - if w >= 1000 && w <= 4000 { - width = w as u32; - } - } - } - let png = convert_svg_to_png(&self.svg_value.as_bytes(), width); - copy_png_bytes_to_clipboard(&png); - let used = elapsed(&t); - let extra = MIN_FLASH_SECONDS - used; - if extra > 0.0 { - thread::sleep(Duration::from_millis((extra * 1000.0).round() as u64)); - } - self.copy_image_button_color = Color::from_rgb(0.0, 0.0, 0.0); - Command::none() - } - - Message::CommandCopyButtonPressed => { - copy_bytes_to_clipboard(&self.translated_input_current().as_bytes()); - Command::none() - } - - Message::DoNothing => Command::none(), - } - } -} diff --git a/enclone_visual/src/share.rs b/enclone_visual/src/share.rs deleted file mode 100644 index bc1909c5f4..0000000000 --- a/enclone_visual/src/share.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use crate::history::*; -use crate::*; -use chrono::prelude::*; -use iced::Color; - -pub fn update_shares(slf: &mut gui_structures::EncloneVisual) { - if !slf.sharing_enabled { - return; - } - - // Import shares. - - GET_MY_SHARES.store(true, SeqCst); - while GET_MY_SHARES.load(SeqCst) { - thread::sleep(Duration::from_millis(10)); - } - let k = RECEIVED_SHARES_CONTENT.lock().unwrap().len(); - let mut new_filenames = Vec::::new(); - for i in 0..k { - let bytes = &RECEIVED_SHARES_CONTENT.lock().unwrap()[i]; - let origin = RECEIVED_SHARES_MESSAGES.lock().unwrap()[i].clone(); - let mut evh = EncloneVisualHistory::restore_from_bytes(&bytes).unwrap(); - evh.origin = origin.clone(); - if META_TESTING.load(SeqCst) { - evh.origin = "session shared by ***** on ***** at *****".to_string(); - } - let mut now = format!("{:?}", Local::now()); - now = now.replace("T", "___"); - now = now.before(".").to_string(); - now = now.replace(":", "-"); - let filename = format!("{}.{}", now, i + 1); - let path = format!("{}/{}", slf.archive_dir.as_ref().unwrap(), filename); - let res = write_enclone_visual_history(&evh, &path); - if res.is_err() { - xprintln!( - "Was unable to write history to the file {}, \ - so Save on Exit failed.\n", - path - ); - std::process::exit(1); - } - new_filenames.push(filename); - } - prepend_to_vec(&mut slf.archive_list, &new_filenames); - prepend_to_vec(&mut slf.restore_requested, &vec![false; k]); - prepend_to_vec(&mut slf.delete_requested, &vec![false; k]); - prepend_to_vec(&mut slf.deleted, &vec![false; k]); - prepend_to_vec(&mut slf.expand_archive_entry, &vec![false; k]); - prepend_to_vec(&mut slf.restore_msg, &vec![String::new(); k]); - prepend_to_vec(&mut slf.archived_command_list, &vec![None; k]); - prepend_to_vec( - &mut slf.archive_name, - &vec![iced::text_input::State::default(); k], - ); - prepend_to_vec(&mut slf.archive_name_value, &vec![String::new(); k]); - prepend_to_vec( - &mut slf.archive_name_change_button_color, - &vec![Color::from_rgb(0.0, 0.0, 0.0); k], - ); - prepend_to_vec( - &mut slf.copy_archive_narrative_button_color, - &vec![Color::from_rgb(0.0, 0.0, 0.0); k], - ); - prepend_to_vec( - &mut slf.archive_name_change_button, - &vec![iced::button::State::default(); k], - ); - prepend_to_vec( - &mut slf.archive_narrative_button, - &vec![iced::button::State::default(); k], - ); - prepend_to_vec( - &mut slf.copy_archive_narrative_button, - &vec![iced::button::State::default(); k], - ); - prepend_to_vec(&mut slf.archive_share_requested, &vec![false; k]); - prepend_to_vec(&mut slf.archive_origin, &vec![String::new(); k]); - prepend_to_vec(&mut slf.archive_narrative, &vec![String::new(); k]); - - // Delete remote shares. - - RELEASE_MY_SHARES.store(true, SeqCst); - while RELEASE_MY_SHARES.load(SeqCst) { - thread::sleep(Duration::from_millis(10)); - } -} diff --git a/enclone_visual/src/snapshot.rs b/enclone_visual/src/snapshot.rs deleted file mode 100644 index a026375030..0000000000 --- a/enclone_visual/src/snapshot.rs +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2022 10x Genomics, Inc. All rights reserved. - -use crate::copy_image_to_clipboard::*; -use crate::{capture_as_file, get_window_id}; -use perf_stats::*; -use std::fs::{remove_file, File}; -use std::io::Read; -use std::time::{Duration, Instant}; -use std::{env, thread}; - -// Copy window image to clipboard. If the environment variable ENCLONE_VIS_SNAPSHOT is defined, -// also save to that file. This only works on a Mac. - -pub fn snapshot(start: &Option) { - let mut filename = "/tmp/enclone_visual_snapshot.png".to_string(); - let mut snapshot = false; - for (key, value) in env::vars() { - if key == "ENCLONE_VIS_SNAPSHOT" { - snapshot = true; - filename = value.to_string(); - } - } - capture_as_file(&filename, get_window_id()); - let mut bytes = Vec::::new(); - { - let mut f = File::open(&filename).unwrap(); - f.read_to_end(&mut bytes).unwrap(); - } - if !snapshot { - remove_file(&filename).unwrap(); - } - copy_png_bytes_to_clipboard(&bytes); - const MIN_SLEEP: f64 = 0.4; - let used = elapsed(&start.unwrap()); - if used < MIN_SLEEP { - let ms = ((MIN_SLEEP - used) * 1000.0).round() as u64; - thread::sleep(Duration::from_millis(ms)); - } -} - -/* - -Below, there is some code that will snapshot a window under Linux. However, it is dependent -on windows being managed by X, and most Linus distros now use Wayland, for which this won't -work. This was an experimental main program. - -extern crate libwmctl; -extern crate pretty_trace; -extern crate image; -extern crate x11; -extern crate libc; -extern crate string_utils; -extern crate arboard; -extern crate png_decoder; - -// pub mod util; -pub mod xwrap; - -use pretty_trace::*; - -use std::fs::File; -use std::path::Path; - -use std::process::Command; - -use x11::xlib; - -use crate::xwrap::Display; - -use string_utils::strme; -use string_utils::TextUtils; - -use std::io::Read; - -#[cfg(target_os = "linux")] -use arboard::{Clipboard, ImageData}; - -#[cfg(target_os = "linux")] -pub fn copy_png_bytes_to_clipboard(bytes: &[u8]) { - let (header, image_data) = png_decoder::decode(&bytes).unwrap(); - let (width, height) = (header.width as usize, header.height as usize); - let mut clipboard = Clipboard::new().unwrap(); - let img_data = ImageData { - width: width, - height: height, - bytes: image_data.into(), - }; - clipboard.set_image(img_data).unwrap(); -} - -fn main() { - PrettyTrace::new().on(); - - // Get the enclone visual window id. - - let mut window_id = String::new(); - let new = Command::new("wmctrl") - .arg("-l") - .output() - .unwrap_or_else(|_| { - eprintln!("\nThe executable wmctrl could not be found.\n"); - eprintln!("\nYou may need to install it via:\n\ - sudo apt install wmctrl\n" - ); - std::process::exit(1); - }); - if new.status.code() != Some(0) { - eprintln!("\nwmctrl -l failed\n"); - eprintln!("stderr = {}", strme(&new.stderr)); - std::process::exit(1); - } - let s = strme(&new.stdout); - for line in s.lines() { - if line.ends_with(" EncloneVisual") { - window_id = line.before(" ").to_string(); - } - } - if window_id == "" { - eprintln!("\nFailed to find enclone visual window. The output of wmctrl -l is:\n{}", s); - std::process::exit(1); - } - println!("window id = {}", window_id); - - // code taken from shotgun - - let display = match Display::open(None) { - Some(d) => d, - None => { - eprintln!("Failed to open display"); - std::process::exit(1); - } - }; - - let window = xwrap::util::parse_int::(&window_id).unwrap(); - - let output_format = image::ImageOutputFormat::Png; - - let window_rect = display.get_window_rect(window); - - let sel = - xwrap::util::Rect { - x: 0, - y: 0, - w: window_rect.w, - h: window_rect.h, - }; - - let image = match display.get_image(window, sel, xwrap::ALL_PLANES, xlib::ZPixmap) { - Some(i) => i, - None => { - eprintln!("Failed to get image from X"); - std::process::exit(1); - }, - }; - - let image = match image.into_image_buffer() { - Some(i) => image::DynamicImage::ImageRgba8(i), - None => { - eprintln!("Failed to convert captured framebuffer, only 24/32 \ - bit (A)RGB8 is supported"); - std::process::exit(1); - } - }; - - let filename = "/tmp/enclone_visual_snapshot.png"; - { - match File::create(&Path::new(&filename)) { - Ok(mut f) => image.write_to(&mut f, output_format).expect("Writing to file failed"), - Err(e) => { - eprintln!("Failed to create {}: {}", filename, e); - std::process::exit(1); - }, - } - } - let mut bytes = Vec::::new(); - { - let mut f = File::open(&filename).unwrap(); - f.read_to_end(&mut bytes).unwrap(); - } - std::fs::remove_file(&filename).unwrap(); - copy_png_bytes_to_clipboard(&bytes); -} - -*/ - -// Some code that works even less. This was supposed to be an alternative to using wmctrl. - -/* - -// Doesn't work: - -use libwmctl::prelude::*; -let wmctl = WmCtl::connect().unwrap(); -let (_, wm_name) = wmctl.winmgr().unwrap(); -let win = wmctl.active_win().unwrap(); -println!("X11 Information"); -println!("-----------------------------------------------------------------------"); -println!("Window Manager: {}", wm_name); -println!("Composite Manager: {}", wmctl.composite_manager().unwrap()); -println!("Root Window: {}", wmctl.root()); -println!("Work area: {}x{}", wmctl.work_width(), wmctl.work_height()); -println!("Screen Size: {}x{}", wmctl.width(), wmctl.height()); -println!("Desktops: {}", wmctl.desktops().unwrap()); -println!(); -println!("Active Window"); -println!("{:-<120}", ""); - -println!("{:<8} {:<3} {:<6} {:<5} {:<5} {:<4} {:<4} {:<8} {:<7} {:<18} {:<18} {}", "ID", "DSK", "PID", "X", "Y", "W", "H", "BORDERS", "TYPE", "STATE", "CLASS", "NAME"); - -let pid = wmctl.win_pid(win).unwrap_or(-1); -let desktop = wmctl.win_desktop(win).unwrap_or(-1); -let typ = wmctl.win_type(win).unwrap_or(WinType::Invalid); -let states = wmctl.win_state(win).unwrap_or(vec![WinState::Invalid]); -let (x, y, w, h) = wmctl.win_geometry(win).unwrap_or((0,0,0,0)); -let (l, r, t, b) = wmctl.win_borders(win).unwrap_or((0, 0, 0, 0)); -let class = wmctl.win_class(win).unwrap_or("".to_owned()); -let name = wmctl.win_name(win).unwrap_or("".to_owned()); -println!("{:<8} {:<3} {:<6} {:<5} {:<5} {:<4} {:<4} {:<8} {:<7} {:<18} {:<18} {}", - format!("{:0>8}", win), format!("{:>2}", desktop), pid, - format!("{:<4}", x), format!("{:<4}", y), format!("{:<4}", w), format!("{:<4}", h), - format!("{},{},{},{}", l, r, t, b), - typ.to_string(), format!("{:?}", states), class, name); - -*/ - -// Cargo.toml stuff relevant to the above: - -/* - -[dependencies] -string_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -getopts = "0.2" -libc = "0.2" -num-traits = "0.2" -libwmctl = "0.0" -pretty_trace = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -png-decoder = "0.1" - -[dependencies.image] -default-features = false -version = "0.23" -features = ["png", "pnm"] - -[dependencies.x11] -version = "2.18" -features = ["xlib", "xrandr"] - -[target.'cfg(target_os = "linux")'.dependencies] -arboard = "2" - -*/ diff --git a/enclone_visual/src/style.rs b/enclone_visual/src/style.rs deleted file mode 100644 index 9f6e14cf59..0000000000 --- a/enclone_visual/src/style.rs +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use iced::{button, Background}; - -// This file defines styles for some elements in the GUI. - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub struct ButtonBoxStyle1; - -impl button::StyleSheet for ButtonBoxStyle1 { - fn active(&self) -> button::Style { - button::Style { - background: Some(Background::Color(Color::from_rgb(0.8, 0.93, 0.9))), - border_radius: 3.0, - text_color: Color::WHITE, - ..button::Style::default() - } - } - - fn hovered(&self) -> button::Style { - button::Style { - background: Some(Background::Color(Color::from_rgb(0.8, 0.93, 0.9))), - text_color: Color::WHITE, - ..self.active() - } - } - - fn pressed(&self) -> button::Style { - button::Style { - border_width: 1.0, - border_color: Color::WHITE, - ..self.hovered() - } - } -} - -pub struct ButtonBoxStyle2; - -impl button::StyleSheet for ButtonBoxStyle2 { - fn active(&self) -> button::Style { - button::Style { - background: Some(Background::Color(Color::from_rgb(0.6, 0.73, 0.7))), - border_radius: 3.0, - text_color: Color::WHITE, - ..button::Style::default() - } - } - - fn hovered(&self) -> button::Style { - button::Style { - background: Some(Background::Color(Color::from_rgb(0.6, 0.73, 0.7))), - text_color: Color::WHITE, - ..self.active() - } - } - - fn pressed(&self) -> button::Style { - button::Style { - border_width: 1.0, - border_color: Color::WHITE, - ..self.hovered() - } - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub struct RuleStyle; - -impl iced::rule::StyleSheet for RuleStyle { - fn style(&self) -> iced::rule::Style { - iced::rule::Style { - color: Color::from_rgb(0.0, 1.0, 1.0), - width: 3, - radius: 1.0, - fill_mode: iced::rule::FillMode::Percent(100.0), - } - } -} - -pub struct RuleStyle2; - -impl iced::rule::StyleSheet for RuleStyle2 { - fn style(&self) -> iced::rule::Style { - iced::rule::Style { - color: Color::from_rgb(0.8, 0.7, 0.7), - width: 4, - radius: 1.0, - fill_mode: iced::rule::FillMode::Percent(100.0), - } - } -} - -pub struct ThinRuleStyle; - -impl iced::rule::StyleSheet for ThinRuleStyle { - fn style(&self) -> iced::rule::Style { - iced::rule::Style { - color: Color::from_rgb(1.0, 0.0, 1.0), - width: 1, - radius: 1.0, - fill_mode: iced::rule::FillMode::Percent(100.0), - } - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub struct ScrollableStyle; - -use iced::{scrollable, Color}; - -impl scrollable::StyleSheet for ScrollableStyle { - fn active(&self) -> scrollable::Scrollbar { - scrollable::Scrollbar { - background: Color::from_rgb(0.75, 0.75, 0.75).into(), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - } - } - - fn hovered(&self) -> scrollable::Scrollbar { - let active = self.active(); - scrollable::Scrollbar { - background: Color { - a: 0.5, - ..Color::from_rgb(0.0, 0.0, 0.0) - } - .into(), - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..active.scroller - }, - ..active - } - } - - fn dragging(&self) -> scrollable::Scrollbar { - let hovered = self.hovered(); - scrollable::Scrollbar { - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..hovered.scroller - }, - ..hovered - } - } -} diff --git a/enclone_visual/src/summary.rs b/enclone_visual/src/summary.rs deleted file mode 100644 index 89f0c65989..0000000000 --- a/enclone_visual/src/summary.rs +++ /dev/null @@ -1,906 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. - -use crate::gui_structures::*; -use crate::style::{ButtonBoxStyle1, ButtonBoxStyle2}; -use crate::*; -use enclone_core::stringulate::*; -use iced::Length::Units; -use iced::{Button, Color, Column, Container, Element, Length, Row, Rule, Scrollable, Space, Text}; -use itertools::{izip, Itertools}; -use messages::Message; -use vector_utils::*; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// This section contains the packing and unpacking of the summary. The main reason for packing -// various pieces of information into the summary was to avoid invalidating session files that -// people might have written. We could have done this by raising the output file version, but -// that would have been messy. -// -// There are actually two versions of the packing. The first existed for about a week. - -// pub fn pack_summary() -> String { -// let mut reply_summary = SERVER_REPLY_SUMMARY.lock().unwrap()[0].clone(); -// let n = SERVER_REPLY_DATASET_NAMES.lock().unwrap().len(); -// for i in 0..n { -// reply_summary += &mut format!("$$${}", SERVER_REPLY_DATASET_NAMES.lock().unwrap()[i]); -// } -// let n = SERVER_REPLY_METRICS.lock().unwrap().len(); -// for i in 0..n { -// reply_summary += &mut format!("###{}", SERVER_REPLY_METRICS.lock().unwrap()[i]); -// } -// reply_summary -// } - -pub fn unpack_summary(s: &str) -> Summary { - // Handle the case of the format that existed only briefly. This is flaky because it's - // conceivable that the string $$$ would appear in the second format. - - if s.contains("$$$") { - let mut dataset_names = Vec::::new(); - let mut metrics = Vec::>::new(); - let p1 = s.split("$$$").collect::>(); - let mut p1x = Vec::::new(); - for i in 0..p1.len() { - p1x.push(p1[i].to_string()); - } - let summary = p1x[0].to_string(); - for i in 1..p1x.len() { - if p1x[i].contains("###") { - dataset_names.push(p1x[i].before("###").to_string()); - let p2 = p1x[i].split("###").collect::>(); - for j in 1..p2.len() { - let mut lines = Vec::::new(); - for line in p2[j].lines() { - lines.push(line.to_string()); - } - metrics.push(lines); - } - } else { - dataset_names.push(p1x[i].to_string()); - } - } - let mut all_metric_names = Vec::::new(); - for i in 0..metrics.len() { - for j in 0..metrics[i].len() { - let s = parse_csv(&metrics[i][j]); - let m = format!("{},{}", s[0], s[1]); - all_metric_names.push(m); - } - } - unique_sort(&mut all_metric_names); - let nm = all_metric_names.len(); - Summary { - summary: summary, - dataset_names: dataset_names, - metrics: metrics, - metric_selected: vec![false; nm], - metrics_condensed: false, - } - - // Handle the current case. - } else { - Summary::unpack(&s) - } -} - -pub fn form_summary_from_server_response() -> Summary { - let summary = SERVER_REPLY_SUMMARY.lock().unwrap()[0].clone(); - let mut dataset_names = Vec::::new(); - let n = SERVER_REPLY_DATASET_NAMES.lock().unwrap().len(); - for i in 0..n { - dataset_names.push(SERVER_REPLY_DATASET_NAMES.lock().unwrap()[i].clone()); - } - let mut metrics = Vec::>::new(); - let n = SERVER_REPLY_METRICS.lock().unwrap().len(); - for i in 0..n { - let m = SERVER_REPLY_METRICS.lock().unwrap()[i].clone(); - let mut lines = Vec::::new(); - for line in m.lines() { - lines.push(line.to_string()); - } - metrics.push(lines); - } - let mut all_metric_names = Vec::::new(); - for i in 0..metrics.len() { - for j in 0..metrics[i].len() { - let s = parse_csv(&metrics[i][j]); - let m = format!("{},{}", s[0], s[1]); - all_metric_names.push(m); - } - } - unique_sort(&mut all_metric_names); - let nm = all_metric_names.len(); - Summary { - summary: summary, - dataset_names: dataset_names, - metrics: metrics, - metric_selected: vec![false; nm], - metrics_condensed: false, - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[derive(Clone, Default)] -pub struct Metric { - pub name: String, - pub values: Vec, -} - -pub fn get_metrics(metricsx: &Vec>, nd: usize) -> Vec { - let mut all_metric_names = Vec::::new(); - for i in 0..metricsx.len() { - for j in 0..metricsx[i].len() { - let s = parse_csv(&metricsx[i][j]); - let m = format!("{},{}", s[0], s[1]); - all_metric_names.push(m); - } - } - unique_sort(&mut all_metric_names); - let nm = all_metric_names.len(); - let mut values = vec![vec![String::new(); nd]; nm]; - for i in 0..nd { - for j in 0..metricsx[i].len() { - let s = parse_csv(&metricsx[i][j]); - let value = s[2].clone(); - let m = format!("{},{}", s[0], s[1]); - let p = bin_position(&all_metric_names, &m) as usize; - values[p][i] = value; - } - } - let mut metrics = vec![Metric::default(); nm]; - for i in 0..nm { - metrics[i] = Metric { - name: all_metric_names[i].clone(), - values: values[i].clone(), - } - } - metrics -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn expand_summary(summary: &str, all: bool, show: &Vec) -> String { - let summaryx = unpack_summary(&summary); - let mut summary = String::new(); - if all { - summary = summaryx.summary.clone(); - } - let n = summaryx.metrics.len(); - if n > 0 && n == summaryx.dataset_names.len() { - let dataset_names = summaryx.dataset_names.clone(); - let nd = dataset_names.len(); - let metricsx = summaryx.metrics.clone(); - let metrics = get_metrics(&metricsx, nd); - let nm = metrics.len(); - let mut categories = Vec::::new(); - for i in 0..nm { - categories.push(metrics[i].name.before(",").to_string()); - } - unique_sort(&mut categories); - for cat in categories.iter() { - let catc = format!("{},", cat); - let mut have_some = false; - for i in 0..nm { - if show[i] { - if metrics[i].name.starts_with(&catc) { - have_some = true; - } - } - } - if have_some { - let upcat = cat.to_ascii_uppercase(); - let mut rows = Vec::>::new(); - let mut row = vec!["metric".to_string()]; - row.append(&mut dataset_names.clone()); - rows.push(row); - for i in 0..nm { - if show[i] { - if metrics[i].name.starts_with(&catc) { - let mut row = vec![metrics[i].name.after(&catc).to_string()]; - for j in 0..nd { - row.push(metrics[i].values[j].clone()); - } - rows.push(vec!["\\hline".to_string(); nd + 1]); - rows.push(row); - } - } - } - let mut log = String::new(); - let mut just = vec![b'l']; - for _ in 0..nd { - just.push(b'|'); - just.push(b'r'); - } - print_tabular_vbox(&mut log, &rows, 0, &just, false, false); - summary += &mut format!("\n{} METRICS BY DATASET\n", upcat); - summary += &mut log; - } - } - } - summary -} - -pub fn expand_summary_as_csv(summary: &str, show: &Vec) -> String { - let summaryx = unpack_summary(&summary); - let mut summary = String::new(); - let n = summaryx.metrics.len(); - let mut first = true; - if n > 0 && n == summaryx.dataset_names.len() { - let dataset_names = summaryx.dataset_names.clone(); - let nd = dataset_names.len(); - let metricsx = summaryx.metrics.clone(); - let metrics = get_metrics(&metricsx, nd); - let nm = metrics.len(); - let mut categories = Vec::::new(); - for i in 0..nm { - categories.push(metrics[i].name.before(",").to_string()); - } - unique_sort(&mut categories); - for cat in categories.iter() { - let catc = format!("{},", cat); - let mut have_some = false; - for i in 0..nm { - if show[i] { - if metrics[i].name.starts_with(&catc) { - have_some = true; - } - } - } - if have_some { - let mut rows = Vec::>::new(); - if first { - let mut row = vec!["class".to_string(), "metric".to_string()]; - row.append(&mut dataset_names.clone()); - rows.push(row); - first = false; - } - for i in 0..nm { - if show[i] { - if metrics[i].name.starts_with(&catc) { - let mut row = - vec![cat.clone(), metrics[i].name.after(&catc).to_string()]; - for j in 0..nd { - let m = metrics[i].values[j].replace(",", ""); - row.push(m); - } - rows.push(row); - } - } - } - for i in 0..rows.len() { - summary += &mut format!("{}\n", rows[i].iter().format("\t ")); - } - } - } - } - summary -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -pub fn max_line_val(s: &str) -> usize { - let mut m = 0; - for line in s.lines() { - let mut nchars = 0; - for _ in line.chars() { - nchars += 1; - } - m = std::cmp::max(m, nchars); - } - m -} - -pub fn appropriate_font_size(s: &str, w: u32, max_size: usize) -> usize { - let mut font_size = 20; - let max_line = max_line_val(&s); - const FUDGE: f32 = 175.0; - let width = (max_line * font_size) as f32 * DEJAVU_WIDTH_OVER_HEIGHT + FUDGE; - let iwidth = width.ceil() as u32; - if iwidth > w { - let fs = w as f32 / width * (font_size as f32); - font_size = fs.floor() as usize; - } - if font_size > max_size { - font_size = max_size; - } - font_size -} - -pub fn summary(slf: &mut gui_structures::EncloneVisual) -> Element { - let width = (slf.width - 65) as u16; // for text, so scrollbar is not on top of text - let summary_title = Text::new(&format!("Summary")) - .font(LIBERATION_SANS) - .size(30); - - // Expand summary. - - let summaryx = unpack_summary(&slf.summary_value); - let summary = summaryx.summary.clone(); - let n = summaryx.metrics.len(); - - // Unpack the summary. For now we are assuming that it consists of one or two objects, - // because that's all we have implemented. - - let hets = unpack_to_het_string(&summary); - - // Determine initial font size. - - let mut sum = "The summary is empty. Usually this happens if the command failed.".to_string(); - if !hets.is_empty() { - sum = hets[0].content.clone(); - } - let mut max_line = max_line_val(&sum); - let mut font_size = appropriate_font_size(&sum, slf.width, 20); - const FUDGE: f32 = 175.0; - let orig_font_size = font_size; - - // Put first part of summary into a scrollable. - - let summary = format!("{}\n \n", sum); - let mut summary_scrollable = Scrollable::new(&mut slf.summary_scroll) - .width(Length::Fill) - .height(Length::Fill) - .scrollbar_width(SCROLLBAR_WIDTH) - .scroller_width(12) - .style(style::ScrollableStyle) - .push( - Text::new(&format!("{}", summary)) - .font(DEJAVU_BOLD) - .size(orig_font_size as u16), - ); - - // If there is a DescriptionTable, add that. - - let mut descrips = None; - for j in 1..hets.len() { - if hets[j].name == "DescriptionTable" { - descrips = Some(j); - } - } - if descrips.is_some() { - let j = descrips.unwrap(); - let table = DescriptionTable::from_string(&hets[j].content); - slf.descrips_for_spreadsheet = table.spreadsheet_text.clone(); - let tables_font_size = appropriate_font_size(&table.display_text, slf.width, 16); - summary_scrollable = summary_scrollable - .push(Space::with_height(Units(8))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(8))) - .push( - Text::new("Dataset descriptions") - .font(LIBERATION_SANS) - .size(25) - .color(Color::from_rgb(0.9, 0.0, 0.9)), - ) - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.descrips_copy_button, - Text::new("Copy") - .font(LIBERATION_SANS) - .color(slf.descrips_copy_button_color), - ) - .on_press(Message::CopyDescrips), - ) - .push(Space::with_height(Units(8))) - .push( - Text::new(&format!("{}", table.display_text)) - .font(DEJAVU_BOLD) - .size(tables_font_size as u16), - ); - } - - // If there is a FeatureBarcodeAlluvialReadsTableSet, add that. - - let mut alluv = None; - for j in 1..hets.len() { - if hets[j].name == "FeatureBarcodeAlluvialReadsTableSet" { - alluv = Some(j); - } - } - if alluv.is_some() { - let j = alluv.unwrap(); - let tables = FeatureBarcodeAlluvialReadsTableSet::from_string(&hets[j].content); - slf.alluvial_reads_tables_for_spreadsheet.clear(); - slf.alluvial_reads_tables_for_spreadsheet_cr.clear(); - slf.alluvial_reads_tables_for_spreadsheet_crd.clear(); - let mut tables_text = String::new(); - for i in 0..tables.s.len() { - if tables.s[i].display_text.len() == 0 { - continue; - } - tables_text += &mut format!( - "\nfeature barcode read distribution for {}\n{}", - tables.s[i].id, tables.s[i].display_text - ); - slf.alluvial_reads_tables_for_spreadsheet += &mut tables.s[i].spreadsheet_text.clone(); - let mut s = format!( - "{}\t {}\n", - tables.s[i].id, - tables.s[i].display_text.before(" reference").rev_after("│") - ); - slf.alluvial_reads_tables_for_spreadsheet_cr += &mut s; - let x = tables.s[i].display_text.before(" nonreference"); - let mut y: Vec = x.split('│').map(str::to_owned).collect(); - for j in 0..y.len() { - if y[j].contains("=") { - while y[j].starts_with(" ") { - y[j] = y[j].after(" ").to_string(); - } - while y[j].ends_with(" ") { - y[j] = y[j].rev_before(" ").to_string(); - } - let percent = y[j].before(" "); - let barcode = y[j].between(" ", " = "); - let id = y[j].after(" = "); - let mut s = - format!("{}\t {}\t {}\t {}\n", tables.s[i].id, percent, barcode, id); - slf.alluvial_reads_tables_for_spreadsheet_crd += &mut s; - } - } - } - tables_text += "\n \n"; - let tables_font_size = appropriate_font_size(&tables_text, slf.width, 16); - summary_scrollable = summary_scrollable - .push(Space::with_height(Units(8))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(8))) - .push( - Text::new("Feature barcode read count alluvial tables") - .font(LIBERATION_SANS) - .size(25) - .color(Color::from_rgb(0.9, 0.0, 0.9)), - ) - .push(Space::with_height(Units(8))); - if slf.alluvial_reads_doc_open { - summary_scrollable = summary_scrollable - .push( - Button::new( - &mut slf.close_alluvial_reads_doc_button, - Text::new("Hide documentation").font(LIBERATION_SANS), - ) - .on_press(Message::CloseAlluvialReadsDoc), - ) - .push(Space::with_height(Units(8))) - .push( - Text::new( - "For each dataset, we show a table that classifies its feature barcode \ - reads.\n\n\ - \ - These reads are classified as cellular, if their cell barcode was \ - identified as a cell by the Cell Ranger VDJ pipeline, else noncellular.\n\n\ - \ - Each of these categories is subdivided into:\n\ - • degenerate: R2 starts with at least ten Gs\n\ - • reference: nondegenerate + feature barcode is in the reference\n\ - • nonreference: otherwise.\n\n\ - \ - In the noncellular degenerate category, canonical reads are \ - those whose R1 contains CACATCTCCGAGCCCACGAGAC. This is the end of the \ - Illumina Nextera version of the R2 primer = \ - CTGTCTCTTATACACATCTCCGAGCCCACGAGAC. \ - If R1 contains the first ten bases = CACATCTCCG, and the read is not \ - canonical, we call it semicanonical.\n\n\ - \ - The number of barcodes shown can be controlled using the extra argument\n\ - FB_SHOW=k\n\ - where k is the maximum number of feature barcodes shown for reference (and \ - likewise for nonreference). The default value for k is 3.", - ) - .font(LIBERATION_SANS) - .width(Units(width)), - ) - .push(Space::with_height(Units(8))) - .push( - Text::new( - "All the tables can be copied at once, for inclusion in \ - a spreadsheet, by pushing the button below. This copies the numbers in the \ - last column, but not the numbers in the earlier columns.", - ) - .font(LIBERATION_SANS) - .width(Units(width)), - ); - } else { - summary_scrollable = summary_scrollable.push( - Button::new( - &mut slf.open_alluvial_reads_doc_button, - Text::new("Expand documentation").font(LIBERATION_SANS), - ) - .on_press(Message::OpenAlluvialReadsDoc), - ); - } - summary_scrollable = summary_scrollable - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.alluvial_reads_tables_copy_button, - Text::new("Copy") - .font(LIBERATION_SANS) - .color(slf.alluvial_reads_tables_copy_button_color), - ) - .on_press(Message::CopyAlluvialReadsTables), - ) - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.alluvial_reads_tables_cr_copy_button, - Text::new("Copy cellular reference info") - .font(LIBERATION_SANS) - .color(slf.alluvial_reads_tables_cr_copy_button_color), - ) - .on_press(Message::CopyAlluvialReadsTablesCR), - ) - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.alluvial_reads_tables_crd_copy_button, - Text::new("Copy cellular reference details") - .font(LIBERATION_SANS) - .color(slf.alluvial_reads_tables_crd_copy_button_color), - ) - .on_press(Message::CopyAlluvialReadsTablesCRD), - ) - .push(Space::with_height(Units(4))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(8))) - .push( - Text::new(&format!("{}", tables_text)) - .font(DEJAVU_BOLD) - .size(tables_font_size as u16), - ); - } - - // If there is a FeatureBarcodeAlluvialTableSet, add that. - - let mut alluv = None; - for j in 1..hets.len() { - if hets[j].name == "FeatureBarcodeAlluvialTableSet" { - alluv = Some(j); - } - } - if alluv.is_some() { - let j = alluv.unwrap(); - let tables = FeatureBarcodeAlluvialTableSet::from_string(&hets[j].content); - slf.alluvial_tables_for_spreadsheet.clear(); - slf.alluvial_tables_for_spreadsheet_cr.clear(); - slf.alluvial_tables_for_spreadsheet_crd.clear(); - let mut tables_text = String::new(); - for i in 0..tables.s.len() { - if tables.s[i].display_text.len() == 0 { - continue; - } - tables_text += &mut format!( - "\nfeature barcode UMI distribution for {}\n{}", - tables.s[i].id, tables.s[i].display_text - ); - slf.alluvial_tables_for_spreadsheet += &mut tables.s[i].spreadsheet_text.clone(); - let mut s = format!( - "{}\t {}\n", - tables.s[i].id, - tables.s[i].display_text.before(" reference").rev_after("│") - ); - slf.alluvial_tables_for_spreadsheet_cr += &mut s; - let x = tables.s[i].display_text.before(" nonreference"); - let mut y: Vec = x.split('│').map(str::to_owned).collect(); - for j in 0..y.len() { - if y[j].contains("=") { - while y[j].starts_with(" ") { - y[j] = y[j].after(" ").to_string(); - } - while y[j].ends_with(" ") { - y[j] = y[j].rev_before(" ").to_string(); - } - let percent = y[j].before(" "); - let barcode = y[j].between(" ", " = "); - let id = y[j].after(" = "); - let mut s = - format!("{}\t {}\t {}\t {}\n", tables.s[i].id, percent, barcode, id); - slf.alluvial_tables_for_spreadsheet_crd += &mut s; - } - } - } - tables_text += "\n \n"; - let tables_font_size = appropriate_font_size(&tables_text, slf.width, 20); - summary_scrollable = summary_scrollable - .push(Space::with_height(Units(8))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(8))) - .push( - Text::new("Feature barcode UMI count alluvial tables") -.font(LIBERATION_SANS) - .size(25) - .color(Color::from_rgb(0.9, 0.0, 0.9)), - ) - .push(Space::with_height(Units(8))) - .push(Text::new( - "These tables are similar to the tables for reads. See the documentation there. \ - UMIs for degenerate reads are not included in these tables. \ - Note that the FB_SHOW option can also be used here.\n\n\ - All the tables can be copied at once, in a form suitable for inclusion in \ - a spreadsheet, by pushing the button below. This copies the numbers in the \ - last column, but not the numbers in the earlier columns.", - ).font(LIBERATION_SANS)) - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.alluvial_tables_copy_button, - Text::new("Copy").font(LIBERATION_SANS).color(slf.alluvial_tables_copy_button_color), - ) - .on_press(Message::CopyAlluvialTables), - ) - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.alluvial_tables_cr_copy_button, - Text::new("Copy cellular reference info") -.font(LIBERATION_SANS) - .color(slf.alluvial_tables_cr_copy_button_color), - ) - .on_press(Message::CopyAlluvialTablesCR), - ) - .push(Space::with_height(Units(8))) - .push( - Button::new( - &mut slf.alluvial_tables_crd_copy_button, - Text::new("Copy cellular reference details") -.font(LIBERATION_SANS) - .color(slf.alluvial_tables_crd_copy_button_color), - ) - .on_press(Message::CopyAlluvialTablesCRD), - ) - .push(Space::with_height(Units(4))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(8))) - .push( - Text::new(&format!("{}", tables_text)) - .font(DEJAVU_BOLD) - .size(tables_font_size as u16), - ); - } - - // Suppose we have dataset level metrics. - - let mut button_text_row = Row::new(); - if n > 0 && n == summaryx.dataset_names.len() { - let dataset_names = summaryx.dataset_names.clone(); - let nd = dataset_names.len(); - let metricsx = summaryx.metrics.clone(); - let metrics = get_metrics(&metricsx, nd); - let nm = metrics.len(); - if slf.metric_button.len() != nm { - slf.metric_button = vec![iced::button::State::default(); nm]; - } - let mut categories = Vec::::new(); - for i in 0..nm { - categories.push(metrics[i].name.before(",").to_string()); - } - unique_sort(&mut categories); - - // Make text for metrics. - - let mut text = String::new(); - for cat in categories.iter() { - let mut have_some = false; - let catc = format!("{},", cat); - if !slf.metrics_condensed { - have_some = true; - } else { - for i in 0..nm { - if metrics[i].name.starts_with(&catc) { - if slf.metric_selected[i] { - have_some = true; - } - } - } - } - if have_some { - let upcat = cat.to_ascii_uppercase(); - let mut rows = Vec::>::new(); - let mut row = vec!["metric".to_string()]; - row.append(&mut dataset_names.clone()); - rows.push(row); - for i in 0..nm { - if metrics[i].name.starts_with(&catc) { - if slf.metrics_condensed && !slf.metric_selected[i] { - continue; - } - let mut row = vec![metrics[i].name.after(&catc).to_string()]; - for j in 0..nd { - row.push(metrics[i].values[j].clone()); - } - rows.push(vec!["\\hline".to_string(); nd + 1]); - rows.push(row); - } - } - let mut log = String::new(); - let mut just = vec![b'l']; - for _ in 0..nd { - just.push(b'|'); - just.push(b'r'); - } - print_tabular_vbox(&mut log, &rows, 0, &just, false, false); - text += &mut format!("\n{} METRICS BY DATASET\n", upcat); - text += &mut log; - } - } - text = format!("{}\n \n", text); - - // Update font size. - - for line in text.lines() { - let mut nchars = 0; - for _ in line.chars() { - nchars += 1; - } - max_line = std::cmp::max(max_line, nchars); - } - let width = (max_line * font_size) as f32 * DEJAVU_WIDTH_OVER_HEIGHT + FUDGE; - let iwidth = width.ceil() as u32; - if iwidth > slf.width { - let fs = slf.width as f32 / width * (font_size as f32); - font_size = fs.floor() as usize; - } - - // Make text column for metrics. - - let font_size = font_size as u16; - let text_column = Column::new().push(Text::new(&text).font(DEJAVU_BOLD).size(font_size)); - - // Make button column for metrics. - - let mut button_column = Column::new(); - for (i, y) in izip!(0..nm, slf.metric_button.iter_mut()) { - if i == 0 || metrics[i].name.before(",") != metrics[i - 1].name.before(",") { - button_column = button_column.push(Space::with_height(Units(4 * font_size))); - } - if i > 0 && metrics[i].name.before(",") != metrics[i - 1].name.before(",") { - button_column = button_column.push(Space::with_height(Units(font_size))); - } - let mut button = Button::new( - y, - Text::new("") - .font(LIBERATION_SANS) - .height(Units(font_size)) - .width(Units(font_size)), - ); - if !slf.metric_selected[i] { - button = button.style(ButtonBoxStyle1); - } else { - button = button.style(ButtonBoxStyle2); - } - button = button.padding(0).on_press(Message::MetricButton(i)); - button_column = button_column - .push(Space::with_height(Units(font_size))) - .push(button); - } - - // Put together buttons and text. - - if slf.metrics_condensed { - button_text_row = Row::new().push(text_column); - } else { - button_text_row = Row::new() - .push(button_column) - .push(Space::with_width(Units(font_size / 4))) - .push(text_column); - } - } - - // Build final structure. - - let _summary_snapshot_button = Button::new( - &mut slf.graphic_snapshot_button, - Text::new("Snapshot") - .font(LIBERATION_SANS) - .color(slf.summary_snapshot_button_color), - ) - .on_press(Message::SummarySnapshot); - let summary_copy_button = Button::new( - &mut slf.summary_copy_button, - Text::new("Copy") - .font(LIBERATION_SANS) - .color(slf.copy_summary_button_color), - ) - .on_press(Message::CopySummary); - let summary_close_button = Button::new( - &mut slf.summary_button, - Text::new("Dismiss").font(LIBERATION_SANS), - ) - .on_press(Message::SummaryClose(Ok(()))); - let mut top_bar = Row::new() - .push(summary_title) - .push(Space::with_width(Length::Fill)); - #[cfg(any(target_os = "macos", target_os = "ios"))] - { - top_bar = top_bar - .push(_summary_snapshot_button) - .push(Space::with_width(Units(8))); - } - top_bar = top_bar - .push(summary_copy_button) - .push(Space::with_width(Units(8))) - .push(summary_close_button); - let mut have_metrics = false; - for m in summaryx.metrics.iter() { - if m.len() > 0 { - have_metrics = true; - } - } - if have_metrics && n == summaryx.dataset_names.len() { - summary_scrollable = summary_scrollable - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(Space::with_height(Units(8))); - if !slf.metrics_condensed { - summary_scrollable = summary_scrollable - .push( - Text::new("Dataset level metrics") - .font(LIBERATION_SANS) - .size(25) - .color(Color::from_rgb(0.9, 0.0, 0.9)), - ) - .push(Space::with_height(Units(8))) - .push( - Text::new( - "Metrics below can be selectively displayed by clicking on boxes, \ - and then pushing the button below.", - ) - .font(LIBERATION_SANS), - ) - .push(Space::with_height(Units(4))) - .push( - Text::new( - "The display choices made here are \ - saveable, but cannot be recapitulated using an enclone command.", - ) - .font(LIBERATION_SANS), - ) - .push(Space::with_height(Units(4))) - .push( - Text::new( - "The copy selected metrics button may be used to copy the selected \ - metrics to the clipboard, in a form that can be pasted into a spreadsheet.", - ) - .font(LIBERATION_SANS), - ) - .push(Space::with_height(Units(12))); - } - let text = if slf.metrics_condensed { - "Show all metrics".to_string() - } else { - "Show selected metrics".to_string() - }; - summary_scrollable = summary_scrollable.push( - Button::new( - &mut slf.condense_metrics_button, - Text::new(&text).font(LIBERATION_SANS), - ) - .on_press(Message::CondenseMetrics), - ); - summary_scrollable = summary_scrollable.push(Space::with_height(Units(8))); - summary_scrollable = summary_scrollable.push( - Button::new( - &mut slf.copy_selected_metrics_button, - Text::new("Copy selected metrics") - .font(LIBERATION_SANS) - .color(slf.copy_selected_metrics_button_color), - ) - .on_press(Message::CopySelectedMetrics), - ); - summary_scrollable = summary_scrollable - .push(Space::with_height(Units(8))) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(button_text_row); - } - let content = Column::new() - .spacing(SPACING) - .padding(20) - .push(top_bar) - .push(Rule::horizontal(10).style(style::RuleStyle2)) - .push(summary_scrollable); - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .into() -} diff --git a/enclone_visual/src/svg_to_geometry.rs b/enclone_visual/src/svg_to_geometry.rs deleted file mode 100644 index 8fa2d69872..0000000000 --- a/enclone_visual/src/svg_to_geometry.rs +++ /dev/null @@ -1,566 +0,0 @@ -// Copyright (c) 2021 10x Genomics, Inc. All rights reserved. -// -// Attempt to convert an SVG object to geometries. This is possibly temporary. It is designed -// to work only with certain sorts of SVG objects. - -use crate::geometry::*; -use crate::svg_to_geometry::HorizontalAlignment::*; -use crate::*; -use enclone_core::parse_bsv; -use std::collections::HashMap; - -fn get_opacity(key: &str, value: &str, o: &mut u8) -> bool { - if key == "opacity" && value.parse::().is_ok() { - let v = value.parse::().unwrap(); - if v >= 0.0 && v <= 1.0 { - *o = (v * 255.0).round() as u8; - return true; - } else { - return false; - } - } - return false; -} - -fn numeric(x: &str) -> Option { - x.parse::().ok() -} - -fn get_numeric(key: &str, value: &str, var: &str, x: &mut Option) -> bool { - if key == var { - *x = numeric(&value); - x.is_some() - } else { - false - } -} - -fn dehex(h: &[u8]) -> Option { - let mut x = 0 as u8; - for p in 0..2 { - if h[p] >= b'0' && h[p] <= b'9' { - x += h[p] - b'0'; - } else if h[p] >= b'A' && h[p] <= b'Z' { - x += h[p] - b'A' + 10; - } else { - return None; - } - if p == 0 { - x *= 16; - } - } - Some(x) -} - -fn parse_color(x: &str, to_rgb: &HashMap) -> Option<(u8, u8, u8)> { - let (c1, c2, c3); - let y = x.replace(" ", "").to_lowercase(); - if x.starts_with("rgb(") && x.ends_with(")") { - let rgb = x - .after("rgb(") - .rev_before(")") - .split(',') - .collect::>(); - if rgb.len() != 3 { - return None; - } - c1 = rgb[0].parse::().ok(); - c2 = rgb[1].parse::().ok(); - c3 = rgb[2].parse::().ok(); - } else if to_rgb.contains_key(&y) { - let b = to_rgb[&y].as_bytes(); - c1 = dehex(&b[1..=2]); - c2 = dehex(&b[3..=4]); - c3 = dehex(&b[5..=6]); - } else { - let b = x.as_bytes(); - if b.len() == 7 && b[0] == b'#' { - c1 = dehex(&b[1..=2]); - c2 = dehex(&b[3..=4]); - c3 = dehex(&b[5..=6]); - } else { - return None; - } - } - if c1.is_some() && c2.is_some() && c3.is_some() { - Some((c1.unwrap(), c2.unwrap(), c3.unwrap())) - } else { - None - } -} - -fn parse_kv(line: &str) -> Option> { - let mut kv = Vec::<(String, String)>::new(); - let fields = parse_bsv(&line); - for j in 0..fields.len() { - if !fields[j].contains("=") { - return None; - } - let key = fields[j].before("="); - let mut value = fields[j].after("=").to_string(); - if !value.starts_with('"') || !value.ends_with('"') { - return None; - } - value = value.after("\"").rev_before("\"").to_string(); - if key == "style" { - let vals = value.split(';').collect::>(); - for k in 0..vals.len() { - if !vals[k].contains(":") { - return None; - } - let key = vals[k].before(":"); - let value = vals[k].after(":").to_string(); - kv.push((key.to_string(), value.to_string())); - } - } else { - kv.push((key.to_string(), value.to_string())); - } - } - Some(kv) -} - -fn parse_kv_term(line: &str) -> Option> { - let mut line = line.to_string(); - if line.ends_with(" />") { - line = line.before(" />").to_string(); - } else if line.ends_with("/>") { - line = line.before("/>").to_string(); - } else { - return None; - } - // xprintln!("calling parse_kv"); // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - parse_kv(&line) -} - -pub fn svg_to_geometry(svg: &str, verbose: bool) -> Option> { - // - // Get color list. - - let mut to_rgb = HashMap::::new(); - { - let colors = include_str!["colors"]; - for line in colors.lines() { - if !line.starts_with('#') { - let (color, rgb) = (line.before(" "), line.after(" ")); - to_rgb.insert(color.to_string(), rgb.to_string()); - } - } - } - - // Divide svg into lines of the form <...>, or something between such. - - let mut lines = Vec::::new(); - { - let mut line = String::new(); - let (mut lt, mut gt) = (0, 0); - for char in svg.chars() { - if lt == gt && char == '<' { - if line == "\n" { - line.clear(); - } else if line.len() > 0 { - if verbose { - xprintln!("pushing line = {}", line); - } - lines.push(line.clone()); - line.clear(); - } - } - line.push(char); - if char == '<' { - lt += 1; - } else if char == '>' { - gt += 1; - } - if lt == gt && line.contains('>') { - if line != "\n" { - if verbose { - xprintln!("pushing line = {}", line); - } - lines.push(line.clone()); - } - line.clear(); - } - } - if line.ends_with('\n') { - line.truncate(line.len() - 1); - } - while line.ends_with(' ') { - line.truncate(line.len() - 1); - } - if line.len() > 0 && line != "\n" { - if verbose { - xprintln!("residual line = {} = ${}$", line.len(), line); - } - return None; - } - } - - // Repackage lines into known svg entities. - - let mut geom = Vec::::new(); - let mut i = 0; - while i < lines.len() { - let mut line = lines[i].clone(); - if verbose { - xprintln!("\nline = {} = ${}$", lines[i].len(), lines[i]); - } - i += 1; - if line == "" { - break; - } - - // Process defs. We ignore them. - - if line == "" { - while i < lines.len() && lines[i] != "" { - i += 1; - } - i += 1; - continue; - } - - // Keep going. - - if !line.contains(' ') { - return None; - } - let tag = line.between("<", " ").to_string(); - if tag == "svg" { - continue; - } - line = line.after(" ").to_string(); - if verbose { - xprintln!("tag = {}", tag); - } - /* - if i < lines.len() { - xprintln!("lines[i] = {}", lines[i]); - } // XXXXXXXXXXXXXXXXXXXXXXXXXXXX - if i + 1 < lines.len() { - xprintln!("lines[i+1] = {}", lines[i + 1]); - } // XXXXXXXXXXXXXXXXXXXXXX - */ - - // Process circle. - - if tag == "circle" { - if verbose { - xprintln!("processing circle"); - } - let kv = parse_kv_term(&line); - if kv.is_none() { - return None; - } - let (mut x, mut y, mut r) = (None, None, None); - let mut c = None; - let mut o = 255 as u8; // opacity - let mut t = String::new(); - let mut stroke_width = None; - let mut sc = None; - for m in kv.unwrap().iter() { - let key = &m.0; - let value = &m.1; - if verbose { - xprintln!("key = {}, value = {}", key, value); - } - if key == "stroke" { - sc = parse_color(&value, &to_rgb); - } else if get_numeric(&key, &value, "stroke-width", &mut stroke_width) { - } else if key == "tooltip" { - t = value.to_string(); - } else if get_numeric(&key, &value, "cx", &mut x) { - } else if get_numeric(&key, &value, "cy", &mut y) { - } else if get_numeric(&key, &value, "r", &mut r) { - } else if key == "fill" { - c = parse_color(&value, &to_rgb); - } else if get_opacity(&key, &value, &mut o) { - } else { - return None; - } - } - if x.is_none() || y.is_none() || r.is_none() || c.is_none() { - return None; - } - if t.len() == 0 && sc.is_none() { - geom.push(Geometry::Circle(Circle { - p: Point::new(x.unwrap(), y.unwrap()), - r: r.unwrap(), - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - })); - } else if t.len() == 0 { - geom.push(Geometry::CircleWithStroke(CircleWithStroke { - p: Point::new(x.unwrap(), y.unwrap()), - r: r.unwrap(), - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - w: stroke_width.unwrap(), - // note probably wrong reuse of opacity - s: Color::new(sc.unwrap().0, sc.unwrap().1, sc.unwrap().2, o), - })); - } else if stroke_width.is_none() { - geom.push(Geometry::CircleWithTooltip(CircleWithTooltip { - p: Point::new(x.unwrap(), y.unwrap()), - r: r.unwrap(), - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - t: t, - })); - } else { - geom.push(Geometry::CircleWithTooltipAndStroke( - CircleWithTooltipAndStroke { - p: Point::new(x.unwrap(), y.unwrap()), - r: r.unwrap(), - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - t: t, - w: stroke_width.unwrap(), - // note probably wrong reuse of opacity - s: Color::new(sc.unwrap().0, sc.unwrap().1, sc.unwrap().2, o), - }, - )); - } - - // Process line. - } else if tag == "line" { - let kv = parse_kv_term(&line); - if kv.is_none() { - return None; - } - let (mut x1, mut y1, mut x2, mut y2) = (None, None, None, None); - let mut c = None; - let mut o = 255; - let mut stroke_width = None; - for m in kv.unwrap().iter() { - let key = &m.0; - let value = &m.1; - if get_numeric(&key, &value, "x1", &mut x1) { - } else if get_numeric(&key, &value, "y1", &mut y1) { - } else if get_numeric(&key, &value, "x2", &mut x2) { - } else if get_numeric(&key, &value, "y2", &mut y2) { - } else if key == "stroke" { - c = parse_color(&value, &to_rgb); - } else if key == "stroke-width" { - stroke_width = value.parse::().ok(); - } else if get_opacity(&key, &value, &mut o) { - } else { - return None; - } - } - if x1.is_none() || x2.is_none() || x2.is_none() || y2.is_none() { - return None; - } else if c.is_none() || stroke_width.is_none() { - return None; - } - geom.push(Geometry::Segment(Segment { - p1: Point::new(x1.unwrap(), y1.unwrap()), - p2: Point::new(x2.unwrap(), y2.unwrap()), - w: stroke_width.unwrap(), - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - })); - - // Process polyline. - } else if tag == "polyline" { - let kv = parse_kv_term(&line); - if kv.is_none() { - return None; - } - let mut p = Option::>::default(); - let mut c = None; - let mut o = 255; - let mut stroke_width = None; - for m in kv.unwrap().iter() { - let key = &m.0; - let mut value = m.1.clone(); - if verbose { - xprintln!("key = {}, value = {}", key, value); - } - if key == "points" { - if value.ends_with(' ') { - value = value.rev_before(" ").to_string(); - } - let mut points = Vec::::new(); - let ps = value.split(' ').collect::>(); - for x in ps.iter() { - let z = x.split(',').collect::>(); - if z.len() != 2 { - return None; - } - let mut p = vec![0.0; 2]; - for j in 0..z.len() { - if z[j].parse::().is_err() { - return None; - } else { - p[j] = z[j].parse::().unwrap(); - } - } - points.push(Point { x: p[0], y: p[1] }); - } - p = Some(points); - } else if key == "fill" { - } else if key == "stroke" { - c = parse_color(&value, &to_rgb); - } else if key == "stroke-width" { - stroke_width = value.parse::().ok(); - } else if get_opacity(&key, &value, &mut o) { - } else { - return None; - } - } - if verbose { - xprintln!("testing prereqs"); - } - if p.is_none() || c.is_none() || stroke_width.is_none() { - return None; - } - geom.push(Geometry::PolySegment(PolySegment { - p: p.unwrap(), - w: stroke_width.unwrap(), - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - })); - - // Process rectangle. - } else if tag == "rect" { - let kv = parse_kv_term(&line); - if kv.is_none() { - return None; - } - let (mut x, mut y, mut width, mut height) = (None, None, None, None); - let (mut fill_color, mut stroke_color) = (None, None); - let mut stroke_width = None; - for m in kv.unwrap().iter() { - let key = &m.0; - let value = &m.1; - if get_numeric(&key, &value, "x", &mut x) { - } else if get_numeric(&key, &value, "y", &mut y) { - } else if get_numeric(&key, &value, "width", &mut width) { - } else if get_numeric(&key, &value, "y", &mut y) { - } else if get_numeric(&key, &value, "width", &mut width) { - } else if get_numeric(&key, &value, "height", &mut height) { - } else if key == "fill" { - fill_color = parse_color(&value, &to_rgb); - } else if key == "stroke" { - stroke_color = parse_color(&value, &to_rgb); - } else if key == "stroke-width" { - stroke_width = value.parse::().ok(); - } else { - return None; - } - } - if x.is_none() || y.is_none() || width.is_none() || height.is_none() { - return None; - } - if stroke_width.is_none() ^ stroke_color.is_none() { - return None; - } - if fill_color.is_none() { - return None; - } - if stroke_width.is_none() { - geom.push(Geometry::Rectangle(Rectangle { - p: Point::new(x.unwrap(), y.unwrap()), - width: width.unwrap(), - height: height.unwrap(), - fill_color: Color::from_tuple_plus(fill_color.unwrap(), 255), - stroke_width: 0.0, - stroke_color: Color::new(0, 0, 0, 0), - })); - } else { - geom.push(Geometry::Rectangle(Rectangle { - p: Point::new(x.unwrap(), y.unwrap()), - width: width.unwrap(), - height: height.unwrap(), - fill_color: Color::from_tuple_plus(fill_color.unwrap(), 255), - stroke_width: stroke_width.unwrap(), - stroke_color: Color::from_tuple_plus(stroke_color.unwrap(), 255), - })); - } - - // Process text. - } else if tag == "text" && i + 1 < lines.len() && lines[i + 1] == "" { - if verbose { - xprintln!("processing text"); - } - let text = lines[i].to_string(); - if verbose { - xprintln!("text content = {}", text); - } - let mut font = "Arial".to_string(); - let mut font_size = None; - let (mut x, mut y) = (None, None); - let mut c = Some((0, 0, 0)); - let mut o = 255; - let mut text_anchor = "start".to_string(); - let mut rotate = [0.0; 3]; - i += 2; - if verbose { - xprintln!("calling parse_kv on line {}", line); - } - let kv = parse_kv(&line.rev_before(">")); - if kv.is_none() { - return None; - } - for m in kv.unwrap().iter() { - let key = &m.0; - let value = &m.1; - if verbose { - xprintln!("key = {}, value = {}", key, value); - } - if get_numeric(&key, &value, "x", &mut x) { - } else if get_numeric(&key, &value, "y", &mut y) { - } else if get_numeric(&key, &value, "font-size", &mut font_size) { - } else if key == "dx" || key == "dy" { - } else if key == "font-family" && (value == "arial" || value == "Arial") { - } else if key == "font-family" && value == "DejaVu LGC Sans Mono" { - font = "DejaVuSansMono".to_string(); - } else if key == "fill" { - c = parse_color(&value, &to_rgb); - } else if get_opacity(&key, &value, &mut o) { - } else if key == "text-anchor" && value == "start" { - text_anchor = "start".to_string(); - } else if key == "text-anchor" && value == "middle" { - text_anchor = "middle".to_string(); - } else if key == "text-anchor" && value == "end" { - text_anchor = "end".to_string(); - } else if key == "transform" && value.starts_with("rotate(") && value.ends_with(")") - { - let mut r = value.after("rotate(").rev_before(")").to_string(); - r = r.replace(" ", ""); - let z = r.split(',').collect::>(); - if z.len() == 3 { - for j in 0..3 { - let v = z[j].parse::(); - if !v.is_ok() { - return None; - } - rotate[j] = v.unwrap(); - } - } else { - return None; - } - } else { - return None; - } - } - if font_size.is_none() || x.is_none() || y.is_none() { - return None; - } - let halign; - if text_anchor == "start" { - halign = Left; - } else if text_anchor == "middle" { - halign = Center; - } else { - halign = Right; - } - geom.push(Geometry::Text(Text { - p: Point::new(x.unwrap(), y.unwrap()), - halign: halign, - c: Color::new(c.unwrap().0, c.unwrap().1, c.unwrap().2, o), - t: text, - font: font, - font_size: font_size.unwrap(), - rotate: rotate, - })); - } else { - return None; - } - } - Some(geom) -} diff --git a/enclone_visual/src/testsuite.rs b/enclone_visual/src/testsuite.rs deleted file mode 100644 index c9d876bbfc..0000000000 --- a/enclone_visual/src/testsuite.rs +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Automated and manual tests. - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// AUTOMATED TESTS -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// These are executed by bin/test_vis. - -use crate::messages::*; -use crate::*; -use std::env; - -#[rustfmt::skip] -pub fn metatests() -> Vec> { - let mut user = String::new(); - for (key, value) in env::vars() { - if key == "USER" { - user = value.to_string(); - } - } - vec![ - // 1 = enclone VIS - vec![ - Message::ArchiveOpen(Ok(())), - Message::ExpandArchiveEntry(true, 0), - Message::SetName("expand"), // test pushing expand button once - Message::ExpandArchiveEntry(false, 0), - Message::SetName("unexpand"), // test pushing expand button second time - Message::DeleteArchiveEntry(true, 0), - Message::SetName("delete1"), // see if delete message shows up - Message::ArchiveClose, - Message::ArchiveOpen(Ok(())), - Message::SetName("delete2"), // see if deletion occurred - Message::Restore(true, 1), - Message::SetName("restore1"), // see if restore message shows up - Message::ArchiveClose, - Message::SetName("restore2"), // see if restore occurs - Message::ArchiveOpen(Ok(())), - Message::ArchiveName("honeycomb".to_string(), 1), - Message::ArchiveNameChange(1), - Message::CompleteArchiveNameChange(Ok(())), - Message::ArchiveClose, - Message::ArchiveOpen(Ok(())), - Message::SetName("rename"), // see if rename occurs - ], - // 2 = enclone VIS=b - vec![ - Message::ArchiveOpen(Ok(())), - Message::ArchiveShare(true, 0), - Message::UserName(user, 0), - Message::UserSelected(true, 0), - Message::DoShare(true), - Message::CompleteDoShare(Ok(())), - Message::ArchiveRefresh, - Message::ArchiveRefreshComplete(Ok(())), - Message::ExpandArchiveEntry(true, 0), - Message::SetName("share"), // test share - ], - // 3 = enclone VIS FAIL_ON_ERROR - vec![ - Message::ArchiveOpen(Ok(())), - Message::RestoreCookbook(true, 0), - Message::ArchiveClose, - Message::SubmitButtonPressed(Ok(())), - Message::WaitCommand(Ok(())), - ], - // 4 = enclone VIS - vec![ - Message::InputChanged1("enclone PRE=~/enclone/datasets BCR_GEX=tiny_multi_PD SUMMARY_CLEAN".to_string()), - Message::SubmitButtonPressed(Ok(())), - Message::WaitCommand(Ok(())), - Message::SummaryOpen(Ok(())), - Message::SetName("metrics"), - Message::MetricButton(2), - Message::MetricButton(3), - Message::CondenseMetrics, - Message::SetName("metrics"), // this is totally flaky - Message::SetName("select_metrics"), - Message::SummaryClose(Ok(())), - Message::Save, - Message::ArchiveOpen(Ok(())), - Message::Restore(true, 0), - Message::ArchiveClose, - Message::SummaryOpen(Ok(())), - Message::SetName("restore_metrics"), - ], - // 5 = enclone VIS - vec![ - - Message::InputChanged1( - "enclone BCR=123085 GEX=123217 HONEY=out=gui,color=var,IGHV3-7_g_cell" - .to_string() - ), - Message::SubmitButtonPressed(Ok(())), - Message::SetName("color_by_var"), - - Message::InputChanged1( - "enclone BCR=85333 HONEY=out=gui,color=var,u_cell1,,minmax,0,10" - .to_string() - ), - Message::SubmitButtonPressed(Ok(())), - Message::SetName("trunc"), - - Message::InputChanged1( - "enclone BCR=85333 HONEY=out=gui,color=var,u_cell1,legend=none" - .to_string() - ), - Message::SubmitButtonPressed(Ok(())), - Message::SetName("no_legend"), - - Message::InputChanged1( - "enclone BCR=85333 HONEY=out=gui,color=var,u1:u_cell1" - .to_string() - ), - Message::SubmitButtonPressed(Ok(())), - Message::SetName("abbr"), - ], - // 6 = enclone VIS - vec![ - - Message::InputChanged1("enclone BCR=testset_bcr_micro GEX=testset_gex_micro".to_string()), - Message::SubmitButtonPressed(Ok(())), - Message::SetSummaryScrollablePos(1.0), - Message::SummaryOpen(Ok(())), - Message::SetName("alluvial_tables"), - ], - - ] -} - -const SUBMIT: fn(Result<(), std::string::String>) -> messages::Message = - Message::SubmitButtonPressed as MsgFn; - -const BACK: fn(Result<(), std::string::String>) -> messages::Message = - Message::BackButtonPressed as MsgFn; - -const FORWARD: fn(Result<(), std::string::String>) -> messages::Message = - Message::ForwardButtonPressed as MsgFn; - -const DEL: fn(Result<(), std::string::String>) -> messages::Message = - Message::DelButtonPressed as MsgFn; - -const HELP1: fn(Result<(), std::string::String>) -> messages::Message = Message::HelpOpen as MsgFn; -const HELP2: fn(Result<(), std::string::String>) -> messages::Message = Message::HelpClose as MsgFn; - -const SUMMARY1: fn(Result<(), std::string::String>) -> messages::Message = - Message::SummaryOpen as MsgFn; -const SUMMARY2: fn(Result<(), std::string::String>) -> messages::Message = - Message::SummaryClose as MsgFn; - -const ARCH1: fn(Result<(), std::string::String>) -> messages::Message = - Message::ArchiveOpen as MsgFn; - -const X0: &str = "enclone woof"; -const X1: &str = "enclone BCR=123085 PLOT=gui MIN_CELLS=5 G=12"; -const X2: &str = "enclone BCR=123085 CHAINS=4 PLOT_BY_ISOTYPE=gui"; -const X3: &str = "enclone + BCR=123085 NOPRINT"; -const X4: &str = "enclone BCR=123085 CHAINS=10"; -const X5: &str = "enclone BCR=123085 KEEP_CLONO_IF_CELL_MAX=\"u1 >= 6000\" SEG=IGHM"; -const X6: &str = "enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX \ - SIM_MAT_PLOT=gui,fb1_n,fb2_n,fb3_n,fb4_n,fb5_n SUMMARY_CLEAN"; -const N1: &str = "enclone BCR=123085 PLOT=gui MIN_CELLS=5"; -const N2: &str = "enclone BCR=123085 PLOT_BY_ISOTYPE=gui MIN_CELLS=5"; -const N3: &str = "enclone BCR=123085 GEX=123217 PLOTXY_EXACT=HLA-A_g,CD74_g,gui"; -const N4: &str = "enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX"; -const N5: &str = - "enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX LVARSP=fb1,fb1_n,fb2,fb2_n"; - -// This block of tests is good because it tests a lot, but bad because one can't test parts of it. -// For future tests, it would be better to have smaller chunks, as in the earlier tests. Except -// that, there is some startup cost, so we don't want the chunks to be too small. - -#[rustfmt::skip] -pub const TESTS: [(&str, MsgFn, &str); 40] = [ - (X0, SUBMIT, ""), // enclone woof - (N1, SUBMIT, "test1"), // enclone BCR=123085 PLOT=gui MIN_CELLS=5 - ("#999", SUBMIT, "test1a"), // #999 - ("", DEL, ""), // enclone BCR=123085 PLOT=gui MIN_CELLS=5 - ("", BACK, ""), // enclone woof - ("", FORWARD, ""), // #1 - ("10", SUBMIT, "test1b"), // 10 - ("", BACK, ""), // #1 - ("", FORWARD, "test1x"), // 10 - (X1, SUBMIT, "test1c"), // enclone BCR=123085 PLOT=gui MIN_CELLS=5 G=12 - (X2, SUBMIT, "test1d"), // enclone BCR=123085 CHAINS=4 PLOT_BY_ISOTYPE=gui - (N2, SUBMIT, "test2"), // enclone BCR=123085 PLOT_BY_ISOTYPE=gui MIN_CELLS=5 - (N3, SUBMIT, "test3"), // enclone BCR=123085 GEX=123217 PLOTXY_EXACT=HLA-A_g,CD74_g,gui - ("", BACK, "test4"), // #2 - ("", FORWARD, "test5"), // #3 - (N4, SUBMIT, "test6"), // enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX - ("1", SUBMIT, "test7"), // 1 - ("", BACK, "test8"), // #4 - ("", BACK, "test9"), // #3 - ("10", SUBMIT, "test10"), // 10 - ("", DEL, "test11"), // #3 - ("", BACK, ""), // #2 - ("", DEL, ""), // X2 = ... - ("", DEL, ""), // X1 = ... - ("", DEL, ""), // 10 - ("", DEL, ""), // #1 - ("", DEL, ""), // X0 = ... - ("", DEL, "test12"), // #3 - (X3, SUBMIT, ""), // enclone + BCR=123085 NOPRINT - ("5", SUBMIT, ""), // 5 - ("", BACK, "test13"), // enclone + BCR=123085 NOPRINT - (X4, SUBMIT, "test14"), // enclone BCR=123085 CHAINS=10 - (X5, SUBMIT, "test15"), // enclone BCR=123085 KEEP_CLONO_IF_CELL_MAX="u1 >= 6000" SEG=IGHM - (N5, SUBMIT, "test16"), // enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT - // NGEX LVARSP=fb1,fb1_n,fb2,fb2_n - (X6, SUBMIT, "test17"), // enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX - // SIM_MAT_PLOT=gui,fb1_n,fb2_n,fb3_n,fb4_n,fb5_n - // SUMMARY_CLEAN - ("", HELP1, "test18"), // (help) - ("", HELP2, ""), // enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX - // SIM_MAT_PLOT=gui,fb1_n,fb2_n,fb3_n,fb4_n,fb5_n - // SUMMARY_CLEAN - ("", SUMMARY1, "test19"), // (summary) - ("", SUMMARY2, ""), // enclone BCR=testset_bcr_micro GEX=testset_gex_micro ALLOW_INCONSISTENT NGEX - // SIM_MAT_PLOT=gui,fb1_n,fb2_n,fb3_n,fb4_n,fb5_n - // SUMMARY_CLEAN - ("", ARCH1, "test20"), // (archive) -]; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// MANUAL TESTS -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// 1. enclone VIS=b -// (a) Type #1 and then manually scroll up/down for two minutes. Should not slow down or crash. -// (b) Scroll to the bottom and make sure the last clonotype is not truncated. -// (c) Check that group number 0 and too large give errors. -// (d) Check that group number 1 is the right clonotype. -// (e) Try to cut and paste from clonotype tables [BROKEN]. -// (f) Test that copy image button flashes and that it actually copies. -// (g) enclone BCR=1096354 MIN_CELLS=5 PLOT_BY_ISOTYPE=gui -// check tooltip functionality and group clicks -// (h) enclone BCR=123085:123089 PLOT="gui,s1->red,s2->blue" LEGEND=red,"f 085",blue,"f 089" -// check tooltip functionality and group clicks -// -// 2. Repeat ten times: -// (a) type enclone VIS -// (b) type #1 -// (c) make sure it says "thinking" briefly and produces output -// (d) exit. -// -// 3. enclone VIS and type Help, Dismiss, Help, Dismiss, Help, Dismiss. Do these respond instantly? -// -// 4. enclone VIS=b -// - enclone TCR=1146724-1146731,1146751-1146758 PLOT=gui -// - this is a large dataset, so the canvas is huge -// - make sure scrolling is smooth and that tooltip responds essentially instantly -// -// 5. test that horizontal resizing works on enclone BCR=123085 CHAINS=4 -// and test that there is no limit on horizontal resizing diff --git a/enclone_visual/src/todo b/enclone_visual/src/todo deleted file mode 100644 index 9e9395dcc3..0000000000 --- a/enclone_visual/src/todo +++ /dev/null @@ -1,95 +0,0 @@ -TO DO - -1. Improve data shown for tooltip. - -2. Trim features and duplicated crates; reduce binary size. - -3. What do we do about the truncation of printing to fifty clonotypes? - -4. Make code work for 2 or more SVG files. - -5. Fix the close button on the upper left. - -6. Eliminate the 9.2 second delay on the Mac. This is sometimes observed, even when connected - to the internet. Also should we codesign enclone for the Mac? - -7. Diagnose memory leak. - -8. Use of help and cookbook and perhaps other buttons is flaky, as they reuse button stats. - Probably should fix. - ---------------------------------------------------------------------------------------------------- - -WAITING ON ICED - -1. Can't cut and paste text from the GUI window, except for the text input box. - This is https:github.com/hecrj/iced/issues/36. - -2. Pretty, not plain. - Enabling e.g. multicolor text is on the iced roadmap. - See https://github.com/iced-rs/iced/issues/156. - -3. Place the scrollbar on the left side of the scrollable window. - Asked on zulip chat if this is possible, but did not get a response. This is far enough - down our list of requests that I don't want to ask further now. - -4. Make the TextInput gracefully handle long inputs. - This is https:github.com/hecrj/iced/issues/320. Fix targetted for 1.0. - -5. Flaky behavior scrolling large texts. - Issue filed: https:github.com/hecrj/iced/issues/897. - -6. Canvas in scrollable crashes. So we can't put plots in a scrollable window. - Reported as issue #924, flagged as bug. - -7. Rotation of text is not yet supported, so xy plots cannot be converted to canvas, so they - can't have tooltips. - ---------------------------------------------------------------------------------------------------- - -NICE TO HAVE - -1. Add font size slider for clonotype tables. - -2. Can carriage return be used instead of pushing a button? - -3. Bold some text on the help page. - Probably not possible at this time, could ask on zulip chat. - -4. Use native ssh calls rather than ssh commands, as this might be faster and more robust. - -5. Add scale slider for plots, and/or zooming. - -6. Make "enclone help ..." work. - -7. Improve rendering of enclone TCR=1146724-1146731,1146751-1146758 PLOT=gui. The image - exhibits weird fluctuations in darkness. - -8. Profile and optimize, including on large datasets. Addition of last_widths seemed to slow - things down, and gzipped representation of tables is crappy because it doesn't allow access - to individual elements without unzipping everything. - -9. Possibly remove the window top bar, since the red exit button is broken anyway. There is - a thing platform_specific.title_hidden in iced, but it's not clear how to use it. This seems - to have something to do with using cfg! macros. - -10. Clean up hist_uniq vectors after each del operation to avoid wasting memory. - -11. Make sure layout is optimized for top/bottom balance and efficient space usage, including when - the window is changed in size. An example where suboptimal space usage can be seen is - enclone BCR=123085:123089 HONEY=out=gui,color=var,u_cell2 SPLIT_PLOT_BY_ORIGIN MIN_CELLS=5 - including as one shrinks the window vertically. - -12. Make horizontal rules in scrollables less wide so they don't overlap the scrollbar, which - seems ugly. - -13. The copy image button yields low quality. Inspection of the PNG shows that the DPI is 72, - regardless of the value given for DPI. Filed issue #451 for resvg crate. Note that - screen capture gives 144 DPI, and the screen capture images are much better. Note that one - can increase quality for resvg e.g. - cargo run --release -- --width 8000 --background white ~/plot.svg ~/plot.png - but that results in a physically much larger image, because it's still at 72 DPI. - -14. Make the middle line vertically movable to change the relative window sizes. Maybe. - Or maybe just make both halves viewable as separate windows. - diff --git a/enclone_visual/src/update_restart.rs b/enclone_visual/src/update_restart.rs deleted file mode 100644 index 3ff066c877..0000000000 --- a/enclone_visual/src/update_restart.rs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use crate::*; -use std::env; -use std::process::Command; - -pub fn restart_enclone() { - let args: Vec = env::args().collect(); - let mut args1 = Vec::::new(); - for i in 1..args.len() { - args1.push(args[i].clone()); - } - let o = Command::new("enclone").args(&args1).spawn(); - if o.is_err() { - let msg = format!("{}", o.as_ref().err().unwrap()); - if msg.contains("No such file or directory") { - xprintln!( - "Attempt to restart enclone failed because the executable could not be found.\n\ - This is unexpected, and perhaps attributable to a problem with your PATH.\n" - ); - xprintln!("Here is some debugging information that might be helpful:\n"); - for (key, value) in env::vars() { - if key == "PATH" { - xprintln!("Your PATH is\n\n{}\n", value); - } - } - let home = dirs::home_dir().unwrap().to_str().unwrap().to_string(); - let enclone_path = format!("{}/bin/enclone", home); - xprintln!("Here is the output of ls -l {}:\n", enclone_path); - let o = Command::new("ls") - .arg("-l") - .arg(&enclone_path) - .output() - .expect("failed to execute ls"); - xprint!("{}{}", strme(&o.stdout), strme(&o.stderr)); - xprintln!("\nPlease ask for help!\n"); - std::process::exit(1); - } - } - let mut o = o.expect("failed to execute enclone restart"); - let _ = o.wait().expect("failed to wait on child"); - std::process::exit(0); -} - -pub fn update_enclone() { - xprintln!("Automatically updating enclone, following the instructions at bit.ly/enclone.\n"); - let mut home = String::new(); - for (key, value) in env::vars() { - if key == "HOME" { - home = value.clone(); - } - } - if home.len() == 0 { - xprintln!("Weird, unable to determine your home directory.\n"); - std::process::exit(1); - } - let o = Command::new("curl") - .arg("-s") - .arg("-L") - .arg( - "https://github.com/10XGenomics/enclone/\ - releases/latest/download/enclone_macos", - ) - .arg("--output") - .arg(&format!("{}/bin/enclone", home)) - .output() - .expect("failed to execute curl"); - if o.status.code() != Some(0) { - xprintln!( - "Update failed with the following error message:\n{}", - strme(&o.stderr) - ); - std::process::exit(1); - } -} diff --git a/enclone_visual/src/xwrap.rs.aside b/enclone_visual/src/xwrap.rs.aside deleted file mode 100644 index d1cf5a0e29..0000000000 --- a/enclone_visual/src/xwrap.rs.aside +++ /dev/null @@ -1,264 +0,0 @@ -// This code is a minimally modified version of code in the crate shotgun:2.2.1. It is -// subject to the terms of the Mozilla Public License, v. 2.0. - -// Originally this was used as part of screen capture for Linux. But it only works under X, -// and most Linux distros are moving to Wayland, so it's not very useful. If we want to bring -// this back, we should add -// x11 = { version = "2.18", features = ["xlib", "xrandr"] } -// to Cargo.toml. - -use std::mem; -use std::os::raw; -use std::ptr; -use std::slice; - -use image::Pixel; -use image::Rgba; -use image::RgbaImage; -use libc; -use x11::xlib; - -pub mod util { - - use std::cmp; - - #[derive(Copy, Clone, Debug)] - pub struct Rect { - pub x: i32, - pub y: i32, - pub w: i32, - pub h: i32, - } - - impl Rect { - pub fn intersection(&self, other: Rect) -> Option { - let ix = cmp::max(self.x, other.x); - let iy = cmp::max(self.y, other.y); - let iw = cmp::min(self.x + self.w, other.x + other.w) - ix; - let ih = cmp::min(self.y + self.h, other.y + other.h) - iy; - - if iw > 0 && ih > 0 { - Some(Rect { - x: ix, - y: iy, - w: iw, - h: ih, - }) - } else { - None - } - } - } - - pub fn parse_int(string: &str) -> Result { - if string.len() < 2 { - return T::from_str_radix(string, 10); - } - match &string[..2] { - "0x" | "0X" => T::from_str_radix(&string[2..], 16), - "0o" | "0O" => T::from_str_radix(&string[2..], 8), - "0b" | "0B" => T::from_str_radix(&string[2..], 2), - _ => T::from_str_radix(string, 10), - } - } -} - -pub const ALL_PLANES: libc::c_ulong = !0; - -pub struct Display { - handle: *mut xlib::Display, -} - -pub struct Image { - handle: *mut xlib::XImage, -} - -impl Display { - pub fn open(name: Option) -> Option { - unsafe { - let name = match name { - None => ptr::null(), - Some(cstr) => cstr.as_ptr(), - }; - let d = xlib::XOpenDisplay(name); - - if d.is_null() { - return None; - } - - Some(Display { handle: d }) - } - } - - pub fn get_default_root(&self) -> xlib::Window { - unsafe { xlib::XDefaultRootWindow(self.handle) } - } - - pub fn get_window_rect(&self, window: xlib::Window) -> util::Rect { - unsafe { - let mut attrs = mem::MaybeUninit::uninit(); - xlib::XGetWindowAttributes(self.handle, window, attrs.as_mut_ptr()); - let attrs = attrs.assume_init(); - - let mut root = 0; - let mut parent = 0; - let mut children: *mut xlib::Window = ptr::null_mut(); - let mut nchildren = 0; - xlib::XQueryTree( - self.handle, - window, - &mut root, - &mut parent, - &mut children, - &mut nchildren, - ); - if !children.is_null() { - xlib::XFree(children as *mut raw::c_void); - } - - let mut x = attrs.x; - let mut y = attrs.y; - - if parent != 0 { - let mut child = 0; - xlib::XTranslateCoordinates( - self.handle, - parent, - root, - attrs.x, - attrs.y, - &mut x, - &mut y, - &mut child, - ); - } - - util::Rect { - x: x, - y: y, - w: attrs.width, - h: attrs.height, - } - } - } - - pub fn get_image( - &self, - window: xlib::Window, - rect: util::Rect, - plane_mask: libc::c_ulong, - format: libc::c_int, - ) -> Option { - unsafe { - let image = xlib::XGetImage( - self.handle, - window, - rect.x, - rect.y, - rect.w as libc::c_uint, - rect.h as libc::c_uint, - plane_mask, - format, - ); - - if image.is_null() { - return None; - } - - Some(Image::from_raw_ximage(image)) - } - } -} - -impl Drop for Display { - fn drop(&mut self) { - unsafe { - xlib::XCloseDisplay(self.handle); - } - } -} - -impl Image { - pub fn from_raw_ximage(ximage: *mut xlib::XImage) -> Image { - Image { handle: ximage } - } - - pub fn into_image_buffer(&self) -> Option { - unsafe { - // Extract values from the XImage into our own scope - macro_rules! get { - ($($a:ident),+) => ($(let $a = (*self.handle).$a;)+); - } - get!( - width, - height, - byte_order, - depth, - bytes_per_line, - bits_per_pixel, - red_mask, - green_mask, - blue_mask - ); - - // Pixel size - let stride = match (depth, bits_per_pixel) { - (24, 24) => 3, - (24, 32) | (32, 32) => 4, - _ => return None, - }; - - // Compute subpixel offsets into each pixel according the the bitmasks X gives us - // Only 8 bit, byte-aligned values are supported - // Truncate masks to the lower 32 bits as that is the maximum pixel size - macro_rules! channel_offset { - ($mask:expr) => { - match (byte_order, $mask & 0xFFFFFFFF) { - (0, 0xFF) | (1, 0xFF000000) => 0, - (0, 0xFF00) | (1, 0xFF0000) => 1, - (0, 0xFF0000) | (1, 0xFF00) => 2, - (0, 0xFF000000) | (1, 0xFF) => 3, - _ => return None, - } - }; - } - let red_offset = channel_offset!(red_mask); - let green_offset = channel_offset!(green_mask); - let blue_offset = channel_offset!(blue_mask); - let alpha_offset = channel_offset!(!(red_mask | green_mask | blue_mask)); - - // Wrap the pixel buffer into a slice - let size = (bytes_per_line * height) as usize; - let data = slice::from_raw_parts((*self.handle).data as *const u8, size); - - // Finally, generate the image object - Some(RgbaImage::from_fn(width as u32, height as u32, |x, y| { - macro_rules! subpixel { - ($channel_offset:ident) => { - data[(y * bytes_per_line as u32 + x * stride as u32 + $channel_offset) - as usize] - }; - } - Rgba::from_channels( - subpixel!(red_offset), - subpixel!(green_offset), - subpixel!(blue_offset), - // Make the alpha channel fully opaque if none is provided - if depth == 24 { - 0xFF - } else { - subpixel!(alpha_offset) - }, - ) - })) - } - } -} - -impl Drop for Image { - fn drop(&mut self) { - unsafe { - xlib::XDestroyImage(self.handle); - } - } -} diff --git a/enclone_visual/tests/sample_visual/history/2021-08-23___12-19-03 b/enclone_visual/tests/sample_visual/history/2021-08-23___12-19-03 deleted file mode 100644 index 1eca03ba96..0000000000 Binary files a/enclone_visual/tests/sample_visual/history/2021-08-23___12-19-03 and /dev/null differ diff --git a/enclone_visual/tests/sample_visual/history/2021-08-23___12-19-29 b/enclone_visual/tests/sample_visual/history/2021-08-23___12-19-29 deleted file mode 100644 index 4e53c4706a..0000000000 Binary files a/enclone_visual/tests/sample_visual/history/2021-08-23___12-19-29 and /dev/null differ diff --git a/index.html b/index.html index a270d60f14..f9cb943760 100644 --- a/index.html +++ b/index.html @@ -1,747 +1,837 @@ - + + - -enclone (bit.ly/enclone) - - - - - - - - - - - - -
-
-enclone banner - - -
-

enclone (beta)

-

Accurate and user-friendly computational tool for clonal grouping to study the adaptive immune system

-

(Antigen analysis is not supported)

-
- -

10x Genomics Chromium Single Cell V(D)J data - containing B cell - receptor (BCR) and T cell receptor (TCR) RNA sequences are entered as input data to - enclone. Based on the - input, enclone finds and organizes cells arising from the same progenitors into groups - (clonotypes) and - compactly displays each clonotype along with its salient features, including mutated amino - acids.

-

+ enclone (bit.ly/enclone) + + + + + + + + + + + + +
+ + enclone banner + + +

+

enclone (beta)

+

Accurate and user-friendly computational tool for clonal grouping to study the adaptive immune system +

+

(Antigen analysis is not supported)

+
+ +

10x Genomics Chromium Single Cell V(D)J data + containing B cell + receptor (BCR) and T cell receptor (TCR) RNA sequences are entered as input data to + enclone. Based on the + input, enclone finds and organizes cells + arising from the same progenitors into groups + (clonotypes) and + compactly displays each clonotype along with its salient features, including mutated amino + acids. +

+

-enclone (beta) is provided as a tool for use by the community to accelerate immunology research. -enclone is only supported via -enclone@10xgenomics.com. -The clonotype assignment algorithm that is part of enclone is integrated into Cell Ranger. -

- -

enclone has been designed for immunologists but anyone can download and experiment with it.

- -

Background: when you get sick, your body mounts an immune response by selectively -amplifying immune cells and mutations within these selected cells. enclone allows you to see the -history of -single immune cells within a biological sample (such as a blood draw or biopsy). This history -reflects how the cognate receptors of these cells evolved in response to antigens, including -viruses, bacteria, and tumors.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 1. Introduction  8. Help 
 2. Objective  9. Understanding enclone output 
 3. Why enclone 10. Combining multiomic data 
 4. Data input  11. Visualizing multiple clonotypes at once 
 5. Software  12. The power of enclone 
 6. Installing enclone  13. Questions 
 7. Running enclone  14. Where am I? 
- -
- -
- -

-

Introduction

-

The body defends itself from antigens, like viruses, bacteria, and tumors, by recognizing the -antigens and mounting an immune response through selective amplification of immune cells and -mutations within selected cells. enclone enables profiling of the history of single immune -cells within a biological sample (such as a blood draw or a biopsy) by mapping the evolution of the -cognate BCRs and TCRs of those cells responding to antigen exposure. This history reflects how the -cognate receptors of these cells evolved in response to various antigens.

- -

-

Objective

- - -

Using enclone to profile B and T cell receptors for any sample using Chromium Single Cell -V(D)J as input enables you to make the best use of your data. You can explore the biology of these -cells without help from a computational expert!

- -

The objective of enclone is to:

- - - - + + +
-

enclone (beta) is provided as a tool for use + by the community to accelerate immunology research. + enclone is only supported via + enclone@10xgenomics.com. + The clonotype assignment algorithm that is part of enclone is integrated into Cell Ranger. +

+ +

enclone has been designed for immunologists but + anyone can download and experiment with it.

+ +

Background: when you get sick, your body mounts an immune response by selectively + amplifying immune cells and mutations within these selected cells. enclone allows you to see the + history of + single immune cells within a biological sample (such as a blood draw or biopsy). This history + reflects how the cognate receptors of these cells evolved in response to antigens, including + viruses, bacteria, and tumors.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 1. Introduction  8. Help 
 2. Objective  9. Understanding enclone output  +
 3. Why enclone 10. Combining multiomic data 
 4. Data input  11. Visualizing multiple clonotypes at + once 
 5. Software  12. The power of enclone 
 6. Installing enclone  13. Questions 
 7. Running enclone  14. Where am I? 
+ +
+ +
+ +

+

Introduction

+

The body defends itself from antigens, like viruses, bacteria, and tumors, by recognizing the + antigens and mounting an immune response through selective amplification of immune cells and + mutations within selected cells. enclone + enables profiling of the history of single immune + cells within a biological sample (such as a blood draw or a biopsy) by mapping the evolution of the + cognate BCRs and TCRs of those cells responding to antigen exposure. This history reflects how the + cognate receptors of these cells evolved in response to various antigens.

+ +

+

Objective

+ + +

Using enclone to profile B and T cell receptors + for any sample using Chromium Single Cell + V(D)J as input enables you to make the best use of your data. You can explore the biology of these + cells without help from a computational expert!

+ +

The objective of enclone is to:

+ + + + - - -
+

- Find and display clonotypes: - groups of T and B cells sharing the same fully rearranged common ancestor. -

-
-

Find: - It is easy to mistakenly put unrelated cells in - the same clonotype, or "pollute" a clonotype with extraneous chains. - enclone's algorithms make finding accurate.

-

Display: - It is challenging to compactly represent a - large repertoire of data. enclone enables compact, easy-to-grasp data - display.

-
- -

The diversity of BCR and TCR chains, containing various combinations of V, D, and/or J segments, -broadens the immune repertoire to protect against a wide variety of pathogens. The figure below -illustrates the concept of a BCR clonotype. A similar concept applies to TCRs but without -somatic hypermutations.

- - -what is a clonotype - -

Each cell in a clonotype is typically represented by two or three chains, and this information is -present and directly observable in single cell V(D)J data. enclone computationally approximates -the clonotypes -from the data with high accuracy (see below). The methods of enclone are described -briefly in the online documentation for enclone, and see -below.

- -
- -

-

Why use enclone?

-

-enclone has unique features! -

-

-Unique insights into 10x Genomics data: enclone has been designed and tested -extensively to -gain in-depth insight and perspective regarding 10x Genomics single cell V(D)J datasets. Other -similar tools -may be used, but frequently, enclone will provide a different answer, which in turn may affect -the biological interpretation of the data. -

-

-Speed: enclone is very fast, allowing analysis of datasets in seconds. -

-

-Easy installation: The software is easy to install and to use. -

- -
- -

-

Inputs to enclone

- -

10x Genomics single cell 5' data

- -

-BCR or TCR RNA sequences generated using the 10x Genomics -Chromium Single Cell Immune Profiling Solution and Cell Ranger 3.1 or higher are the inputs to -enclone. enclone can also process and display gene expression and Feature Barcode data -from the same cells. The latter can be used to quantify cell surface proteins, antigen binding, CRISPR -sgRNA, and other cellular features. You can see a list of publications that use 10x VDJ data -here. - -

- -
- -

-

The enclone software

- -

enclone is beta software†† released under this license. -Binary executables for Linux and Mac and Windows can be directly downloaded from this page, as can -sample 10x Genomics datasets. -enclone can be run on a laptop, desktop, or server. -

-

-To use enclone, basic knowledge of the command line is necessary. The command line is easy to -learn, and a -colleague may be able to help you if you are unfamiliar. Additional skills, like programming, -are not required. The command line can be dynamically changed to select specific clonotypes and -fields you wish to -see. enclone is fast, typically responding in seconds (if run on a single dataset). -

- -

- - - - -
-There is also a graphical (GUI) version of enclone, called enclone visual, that is -alpha software. To use it, one installs -enclone as described below and then types enclone VIS from a terminal window -to launch the GUI. Documentation is here. -
-

- -

-enclone, in addition to Cell Ranger and -Loupe -(and in which the core algorithm of enclone will be integrated at a later point in time), -supports the -analysis of V(D)J and other data from the -Chromium Single Cell Immune Profiling -solution. -

- -

- ††beta software implies that it is still being actively developed, with -features being added/modified, -and on rare occasions may involve breaking syntax that previously worked. See -this page for the history of changes. -

- -
- -

-

Installing enclone

- -

-You can run enclone directly from a Linux or Mac terminal window; see -here for Windows instructions. -

- - - - - - - -
Type this  -
curl -sSf -L bit.ly/enclone_install | bash -s SIZE
-
- where SIZE is -small, medium, large, or colossus, according to: -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
-

- small -

-
-

- load small dataset collection (one dataset, 123085) -

-
-

- 30 MB -

-
-

- do this if your internet connection is very slow -

-
-

- medium -

-
-

- load medium dataset collection -

-
-

- 3400 MB -

-
-

- do this for a moderate number of datasets (~120) -

-
-

- large -

-
-

- load large dataset collection -

-
-

- 4700 MB -

-
-

- do this for a large number of datasets (~240) -

-
-

- colossus -

-
-

- load colossus dataset collection -

-
-

- 26400 MB -

-
-

- same as large but includes gene expression data for many datasets -

-
- -

The command does three things:

-
    -
  1. Puts the enclone executable (for Linux or Mac as appropriate) in ~/bin.
  2. -
  3. If needed, adds a line to your bash initialization file so that ~/bin is included. -
  4. -
  5. Puts enclone datasets in ~/enclone.
  6. -
-Additional details can be found here. - -Restart your terminal session; you can now run enclone.

- - - - - -
-Please see -here if you have an installation problem. -
- -

To update, type the same command! - -You can also type enclone UPDATE, which does the same thing (except for older versions -of enclone). Only required files will be downloaded. -See history for the history of changes to -enclone. -

- -

Information about previous releases of enclone, matching particular Cell Ranger releases is -here, along with an inventory of enclone changes that -affect Cell Ranger output.

- - - - - -
-On a Mac, the Terminal application can enter weird states. One behavior is an intermittently -spinning disk. Another is that some executables (perhaps enclone) may respond with -Command not found or Permission denied. In such cases, it may work -to close the Terminal application (Quit Terminal on the top bar), then reopen it. -This should only be needed rarely, if at all. -
- -
- -

-

Running enclone

- -

Running enclone can be as simple as typing e.g.

-
enclone BCR=/home/my_name/experiment_123
+                              Find and display clonotypes:
+                              groups of T and B cells sharing the same fully rearranged common ancestor.
+                         

+
+

Find: + It is easy to mistakenly put unrelated cells in + the same clonotype, or "pollute" a clonotype with extraneous chains. + enclone's algorithms make + finding accurate. +

+

Display: + It is challenging to compactly represent a + large repertoire of data. enclone enables compact, + easy-to-grasp data + display.

+
+ +

The diversity of BCR and TCR chains, containing various combinations of V, D, and/or J segments, + broadens the immune repertoire to protect against a wide variety of pathogens. The figure below + illustrates the concept of a BCR clonotype. A similar concept applies to TCRs but without + somatic hypermutations.

+ + + what is a clonotype + +

Each cell in a clonotype is typically represented by two or three chains, and this information is + present and directly observable in single cell V(D)J data. enclone computationally approximates + the clonotypes + from the data with high accuracy (see below). The methods of enclone are described + briefly in the online documentation for enclone, and see + below. +

+ +
+ +

+

Why use enclone?

+

+ enclone has unique features! +

+

+ Unique insights into 10x Genomics data: enclone has been designed and tested + extensively to + gain in-depth insight and perspective regarding 10x Genomics single cell V(D)J datasets. Other + similar tools + may be used, but frequently, enclone will + provide a different answer, which in turn may affect + the biological interpretation of the data. +

+

+ Speed: enclone is very fast, allowing + analysis of datasets in seconds. +

+

+ Easy installation: The software is easy to install and to use. +

+ +
+ +

+

Inputs to enclone

+ +

10x Genomics single cell 5' data

+ +

+ BCR or TCR RNA sequences generated using the 10x Genomics + Chromium Single Cell Immune Profiling Solution and Cell Ranger 3.1 or higher are the inputs to + enclone. enclone can also process and display gene + expression and Feature Barcode data + from the same cells. The latter can be used to quantify cell surface proteins, antigen binding, + CRISPR + sgRNA, and other cellular features. You can see a list of publications that use 10x VDJ data + here. + +

+ +
+ +

+

The enclone software

+ +

enclone is beta software†† released + under this license. + Binary executables for Linux and Mac and Windows can be directly downloaded from this page, as can + sample 10x Genomics datasets. + enclone can be run on a laptop, desktop, or + server. +

+

+ To use enclone, basic knowledge of the + command line is necessary. The command line is easy to + learn, and a + colleague may be able to help you if you are unfamiliar. Additional skills, like programming, + are not required. The command line can be dynamically changed to select specific clonotypes and + fields you wish to + see. enclone is fast, typically responding in + seconds (if run on a single dataset). +

+ +

+ enclone, in addition to Cell Ranger and + Loupe + (and in which the core algorithm of enclone + will be integrated at a later point in time), + supports the + analysis of V(D)J and other data from the + Chromium Single Cell Immune + Profiling + solution. +

+ +

+ ††beta software implies that it is still being actively developed, with + features being added/modified, + and on rare occasions may involve breaking syntax that previously worked. See + this page for the history of changes. +

+ +
+ +

+

Installing enclone

+ +

+ You can run enclone directly from a + Linux or Mac terminal window; see + here for Windows instructions. +

+ + + + + + + +
Type this  +
curl -sSf -L bit.ly/enclone_install | bash -s SIZE
+
+  where SIZE is + small, medium, large, or colossus, + according to: +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ small +

+
+

+ load small dataset collection (one dataset, 123085) +

+
+

+ 30 MB +

+
+

+ do this if your internet connection is very slow +

+
+

+ medium +

+
+

+ load medium dataset collection +

+
+

+ 3400 MB +

+
+

+ do this for a moderate number of datasets (~120) +

+
+

+ large +

+
+

+ load large dataset collection +

+
+

+ 4700 MB +

+
+

+ do this for a large number of datasets (~240) +

+
+

+ colossus +

+
+

+ load colossus dataset collection +

+
+

+ 26400 MB +

+
+

+ same as large but includes gene expression data for many datasets +

+
+ +

The command does three things:

+
    +
  1. Puts the enclone executable (for Linux or + Mac as appropriate) in ~/bin.
  2. +
  3. If needed, adds a line to your bash initialization file so that ~/bin is included. +
  4. +
  5. Puts enclone datasets in + ~/enclone.
  6. +
+ Additional details can be found here. + + Restart your terminal session; you can now run enclone.

+ + + + + +
+ Please see + here if you have an installation problem. +
+ +

To update, type the same command! + + You can also type enclone UPDATE, which does the same thing (except for older versions + of enclone). Only required files will be + downloaded. + See history for the history of changes to + enclone. + +

+ +

Information about previous releases of enclone, + matching particular Cell Ranger releases is + here, along with an inventory of enclone changes that + affect Cell Ranger output. +

+ + + + + +
+ On a Mac, the Terminal application can enter weird states. One behavior is an intermittently + spinning disk. Another is that some executables (perhaps enclone) may respond with + Command not found or Permission denied. In such cases, it may work + to close the Terminal application (Quit Terminal on the top bar), then reopen it. + This should only be needed rarely, if at all. +
+ +
+ +

+

Running enclone

+ +

Running enclone can be as simple as typing e.g. +

+
enclone BCR=/home/my_name/experiment_123
 
-

where the path is where your Cell Ranger outputs live, but there are many options to learn -about. For example, if you want to combine many datasets, you can do that, but you probably -need to provide a metadata file that describes the datasets. You can find most of the enclone -documentation within its online menus. To get started you should:

-
    -
  1. -

    Type enclone help, to make sure your terminal window works for -enclone.

    -

    -A few things you need to know: -
    1. To view the online help, your terminal window needs to be 100 characters wide - (or wider). -
    2. When you view enclone output, you will in general need to make your window even - wider. -
    3. How wide depends on the data and the fields you choose to show. -
    4. If it's not wide enough, the output will "wrap" and be very confusing! -
    5. Having clonotype tables in a Terminal on a Mac can make the Terminal less - responsive. This may depend on the operating system version. -

    -
  2. -
  3. -

    Type enclone to get to the main enclone help menu.

    -
  4. -
-
- -

-

Help

- -

-From any page, clicking on the banner at the top will take you back -here.

- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pages on site and accessible from command line
commandwhat it provides
enclone helphelp to test for correct setup
enclonewhat you see here; guide to all the docs
enclone help quickquick guide to getting started
enclone help howoutline of how enclone works, see also heuristics
enclone help commandinfo about enclone command line processing
enclone help glossaryglossary of terms used by enclone, conventions
enclone help example1explanation of an example
enclone help example2example of gene expression, feature barcodes
enclone help inputhow to provide input to enclone
enclone help input_techhow to provide input to enclone (technical notes)
enclone help parseableparseable output
enclone help filterclonotype filtering, feature enrichment scanning
enclone help specialspecial filtering options
enclone help lvarslead column options
enclone help cvarsper chain column options
enclone help aminoper chain column options for amino acids
enclone help displayother clonotype display options
enclone help indelsinsertion and deletion handling
enclone help colorhow enclone uses color, and related things
enclone help faqfrequently asked questions
enclone help allconcatenation of all the help pages
(USE THIS TO SEARCH ALL HELP PAGES)
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
other pages on site
pageaudience
history of changeseveryone
detecting illusory clonotypeseveryone
enclone developers guidepeople who want to contribute code
licenseeveryone
Windowspeople using Windows computers
notes on heuristicsthose curious about the algorithm
enclone default filteringthose curious about the algorithm
plotseveryone
making phylogenetic treeseveryone
installation troubleshooting - if you have trouble installing
installation details - those curious what install command does
iNKT and MAIT cells - those curious about iNKT and MAIT cells
V(D)J features - those curious about CDR*, etc. calculations
enclone variable inventory - everyone
D genes, junction regions - everyone
enclone in cellranger - everyone
- enclone visual - everyone
- -

- - - - -
-Additional information may be found in our bioRxiv preprint -
- -enclone: precision clonotyping and analysis of immune receptors. -
-

- -

And we're here to help! See the bottom of this page for how to contact us.

- -
- -
- -
- -

-

Understanding enclone output

- -

The example below shows how enclone displays clonotypes. Understanding this display is -important for using enclone. Consult the available enclone documentation and use -the sample datasets to understand enclone features and output.

- -enclone annotated example - -Notice the compression in two directions: -
    -
  1. Vertically to group cells into a single line if they have identical V(D)J - transcripts - (instead of showing one line for every cell).
  2. -
  3. Horizontally, a flexible concept, to show by default all positions exhibiting a - difference from the reference and all positions in the CDR3 (instead of showing - all transcript positions, only "interesting" positions are shown).
  4. -
- -

Approximately the same output would be obtained by typing:

-
enclone BCR=123085 CDR3=CTRDRDLRGATDAFDIW
+          

where the path is where your Cell Ranger outputs live, but there are many options to learn + about. For example, if you want to combine many datasets, you can do that, but you probably + need to provide a metadata file that describes the datasets. You can find most of the enclone + documentation within its online menus. To get started you should:

+
    +
  1. +

    Type enclone help, to make sure your terminal window works for + enclone. +

    +

    + A few things you need to know: +
    1. To view the online help, your terminal window needs to be 100 characters wide + (or wider). +
    2. When you view enclone + output, you will in general need to make your window even + wider. +
    3. How wide depends on the data and the fields you choose to show. +
    4. If it's not wide enough, the output will "wrap" and be very confusing! +
    5. Having clonotype tables in a Terminal on a Mac can make the Terminal less + responsive. This may depend on the operating system version. +

    +
  2. +
  3. +

    Type enclone to get to the main enclone help menu.

    +
  4. +
+
+ +

+

Help

+ +

+ From any page, clicking on the banner at the top will take you back + here. +

+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
pages on + site and accessible from command line
commandwhat it provides
enclone helphelp to test for correct setup
enclonewhat you see here; guide to all the docs
enclone help quick + quick guide to getting started
enclone help howoutline of how enclone works, + see also heuristics
enclone help command + info about enclone command + line processing
enclone help + glossaryglossary of terms used by enclone, + conventions
enclone help + example1explanation of an example
enclone help + example2example of gene expression, feature barcodes
enclone help input + how to provide input to enclone
enclone help + input_techhow to provide input to enclone + (technical notes)
enclone help + parseableparseable output
enclone help filter + clonotype filtering, feature enrichment scanning
enclone help special + special filtering options
enclone help lvars + lead column options
enclone help cvars + per chain column options
enclone help amino + per chain column options for amino acids
enclone help display + other clonotype display options
enclone help indels + insertion and deletion handling
enclone help color + how enclone uses + color, and related things
enclone help faqfrequently asked questions
enclone help allconcatenation of all the help pages
(USE THIS TO SEARCH + ALL HELP PAGES)
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
other + pages on site
pageaudience
history of changeseveryone
detecting illusory + clonotypeseveryone
enclone developers guidepeople who want to contribute code
licenseeveryone
Windowspeople using Windows computers
notes on heuristics + those curious about the algorithm
enclone + default filteringthose curious about the algorithm
plotseveryone
making phylogenetic trees + everyone
installation + troubleshooting + if you have trouble installing
installation + details + those curious what install command does
iNKT and MAIT cells + those curious about iNKT and MAIT cells
V(D)J features + those curious about CDR*, etc. calculations
enclone variable inventory + everyone
D genes, junction regions + everyone
enclone in + cellranger + everyone
+ +

+ + + + +
+ Additional information may be found in our bioRxiv preprint +
+ + enclone: precision clonotyping and analysis of immune receptors. +
+

+ +

And we're here to help! See the bottom of this page for how to contact us.

+ +
+ +
+ +
+ +

+

Understanding enclone output

+ +

The example below shows how enclone displays + clonotypes. Understanding this display is + important for using enclone. Consult the + available enclone documentation and use + the sample datasets to understand enclone + features and output.

+ + enclone annotated example + + Notice the compression in two directions: +
    +
  1. Vertically to group cells into a single line if they have identical V(D)J + transcripts + (instead of showing one line for every cell).
  2. +
  3. Horizontally, a flexible concept, to show by default all positions exhibiting a + difference from the reference and all positions in the CDR3 (instead of showing + all transcript positions, only "interesting" positions are shown).
  4. +
+ +

Approximately the same output would be obtained by typing:

+
enclone BCR=123085 CDR3=CTRDRDLRGATDAFDIW
 
-(As we change the algorithm, results are perturbed, and we have not updated the -diagram each time. All other outputs shown on this site are kept current.) - -

The directory 123085 is in the directory ~/enclone/datasets and -contains some files from a Cell Ranger run, obtained from a human ovarian cancer sample.

- -

-How does enclone find my data? -It uses a search path called PRE that is preset to -~/enclone/datasets,~/enclone/datasets2, and which can be set to any value, either -by setting PRE=... on the command line, or by setting the environment variable -ENCLONE_PRE. To find your data, enclone prepends PRE to the value of -BCR or TCR given on the command line. -For example, all of the following argument combinations do the same thing: -
1. BCR=123085 (using the default value of PRE) -
2. PRE=~/enclone/datasets BCR=123085 -
3. PRE=~/enclone BCR=datasets/123085 -
4. BCR=~/enclone/datasets/123085. -
There is also an argument META that is convenient for specifying multiple -datasets. See here for how. -
-
-Please note that while paths can have non-Latin characters, best practice is to not have -blanks, tabs, etc. in path names. enclone can be made to work with such characters by double -quoting the paths, but it makes things harder, and other programs you might use may break. -

- -

The argument CDR3=CTRDRDLRGATDAFDIW causes enclone to display only clonotypes in -which -the given CDR3 sequence occurs. Many other filters are provided. In the absence of filters, all -clonotypes are shown. Clonotypes are shown from largest to smallest, and the output is -automatically paged, so you can scroll through it.

-

By default, enclone prints clonotypes in this human-readable form. You can also instruct -enclone -to print clonotypes in machine-readable forms that are suitable for input to other programs.

-
- -

-

Combining multiomic data

- -

Gene expression and Feature Barcode data can be displayed simultaneously alongside VDJ data. For -example, here we add columns for the same clonotype, showing the median number of UMIs detected -for all genes, and a particular gene:

- -
[1] GROUP = 1 CLONOTYPES = 51 CELLS
+          (As we change the algorithm, results are perturbed, and we have not updated the
+          diagram each time. All other outputs shown on this site are kept current.)
+
+          

The directory 123085 is in the directory ~/enclone/datasets and + contains some files from a Cell Ranger run, obtained from a human ovarian cancer sample.

+ +

+ How does enclone find my data? + It uses a search path called PRE that is preset to + ~/enclone/datasets,~/enclone/datasets2, and which can be set to any value, either + by setting PRE=... on the command line, or by setting the environment variable + ENCLONE_PRE. To find your data, enclone prepends PRE to the value + of + BCR or TCR given on the command line. + For example, all of the following argument combinations do the same thing: +
1. BCR=123085 (using the default value of PRE) +
2. PRE=~/enclone/datasets BCR=123085 +
3. PRE=~/enclone BCR=datasets/123085 +
4. BCR=~/enclone/datasets/123085. +
There is also an argument META that is convenient for specifying multiple + datasets. See here for how. +
+
+ Please note that while paths can have non-Latin characters, best practice is to not have + blanks, tabs, etc. in path names. enclone can be made to work with such + characters by double + quoting the paths, but it makes things harder, and other programs you might use may break. +

+ +

The argument CDR3=CTRDRDLRGATDAFDIW causes enclone to display only clonotypes in + which + the given CDR3 sequence occurs. Many other filters are provided. In the absence of filters, all + clonotypes are shown. Clonotypes are shown from largest to smallest, and the output is + automatically paged, so you can scroll through it.

+

By default, enclone prints clonotypes in this + human-readable form. You can also instruct + enclone + to print clonotypes in machine-readable forms that are suitable for input to other programs. +

+
+ +

+

Combining multiomic data

+ +

Gene expression and Feature Barcode data can be displayed simultaneously alongside VDJ data. For + example, here we add columns for the same clonotype, showing the median number of UMIs detected + for all genes, and a particular gene:

+ +
[1] GROUP = 1 CLONOTYPES = 51 CELLS
 
 [1.1] CLONOTYPE = 51 CELLS
 ┌──────────────────────────┬──────────────────────────────────────┬───────────────────────────────┐
@@ -763,103 +853,125 @@ 

Combining multiomic data

└──────────────────────────┴──────────────────────────────────────┴───────────────────────────────┘
-

To obtain this, we added the extra arguments -GEX=123217 LVARSP=gex,IGHV3-49_g -to the previous command. The GEX part points to the directory containing gene -expression data. The LVARSP part defines the additional columns -to be displayed.

-

Other types of data can be brought in via Feature Barcoding / Feature Barcode Technology. -For example, the response to multiple antigens can be measured using approaches such as those -mentioned in the LIBRA-seq -and Wilson/Stamper/Dugan et al. -papers. These data can be displayed as additional columns.

-
- -

-

Visualizing multiple clonotypes

- - - - - - - + +
- honeycomb plot - -

After selecting multiple clonotypes in enclone, you can display them using - a "honeycomb" plot.

-

In this instance, pre- and post-vaccination samples were collected from four individuals, - many datasets were generated for each sample, and these were combined in a single call - to enclone. Clonotypes containing at least ten cells are shown. - The plot was generated by adding

-
MIN_CELLS=10 PLOT="clono.svg,pre->blue,post->red
+          

To obtain this, we added the extra arguments + GEX=123217 LVARSP=gex,IGHV3-49_g + to the previous command. The GEX part points to the directory containing gene + expression data. The LVARSP part defines the additional columns + to be displayed. +

+

Other types of data can be brought in via Feature Barcoding / Feature Barcode Technology. + For example, the response to multiple antigens can be measured using approaches such as those + mentioned in the LIBRA-seq + and Wilson/Stamper/Dugan et + al. + papers. These data can be displayed as additional columns.

+
+ +

+

Visualizing multiple clonotypes

+ + + + + + + - -
+ honeycomb plot + +

After selecting multiple clonotypes in enclone, you can display them + using + a "honeycomb" plot.

+

In this instance, pre- and post-vaccination samples were collected from four individuals, + many datasets were generated for each sample, and these were combined in a single call + to enclone. Clonotypes + containing at least ten cells are shown. + The plot was generated by adding

+
MIN_CELLS=10 PLOT="clono.svg,pre->blue,post->red
 LEGEND=blue,"pre-vaccination cell",
        red,"post-vaccination cell"
-

to the enclone command line, yielding the image shown here as the file - clono.svg.

-

For more information about honeycomb plots, - see here.

-
- -
-
- -

-

The power of enclone

- -

There are many ways to use 10x Genomics data to study immunobiology.

-

Response to an antigen or vaccine: enclone is a great tool for studying responses to a -vaccine. For example, in the previous section, the red clonotypes may represent responses to -antigens in the vaccine.

-

Vaccine and therapeutic antibody development: For certain infectious agents e.g. COVID-19, -a vaccine does not currently exist; different approaches may be employed in pursuit of this goal. One such -approach is to identify patient and survivor B cell clonotypes that expand in response to the infectious -disease. These define antibodies that can be used to design passive or active vaccines.

-

Additional power is added by mapping antigen specificity to multiple antigens directly via Feature -Barcode Technology (one example of this is the LIBRA-seq -publication). These data are easy to display in enclone. Candidates can be selected directly for vaccine or therapeutic -development by picking large clonotypes with high antigen counts and single or multiple antigen specificities.

-

We are actively working on further functionality that will make this process even more effective.

-

See this vignette to learn how to generate phylogenetic trees using -enclone. -

Another example use of enclone is the detection of -illusory clonotypes.

- -
- -

-

Questions

- -

-Please contact us with your questions and comments! We look forward to hearing your feedback and ideas to -further evolve enclone. -

- -

-Our address is enclone@10xgenomics.com. -

- -

-To send us enclone output, please simply cut and paste text, rather than send a -screenshot, except when necessary. Please send both the command you used and the output. -

- -

enclone command line, + yielding the image shown here as the file + clono.svg. +

+

For more information about honeycomb plots, + see here.

+
+ +
+
+ +

+

The power of enclone

+ +

There are many ways to use 10x Genomics data to study immunobiology.

+

Response to an antigen or vaccine: enclone is a great tool for studying responses + to a + vaccine. For example, in the previous section, the red clonotypes may represent responses to + antigens in the vaccine.

+

Vaccine and therapeutic antibody development: For certain infectious agents e.g. COVID-19, + a vaccine does not currently exist; different approaches may be employed in pursuit of this goal. One + such + approach is to identify patient and survivor B cell clonotypes that expand in response to the + infectious + disease. These define antibodies that can be used to design passive or active vaccines.

+

Additional power is added by mapping antigen specificity to multiple antigens directly via Feature + Barcode Technology (one example of this is the LIBRA-seq + publication). These data are easy to display in enclone. Candidates can be selected directly + for vaccine or therapeutic + development by picking large clonotypes with high antigen counts and single or multiple antigen + specificities.

+

We are actively working on further functionality that will make this process even more effective.

+

See this vignette to learn how to generate phylogenetic trees using + enclone. +

Another example use of enclone is the detection of + illusory clonotypes.

+ +
+ +

+

Questions

+ +

+ Please contact us with your questions and comments! We look forward to hearing your feedback and ideas to + further evolve enclone. +

+ +

+ Our address is enclone@10xgenomics.com. +

+ +

+ To send us enclone output, please simply + cut and paste text, rather than send a + screenshot, except when necessary. Please send both the command you used and the output. +

+ +

-enclone is provided as a tool for use by the community. -enclone is beta software and thus a work in progress. We are actively making many changes and may -be unable to respond promptly to your particular request. -

+ enclone is provided as a tool for use by the + community. + enclone is beta software and thus a work in + progress. We are actively making many changes and may + be unable to respond promptly to your particular request. +

+ +
-
+

+

Where am I?

-

-

Where am I?

+ +

+ bit.ly/enclone

- -

bit.ly/enclone

+ - diff --git a/internal_docs/gex_files b/internal_docs/gex_files index af08b35631..efa20a644e 100644 --- a/internal_docs/gex_files +++ b/internal_docs/gex_files @@ -1,5 +1,5 @@ -Here we spec the GEX file requirements. This is complicated by differences between the -customer (CS) and internal (PD) pipeline outs file structures and the need for backward +Here we spec the GEX file requirements. This is complicated by differences between the +customer (CS) and internal (PD) pipeline outs file structures and the need for backward compatibility. These requirements are likely to change over time. @@ -14,12 +14,8 @@ analysis/pca/10_components/projection.csv analysis_csv/pca/10_components/pro *: named raw_gene_bc_matrices_h5.h5 in older pipeline versions **: not present in older pipeline versions -Given a GEX path p, enclone will look for these files in p, if p ends with outs, and if not, +Given a GEX path p, enclone will look for these files in p, if p ends with outs, and if not, first p/outs, then p. -For internal runs, if the GEX path p does not exist, and (after removing PRE), p is an integer, +For internal runs, if the GEX path p does not exist, and (after removing PRE), p is an integer, then we assume it is an internal identifier and look for it in the internal pipeline outputs. - -If the NH5 option is specified to enclone, it will write out a file feature_barcode_matrix.bin to -this same directory (p or p/outs, as above), provided that feature_barcode_matrix.bin does not -already exist. Subsequently, this file will be used for input whether or not NH5 is specified. diff --git a/master.toml b/master.toml index 7e94097ddf..99bd8690b6 100755 --- a/master.toml +++ b/master.toml @@ -54,8 +54,6 @@ git = "https://github.com/10xGenomics/hdf5-rust.git" graph_simple = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } home = "0.5" hyperbase = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -iced = { git = "https://github.com/hecrj/iced", rev = "3042fa2cb63c651ebed2abe6f4054e61f70b0331", features = ["canvas", "image", "async-std"] } -iced_native = { git = "https://github.com/hecrj/iced", rev = "3042fa2cb63c651ebed2abe6f4054e61f70b0331" } image = { version = "0.23", features = ["jpeg", "png", "jpeg_rayon"], default-features = false } include_dir = { version = "0.6", features = ["search"] } io_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } @@ -67,7 +65,6 @@ libc = "0.2" log = "0.4" lz4 = "1" mach = "0.3" -mirror_sparse_matrix = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } ndarray = "0.15" nix = { version = "0.27", features = ["signal"] } num-traits = "0.2" diff --git a/pages/auto/cellranger.html b/pages/auto/cellranger.html index 2c8072cc37..161b404d3d 100644 --- a/pages/auto/cellranger.html +++ b/pages/auto/cellranger.html @@ -78,7 +78,6 @@

enclone changes date - enclone version git hash first Cell Ranger version change diff --git a/pages/auto/dev.html b/pages/auto/dev.html index 44cbc2b39b..1c2941edc5 100644 --- a/pages/auto/dev.html +++ b/pages/auto/dev.html @@ -227,16 +227,6 @@ full - -3 -test_vis -many tests of enclone visual using screenshots -N/A -1 -none -N/A - - @@ -278,7 +268,6 @@ and uses the code there as part of the test process. To get versions fully synced, you need to touch enclone/enclone_core/defs.rs on the Linux server and then cargo b. Otherwise you’ll get an error message. -
  • See the file enclone_visual/src/bin/test_vis.rs.
  • @@ -302,7 +291,6 @@ it returned zero exit status, even though when called e.g. from a script, it would return a nonzero value. -
  • Manual tests listed at the bottom of enclone_visual/src/testsuite.rs.
  • @@ -312,7 +300,6 @@ There are some other major things that are not tested:
    • Compilation of enclone under Windows.
    • -
    • Functionality of enclone visual under Linux and Windows.
    • Functionality of hdf5 under Windows (which was previously broken).
    diff --git a/pages/auto/help.all.html b/pages/auto/help.all.html index 573aa46d58..1c142033d7 100644 --- a/pages/auto/help.all.html +++ b/pages/auto/help.all.html @@ -571,20 +571,6 @@ Both input forms involve abbreviated names (discussed below), which should be as short as possible, as longer abbreviations will increase the width of the clonotype displays. -┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -┃enclone can use gene expression and feature barcode data, as represented by a feature matrix. ┃ -┃Cell Ranger stores this matrix in an hdf5 file, which while generally very efficient, is not ┃ -┃optimized for interactive use. Therefore enclone provides an alternate file structure, which ┃ -┃speeds up enclone overall by up to 50%. To use this, add the argument NH5 to the enclone command ┃ -┃line. This will work so long as you have write permission on input directories. The first time ┃ -┃you run enclone (using given inputs), an alternate file feature_barcode_matrix.bin will be ┃ -┃written; then subsequent invocations will be faster. Once the file has been created, it will ┃ -┃always be used, regardless of whether NH5 is used. However, we may occasionally change the format┃ -┃of the alternate file. If do that, then if you have previously generated the file, then it will ┃ -┃be rewritten when you invoke enclone for that dataset. Like with other enclone command-line ┃ -┃options, if you want NH5 on all the time, you can set the environment variable ENCLONE_NH5. ┃ -┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - █ 1 █ To point directly at input files on the command line, use e.g. TCR=/home/jdoe/runs/dataset345 or likewise for BCR. A more complicated syntax is allowed in which commas, colons and semicolons diff --git a/pages/auto/help.input.html b/pages/auto/help.input.html index d05fd298d6..a5c7d09f25 100644 --- a/pages/auto/help.input.html +++ b/pages/auto/help.input.html @@ -67,20 +67,6 @@ Both input forms involve abbreviated names (discussed below), which should be as short as possible, as longer abbreviations will increase the width of the clonotype displays. -┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -┃enclone can use gene expression and feature barcode data, as represented by a feature matrix. ┃ -┃Cell Ranger stores this matrix in an hdf5 file, which while generally very efficient, is not ┃ -┃optimized for interactive use. Therefore enclone provides an alternate file structure, which ┃ -┃speeds up enclone overall by up to 50%. To use this, add the argument NH5 to the enclone command ┃ -┃line. This will work so long as you have write permission on input directories. The first time ┃ -┃you run enclone (using given inputs), an alternate file feature_barcode_matrix.bin will be ┃ -┃written; then subsequent invocations will be faster. Once the file has been created, it will ┃ -┃always be used, regardless of whether NH5 is used. However, we may occasionally change the format┃ -┃of the alternate file. If do that, then if you have previously generated the file, then it will ┃ -┃be rewritten when you invoke enclone for that dataset. Like with other enclone command-line ┃ -┃options, if you want NH5 on all the time, you can set the environment variable ENCLONE_NH5. ┃ -┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - █ 1 █ To point directly at input files on the command line, use e.g. TCR=/home/jdoe/runs/dataset345 or likewise for BCR. A more complicated syntax is allowed in which commas, colons and semicolons diff --git a/pages/auto/history.html b/pages/auto/history.html index 020ead45ab..88be6e5b16 100644 --- a/pages/auto/history.html +++ b/pages/auto/history.html @@ -65,8 +65,8 @@

    History

    -

    5/9/22: Add ability to create enclone visual sessions from the command line. Please -see enclone visual.

    +

    5/9/22: Add ability to create enclone_visual sessions from the command line. Please +see enclone_visual.

    5/8/22: enclone now runs under Windows, with some limitations, see here.

    @@ -159,9 +159,9 @@

    History

    -

    2/18/22: Introducing enclone visual! This is alpha software for a +

    2/18/22: Introducing enclone_visual! This is alpha software for a graphic user interface (GUI) for enclone, that is implemented initially for Macs. -Please see enclone visual.

    +Please see enclone_visual.

    2/16/22: Add new grouping options, please see enclone help display.

    diff --git a/pages/dev.html.src b/pages/dev.html.src index c1e783bf8d..a9d9a6bff1 100644 --- a/pages/dev.html.src +++ b/pages/dev.html.src @@ -193,16 +193,6 @@ your terminal window to get the change to PATH to take effect. full - -3 -test_vis -many tests of #enclone_visual using screenshots -N/A -1 -none -N/A - - @@ -244,7 +234,6 @@ other people can run the test with their own personal regression test images.touch enclone/enclone_core/defs.rs
    on the Linux server and then cargo b. Otherwise you’ll get an error message. -
  • See the file enclone_visual/src/bin/test_vis.rs.
  • @@ -268,7 +257,6 @@ Otherwise you’ll get an error message. it returned zero exit status, even though when called e.g. from a script, it would return a nonzero value. -
  • Manual tests listed at the bottom of enclone_visual/src/testsuite.rs.
  • @@ -278,7 +266,6 @@ Otherwise you’ll get an error message. There are some other major things that are not tested:
    • Compilation of #enclone under Windows.
    • -
    • Functionality of #enclone_visual under Linux and Windows.
    • Functionality of hdf5 under Windows (which was previously broken).
    diff --git a/pages/index.html.src b/pages/index.html.src index b48c0bb980..a23c7897d9 100644 --- a/pages/index.html.src +++ b/pages/index.html.src @@ -197,26 +197,13 @@ fields you wish to see. #enclone is fast, typically responding in seconds (if run on a single dataset).

    -

    - - - - -
    -There is also a graphical (GUI) version of #enclone, called #enclone_visual, that is -alpha software. To use it, one installs -#enclone as described below and then types enclone VIS from a terminal window -to launch the GUI. Documentation is here. -
    -

    -

    #enclone, in addition to Cell Ranger and Loupe (and in which the core algorithm of #enclone will be integrated at a later point in time), supports the analysis of V(D)J and other data from the -Chromium Single Cell Immune Profiling +Chromium Single Cell Immune Profiling solution.

    @@ -609,11 +596,6 @@ documentation within its online menus. To get started you should:

    #enclone in cellranger everyone - - - enclone visual - everyone - diff --git a/pages/visual.html.src b/pages/visual.html.src deleted file mode 100644 index eb983b4515..0000000000 --- a/pages/visual.html.src +++ /dev/null @@ -1,257 +0,0 @@ -enclone visual - - - -
    - -enclone banner - - - - -

    enclone visual

    - -

    -#enclone_visual is a graphical user -interface (GUI) for #enclone that can be run on a Mac or Linux or Windows computer. It allows for -simultaneous viewing of clonotype tables and graphical objects such as honeycomb plots that -#enclone can create, and has several other features that you may find convenient. -

    - -

    - - -Please note that #enclone_visual is alpha (α) software! - - -
    • Users may encounter bugs that we are unable to fix. This is in part because different -operating system versions may yield different behavior, and we may be unable to replicate such -problems. - -
    • There are a few features of #enclone that are not properly delivered in -#enclone_visual. Notably, clonotype -tables are in black and white rather than color. To fix this, we are waiting on code changes -from developers outside 10x, and do not have a timeline for those changes. - -
    • Because of considerable -variability between Linux configurations, we anticipate that there may be problems with Linux. -Please see the debugging under Linux section, below. -

    - - - -

    Getting started

    - -

    1. To use #enclone_visual, -follow the installation instructions for #enclone. Choose the medium or a larger -option. Then open a terminal window, and type enclone VIS. An -#enclone_visual window should appear.

    - -

    2. The operating system will intercede and ask if you will allow certain kinds of -access. This may include asking for permission to capture the screen, which you should allow, and -then restart your Terminal. -This should be a one-time operation. The reason for needing access is -that upon pushing certain buttons, #enclone_visual will do a screen capture of the -#enclone_visual window and copy that to your clipboard.

    - -

    3. -#enclone_visual is primarily command driven. This means that you still need to formulate an -#enclone command! It also means that #enclone_visual -commands can be reproduced in #enclone, and, for example, scripted. The commands for -#enclone_visual are similar to, but not identical to #enclone commands. There are two differences: -

      -
    • In a plot argument, instead of putting in the name of an image file, you put in the text -gui. This is illustrated below.
    • -
    • For #enclone_visual, -you do not have to quote ("...") special characters, although arguments containing -blanks do still need to be quoted.
    • -
    - - - -

    Read the help!

    - -

    In the #enclone_visual window, you will see a Help button. Please push that button -and read the help text there. This will take you about five minutes, and then you'll -understand how the system works. Some of the behavior is counterintuitive but easily grasped.

    - - - -

    Read the cookbooks!

    - -

    Push the Archive button. You will see the following (without the red coloring -of the Snapshot button, which is how we captured the image): -
    - -
    -If you later save #enclone_visual sessions, they will appear as entries on this page. For now, -there are only two entries, which are built-in cookbooks. Please expand and read the documentation. -Then for each cookbook, in turn, check the restore box, push Dismiss to -return to the main window, and work your way through.

    - - - -

    An example

    - -

    Here we show an example. You would have seen this in the cookbooks, but we show it here too. -(Note that the outputs here may change over time as #enclone is updated.) -Enter this command -enclone BCR=123085 HONEY=out=gui,color=var,u_cell2 in the command box. -This will display a honeycomb plot showing all cells, colored by the variable u_cell2, -which is the UMI count for the second chain (relative to the numbering of columns in a given -clonotype). The "undefined" cells arise from the case where there is no second chain. Note that -you could arrange to instead color by almost any variable that you can imagine! -

    - -

    -You will see something like this: - - -
    -This is the basic view. Now suppose that you want to see only part of this view, for example -just the plot. Push the Pic button. - - -
    -Now if you push the Dismiss button, you'll be back to the main page.

    - -

    Suppose that you now wish to reproduce the same plot from the command line in a terminal -window. In the command enclone BCR=123085 HONEY=out=gui,color=var,u_cell2, -you would change gui to the name of a file (or path), ending with either -.svg or .png, depending which you prefer. For example, you could use -enclone BCR=123085 HONEY=out=plot.svg,color=var,u_cell2 to put the plot output -of the command into a file plot.svg. You could also to add the argument -NOPRINT, if you do not want to see the standard output (clonotype tables) that -enclone generates.

    - - - -

    States and sessions

    - -

    When you run a series of commands in #enclone_visual, -you create a series of states, and you can navigate instantaneously between those states -using the up and down arrows on the right side of the window, which become visible only as you -create multiple states. You can also delete states that you're not interested in, and you can -annotate them with comments.

    - -

    All these states comprise a session. You can save your session by clicking on the -Save button.

    - -

    When you're done, you can push the Exit button to leave #enclone_visual. -If you saved your session, then you can restart #enclone_visual -later, push the Archive button, and then restore your previously saved session. -These saved sessions can also have names and narratives associated to them.

    - - - -

    Creating a session from the command line

    - -

    It is possible to create a session outside #enclone_visual, from the #enclone command -line. For example, this command -

    enclone BCR=123085 PLOT=gui VIS_DUMP SESSION_NAME="123085 test"
    -will create a session in ~/enclone/visual/history which has a single state -corresponding to the given command. The SESSION_NAME argument is optional. -One may also specify e.g. STATE_NARRATIVE="...narrative..." or indirectly -as STATE_NARRATIVE=@filename, and likewise there are versions for -SESSION_NARRATIVE.

    - - - -

    Remote computation (unreleased)

    - -

    There is unreleased code in #enclone_visual -that enables doing "back end" computations on a remote server. This is -something that we could make public if there was sufficient demand. -

    - -

    There are three motivations for this capability: -

      -
    1. You may have datasets on the server, and not want to have to manually move them to your -personal machine. We believe this is the most compelling reason for remote computation.
    2. -
    3. Computation on the remote server might be faster.
    4. -
    5. Remote computation enables direct sharing of sessions between users who can access the same -server, instantaneously and just by pushing a button. This can be a powerful enabler of -collaboration.
    6. -
    -

    - -

    The catch with the remote computation is that for most system configurations, a "magic -incantation" is needed to "jump over" a firewall between your personal machine and the server. -We only know -what this incantation is for our system, and thus some experimentation would be required for yours. -To release this feature we would need to devise general instructions.

    - - - -

    Debugging under Linux

    - -

    On a Linux computer, if you type enclone VIS, and get an error message, let -us know. We provide here followup steps that may be applicable. The idea of these steps is that -the problem may not be in #enclone, but rather lie in upstream software, or be an issue with your -computer.

    - -

    1. The software underlying #enclone_vis uses the GPU on your computer. It is possible -that the GPU is not accessible to this software. -You can try the following two commands as a diagnostic: -

    sudo apt install -y mesa-utils
    -glxinfo | grep Accelerated
    -If when you do this you see -
        Accelerated: no
    -then something is wrong. It may help to reinstall the GPU driver. Unless you solve this problem, -the steps that follow are unlikely to yield useful information.

    - -

    2. To run the next steps, you need to have a current version of Rust on your computer. -First, if Rust is not already installed in your computer, you can install it using -

    sudo apt update
    -sudo apt install cargo
    -Now you can tell what version you have by typing rustc --version. Go to -https://www.rust-lang.org to see what the current version -is. If those are different, you may need to update, using approximately the following steps: -
    -sudo apt remove cargo
    -sudo apt autoremove cargo
    -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    -go with option 1
    -need ~/.cargo/bin to be in path
    -Possibly you can get away without doing these things.

    - -

    3. Now you can test to see if your problem lies in a particular Rust crate called -wgpu, as follows: -

    -git clone https://github.com/gfx-rs/wgpu
    -cd wgpu
    -cargo run --example cube
    -
    -If a cube shows up on your screen, then probably wgpu is working. Otherwise it may -make sense to file an issue at -https://github.com/gfx-rs/wgpu/issues. -For that you should show exactly what you typed and the terminal output, as well as the output of -the command lsb_release -a.

    - -

    4. If wgpu works, then a next step would be to see if there is a problem -in the iced crate. Try this: -

    -git clone https://github.com/hecrj/iced
    -cd iced
    -cargo run --package clock
    -
    -A clock should show up. If not, you could file an issue at -https://github.com/iced-rs/iced/issues, -with details as above.

    - - - -

    Feedback

    - -

    You can send your thoughts to us here: -#enclone@10xgenomics.com. It is also possible for you -to contribute directly to the code and thereby extend capabilities yourself. Regardless, please -let us know if and how you are using #enclone_visual. We are very interested in your experiences! -

    - - - - - diff --git a/scroll_crash/Cargo.toml b/scroll_crash/Cargo.toml deleted file mode 100644 index a759252a18..0000000000 --- a/scroll_crash/Cargo.toml +++ /dev/null @@ -1,39 +0,0 @@ -[package] -name = "scroll_crash" -version = "0.5.219" -authors = ["""David Jaffe , - Nigel Delaney , - Keri Dockter , - Jessica Hamel , - Lance Hepler , - Shaun Jackman , - Sreenath Krishnan , - Meryl Lewis , - Alvin Liang , - Patrick Marks , - Wyatt McDonnell """] -edition = "2018" -license-file = "LICENSE.txt" -publish = false - -# Please do not edit crate versions within this file. Instead edit the file master.toml -# in the root of the enclone repo. - -# [[bin]] -# name = "enclone" -# path = "src/bin/enclone.rs" - -[dependencies] -iced = { git = "https://github.com/hecrj/iced", rev = "3042fa2cb63c651ebed2abe6f4054e61f70b0331", features = ["canvas", "image", "async-std"] } -itertools = "0.10" -lazy_static = "1" -libc = "0.2" -log = "0.4" -nix = { version = "0.27", features = ["signal"] } -perf_stats = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -pretty_trace = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main", features = ["pprof"]} -prost = { version = "0.9", default_features = false, features = ["std", "prost-derive"] } -string_utils = { git = "https://github.com/10XGenomics/enclone_ranger", branch = "main" } -tokio = { version = "1", default-features = false, features = ["io-util", "macros", "rt-multi-thread"] } -tokio-stream = { version = "0.1", default-features = false, features = ["net"] } -tonic = { version = "0.6", default-features = false, features = ["transport", "codegen", "prost"] } diff --git a/scroll_crash/DejaVuLGCSansMono-Bold.ttf b/scroll_crash/DejaVuLGCSansMono-Bold.ttf deleted file mode 100644 index 3913466ea7..0000000000 Binary files a/scroll_crash/DejaVuLGCSansMono-Bold.ttf and /dev/null differ diff --git a/scroll_crash/DejaVuLGCSansMono.ttf b/scroll_crash/DejaVuLGCSansMono.ttf deleted file mode 100644 index 30fce765ac..0000000000 Binary files a/scroll_crash/DejaVuLGCSansMono.ttf and /dev/null differ diff --git a/scroll_crash/LICENSE.txt b/scroll_crash/LICENSE.txt deleted file mode 120000 index 4ab43736a8..0000000000 --- a/scroll_crash/LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -../LICENSE.txt \ No newline at end of file diff --git a/scroll_crash/README b/scroll_crash/README deleted file mode 100644 index 04bedc0e74..0000000000 --- a/scroll_crash/README +++ /dev/null @@ -1,18 +0,0 @@ -This doesn't actually crash. To get an actual crash, checkout this - -commit a013f21b672c22004e3c555b1845fe29b1790d6d -Author: David Jaffe -Date: Sun May 30 06:41:48 2021 -0700 -revert a diff - -and start up enclone COM=... . - -Then enter "d", and start scrolling in the clonotype tables. After about two minutes, -it seg faults, with thirty threads running. - -This was fixed, after a fashion, with - -commit b9b7e5e93a99e9da17537c46d9f2fdece9e2ebd1 (HEAD -> dj/162, origin/dj/162) -Author: David Jaffe -Date: Sun May 30 07:37:31 2021 -0700 -bug workaround diff --git a/scroll_crash/plot.svg b/scroll_crash/plot.svg deleted file mode 100644 index 35ee9fd33e..0000000000 --- a/scroll_crash/plot.svg +++ /dev/null @@ -1,815 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IGHA1 - -IGHA2 - -IGHD - -IGHE - -IGHG1 - -IGHG2 - -IGHG3 - -IGHG4 - -IGHM - -undetermined - - diff --git a/scroll_crash/src/main.rs b/scroll_crash/src/main.rs deleted file mode 100644 index 2e38a6f7b6..0000000000 --- a/scroll_crash/src/main.rs +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use iced::svg::Handle; -use iced::Length::Units; -use iced::{ - button, scrollable, text_input, Align, Button, Column, Container, Element, Font, Length, Row, - Sandbox, Scrollable, Settings, Svg, Text, TextInput, -}; - -const DEJAVU: Font = Font::External { - name: "DEJAVU", - bytes: include_bytes!("../DejaVuLGCSansMono-Bold.ttf"), -}; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[tokio::main] -async fn main() -> Result<(), Box> { - let mut settings = Settings::default(); - let mut window_settings = iced::window::Settings::default(); - window_settings.size = (1100 as u32, 1000 as u32); - settings.window = window_settings; - let _ = Calculator::run(settings); - Ok(()) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[derive(Default)] -struct Calculator { - scroll: scrollable::State, - input: text_input::State, - input_value: String, - output_value: String, - svg_value: String, - button: button::State, -} - -#[derive(Debug, Clone)] -enum Message { - InputChanged(String), - ButtonPressed, -} - -impl Sandbox for Calculator { - type Message = Message; - - fn new() -> Self { - Calculator::default() - } - - fn title(&self) -> String { - String::from("Calculator") - } - - fn update(&mut self, message: Message) { - match message { - Message::InputChanged(value) => self.input_value = value, - Message::ButtonPressed => { - self.svg_value = include_str!("../plot.svg").to_string(); - self.output_value = include_str!("../test.txt").to_string(); - } - } - } - - fn view(&mut self) -> Element { - let text_input = TextInput::new( - &mut self.input, - "", - &self.input_value, - Message::InputChanged, - ) - .padding(10) - .size(20); - - let button = Button::new(&mut self.button, Text::new("Submit")) - .padding(10) - .on_press(Message::ButtonPressed); - - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(12) - .scroller_width(12) - .style(style::Squeak) - .push(Text::new(&self.output_value).font(DEJAVU).size(13)); - - // Display the SVG. - - let svg = Svg::new(Handle::from_memory(self.svg_value.as_bytes().to_vec())) - .width(Units(400)) - .height(Units(400)); - - let content = Column::new() - .spacing(20) - .padding(20) - .max_width(1500) // this governs the max window width upon manual resizing - .push(Row::new().spacing(10).push(text_input).push(button)) - .push(Row::new().spacing(10).push(svg)) - .push( - Row::new() - .height(Length::Units(1000)) // Height of scrollable window, maybe?? - .align_items(Align::Center) - .push(scrollable), - ); - - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -mod style { - - pub struct Squeak; - - use iced::{scrollable, Color}; - - impl scrollable::StyleSheet for Squeak { - fn active(&self) -> scrollable::Scrollbar { - scrollable::Scrollbar { - background: Color::from_rgb(0.75, 0.75, 0.75).into(), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - } - } - - fn hovered(&self) -> scrollable::Scrollbar { - let active = self.active(); - scrollable::Scrollbar { - background: Color { - a: 0.5, - ..Color::from_rgb(0.0, 0.0, 0.0) - } - .into(), - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..active.scroller - }, - ..active - } - } - - fn dragging(&self) -> scrollable::Scrollbar { - let hovered = self.hovered(); - scrollable::Scrollbar { - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..hovered.scroller - }, - ..hovered - } - } - } -} diff --git a/scroll_crash/src/main.rs.old b/scroll_crash/src/main.rs.old deleted file mode 100644 index 490d4d0476..0000000000 --- a/scroll_crash/src/main.rs.old +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use iced::svg::Handle; -use iced::Length::Units; -use iced::{ - button, scrollable, text_input, Align, Button, Color, Column, Container, Element, - Font, HorizontalAlignment, Length, Row, Rule, Sandbox, Scrollable, Settings, Svg, Text, - TextInput, VerticalAlignment, -}; -use iced_aw::{modal, Card, Modal}; -use string_utils::*; - -const DEJAVU: Font = Font::External { - name: "DEJAVU", - bytes: include_bytes!("../DejaVuLGCSansMono-Bold.ttf"), -}; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[tokio::main] -async fn main() -> Result<(), Box> { - let mut settings = Settings::default(); - let mut window_settings = iced::window::Settings::default(); - window_settings.size = (1100 as u32, 1000 as u32); - settings.window = window_settings; - let _ = Calculator::run(settings); - Ok(()) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[derive(Default)] -struct Calculator { - scroll: scrollable::State, - input: text_input::State, - input_value: String, - output_value: String, - svg_value: String, - button: button::State, -} - -#[derive(Debug, Clone)] -enum Message { - InputChanged(String), - ButtonPressed, -} - -impl Sandbox for Calculator { - type Message = Message; - - fn new() -> Self { - Calculator::default() - } - - fn title(&self) -> String { - String::from("Calculator") - } - - fn update(&mut self, message: Message) { - match message { - Message::InputChanged(value) => self.input_value = value, - Message::ButtonPressed => { - self.output_value = include_str!("../test.txt").to_string(); - } - } - } - - fn view(&mut self) -> Element { - let text_input = TextInput::new( - &mut self.input, - "", - &self.input_value, - Message::InputChanged, - ) - .padding(10) - .size(20); - - let button = Button::new(&mut self.button, Text::new("Submit")) - .padding(10) - .on_press(Message::ButtonPressed); - - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(12) - .scroller_width(12) - .style(style::Squeak) - .push(Text::new(&self.output_value).font(DEJAVU).size(13)); - - // Display the user instructions. The height is set because otherwise the text is - // truncated. - - let instructions = Text::new( - "\nEnter one of the following:\n\ - • an enclone command, without the enclone part\n\ - • an clonotype id (number)\n\ - • d, for a demo, same as BCR=123085 MIN_CELLS=5 PLOT_BY_ISOTYPE=gui PLAIN\n\ - • q to quit\n", - ) - .height(Units(125)); - - // Display the SVG. - - let svg = Svg::new(Handle::from_memory(self.svg_value.as_bytes().to_vec())) - .width(Units(300)) - .height(Units(300)); - - let content = Column::new() - .spacing(20) - .padding(20) - .max_width(1500) // this governs the max window width upon manual resizing - .push(Row::new().spacing(10).push(instructions)) - .push(Row::new().spacing(10).push(text_input).push(button)) - .push(Row::new().spacing(10).push(svg)) - .push( - Row::new() - .height(Length::Units(1000)) // Height of scrollable window, maybe?? - .align_items(Align::Center) - .push(scrollable), - ); - - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -mod style { - - pub struct Squeak; - - use iced::{scrollable, Color}; - - impl scrollable::StyleSheet for Squeak { - fn active(&self) -> scrollable::Scrollbar { - scrollable::Scrollbar { - background: Color::from_rgb(0.75, 0.75, 0.75).into(), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - } - } - - fn hovered(&self) -> scrollable::Scrollbar { - let active = self.active(); - scrollable::Scrollbar { - background: Color { - a: 0.5, - ..Color::from_rgb(0.0, 0.0, 0.0) - } - .into(), - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..active.scroller - }, - ..active - } - } - - fn dragging(&self) -> scrollable::Scrollbar { - let hovered = self.hovered(); - scrollable::Scrollbar { - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..hovered.scroller - }, - ..hovered - } - } - } -} diff --git a/scroll_crash/src/main.rs.without_modal b/scroll_crash/src/main.rs.without_modal deleted file mode 100644 index e2209595c4..0000000000 --- a/scroll_crash/src/main.rs.without_modal +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -use iced::svg::Handle; -use iced::Length::Units; -use iced::{ - button, scrollable, text_input, Align, Button, Color, Column, Container, Element, - Font, HorizontalAlignment, Length, Row, Rule, Sandbox, Scrollable, Settings, Svg, Text, - TextInput, VerticalAlignment, -}; -use iced_aw::{modal, Card, Modal}; -use string_utils::*; - -const DEJAVU: Font = Font::External { - name: "DEJAVU", - bytes: include_bytes!("../DejaVuLGCSansMono-Bold.ttf"), -}; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[tokio::main] -async fn main() -> Result<(), Box> { - let mut settings = Settings::default(); - let mut window_settings = iced::window::Settings::default(); - window_settings.size = (1100 as u32, 1060 as u32); - settings.window = window_settings; - let _ = EncloneVisual::run(settings); - Ok(()) -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[derive(Default)] -struct EncloneVisual { - scroll: scrollable::State, - input: text_input::State, - input_value: String, - output_value: String, - svg_value: String, - button: button::State, - - // open_state: button::State, - // modal_state: modal::State, - // last_message: Option, -} - -#[derive(Debug, Clone)] -enum Message { - InputChanged(String), - ButtonPressed, - // OpenModal, - // CloseModal, - // CancelButtonPressed, -} -/* -#[derive(Default)] -struct ModalState { - cancel_state: button::State, -} -*/ - -impl Sandbox for EncloneVisual { - type Message = Message; - - fn new() -> Self { - EncloneVisual::default() - } - - fn title(&self) -> String { - String::from("EncloneVisual") - } - - fn update(&mut self, message: Message) { - match message { - // Message::OpenModal => self.modal_state.show(true), - // Message::CloseModal => self.modal_state.show(false), - // Message::CancelButtonPressed => self.modal_state.show(false), - Message::InputChanged(ref value) => self.input_value = value.to_string(), - Message::ButtonPressed => { - self.output_value = include_str!("../test.txt").to_string(); - } - } - // self.last_message = Some(message) - } - - fn view(&mut self) -> Element { - let text_input = TextInput::new( - &mut self.input, - "", - &self.input_value, - Message::InputChanged, - ) - .padding(10) - .size(14); - - let button = Button::new(&mut self.button, Text::new("Submit")) - .padding(10) - .on_press(Message::ButtonPressed); - - let scrollable = Scrollable::new(&mut self.scroll) - .width(Length::Fill) - .height(Length::Units(100)) - .scrollbar_width(12) - .scroller_width(12) - .style(style::Squeak) - .push(Text::new(&self.output_value).font(DEJAVU).size(13)); - - // Display the SVG. - - let svg = Svg::new(Handle::from_memory(self.svg_value.as_bytes().to_vec())) - .width(Units(400)) - .height(Units(400)); - - let content = Column::new() - .spacing(20) - .padding(20) - .max_width(1500) // this governs the max window width upon manual resizing - /* - .push(Row::new().spacing(10).align_items(Align::Center).push( - Button::new(&mut self.open_state, Text::new("Help")).on_press(Message::OpenModal), - )) - */ - .push(Row::new().spacing(10).push(text_input).push(button)) - .push(Row::new().spacing(10).push(svg)) - .push(Rule::horizontal(10).style(style::RuleStyle)) - .push( - Row::new() - .height(Length::Units(1000)) // Height of scrollable window, maybe?? - .align_items(Align::Center) - .push(scrollable), - ); - - /* - use iced_aw::style::{ - card::{Style, StyleSheet}, - colors, - }; - - #[derive(Clone, Copy)] - pub struct Gerbil; - - impl StyleSheet for Gerbil { - fn active(&self) -> Style { - Style { - background: iced::Background::Color(Color::from_rgb(0.9, 1.0, 0.9)), - border_width: 0.0, - border_color: iced::Color::from_rgb(1.0, 1.0, 1.0), - head_background: iced::Background::Color(Color::from_rgb(0.9, 1.0, 0.9)), - head_text_color: colors::WHITE, - close_color: colors::WHITE, - ..Style::default() - } - } - } - - let style = Gerbil; - - let version = "0.00000000000000000000000000000000000001"; - let version_float = format!("1e-{}", -version.force_f64().log10()); - Modal::new(&mut self.modal_state, content, move |state| { - Card::new( - Text::new(""), - Text::new(&format!( - "Welcome to enclone visual {} = {}!\n\n\ - Please type bit.ly/enclone in a browser to learn more about enclone.\n\n\ - To use enclone visual, type in the box \ - (see below)\nand then push the Submit button. Here are the things \ - that you can type:\n\n\ - • an enclone command, without the enclone part\n\ - • an clonotype id (number)\n\ - • d, for a demo, same as BCR=123085 MIN_CELLS=5 PLOT_BY_ISOTYPE=gui\n\ - • q to quit\n\n\ - Major limitations of this version:\n\ - 1. There is no color in the clonotype tables.\n\ - 2. Text in plots does not show up.\n\ - 3. Cutting and pasting from clonotype tables doesn't work.\n\ - 4. Long commands are hard to work with in the input box.\n\ - 5. Very wide clonotype tables wrap, making them unintelligible, and \ - only solvable by window resizing, and sometimes not that.", - version, version_float, - )) - .height(Units(450)) - .vertical_alignment(VerticalAlignment::Center), - ) - .style(style) - .foot( - Row::new().spacing(10).push( - Button::new( - &mut state.cancel_state, - Text::new("Dismiss").horizontal_alignment(HorizontalAlignment::Left), - ) - // .width(Length::Fill) - .on_press(Message::CancelButtonPressed), - ), - ) - .width(Units(1100)) - .height(Units(1060)) - .on_close(Message::CloseModal) - .into() - }) - .backdrop(Message::CloseModal) - .on_esc(Message::CloseModal) - .into() - */ - - Container::new(content) - .width(Length::Fill) - .height(Length::Fill) - .center_x() - .center_y() - .into() - - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -mod style { - - pub struct RuleStyle; - - impl iced::rule::StyleSheet for RuleStyle { - fn style(&self) -> iced::rule::Style { - iced::rule::Style { - color: Color::from_rgb(0.0, 1.0, 1.0), - width: 3, - radius: 1.0, - fill_mode: iced::rule::FillMode::Percent(100.0), - } - } - } - - pub struct Squeak; - - use iced::{scrollable, Color}; - - impl scrollable::StyleSheet for Squeak { - fn active(&self) -> scrollable::Scrollbar { - scrollable::Scrollbar { - background: Color::from_rgb(0.75, 0.75, 0.75).into(), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - border_radius: 2.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - } - } - - fn hovered(&self) -> scrollable::Scrollbar { - let active = self.active(); - scrollable::Scrollbar { - background: Color { - a: 0.5, - ..Color::from_rgb(0.0, 0.0, 0.0) - } - .into(), - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..active.scroller - }, - ..active - } - } - - fn dragging(&self) -> scrollable::Scrollbar { - let hovered = self.hovered(); - scrollable::Scrollbar { - scroller: scrollable::Scroller { - color: Color::from_rgb(0.0, 0.0, 0.0), - ..hovered.scroller - }, - ..hovered - } - } - } -} diff --git a/scroll_crash/test.txt b/scroll_crash/test.txt deleted file mode 100644 index 5c692046b2..0000000000 --- a/scroll_crash/test.txt +++ /dev/null @@ -1,955 +0,0 @@ - -CLONOTYPE = 187 CELLS -┌───────────┬───────────────────────────────────────────────────┬────────────────────────────────────┬────────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ CHAIN 3 │ -│ │ 88|IGHV1-69D ◆ 57|IGHJ5 │ 359|IGLV3-21 ◆ 309|IGLJ1 │ 351|IGLV3-10 ◆ 311|IGLJ2 │ -│ ├───────────────────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────┤ -│ │ 11111 11111111111111111111 │ 11111111111111 │ 1 1111111111111 │ -│ │ 3556788900011 11111122222222223333 │ 566 00000111111111 │ 458990 0000011111111 │ -│ │ 1139734323613 45678901234567890123 │ 626 56789012345678 │ 483264 5678901234567 │ -│ │ ════════CDR3════════ │ ═════CDR3═════ │ ═════CDR3════ │ -│reference │ KASINQGSSSSV◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ KVY CQVWDSS◦◦◦◦◦◦◦ │ AGSIQY CYSTD◦◦◦◦◦◦◦◦ │ -│donor ref │ KASINQGSSSSV◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ KVY CQVWDSS◦◦◦◦◦◦◦ │ AGSIQY CYSTD◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────────────┼────────────────────────────────────┼────────────────────────────────────┤ -│# n │ xxxxxxxxxxxxx ..x....x............ u const │ xxx ....xx........ u const │ xxxxxx ...x..x....x. u const│ -│1 147 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 1565 IGHG1 │ KVY CQVWDSSSDHPYVF 4072 IGLC1 │ AGSIQY CYSTDSSGNLVVF 5036 IGLC2│ -│2 9 │ TASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 43 IGHG1 │ KVY CQVWDVSSDHPYVF 74 IGLC1 │ AGSIQY CYSADSTGNLVVF 130 IGLC2│ -│3 2 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 2585 IGHG1 │ KVY CQVWDNSSDHPYVF 5955 IGLC1 │ AGSIQY CYSTDSSGNLVVF 7838 IGLC2│ -│4 2 │ KASINQGSSSSVY CARDSWYTSGRNTPNWFDPW 2099 IGHG1 │ KVY CQVWDSSSDHPYVF 6470 IGLC1 │ AGSIQY CYSTDSSGNLVVF 6578 IGLC2│ -│5 2 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 49 IGHG1 │ KVY CQVWDVSSDHPYVF 68 IGLC1 │ AGSIQY CYSADSTGNLVVF 100 IGLC2│ -│6 2 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 34 IGHG1 │ KVY CQVWDSSSDHPYVF 573 IGLC1 │ AGSIQY CYSTDSSGNLVVF 524 IGLC2│ -│7 2 │ KASINQDSSSSVY CARDSWYSSGRNTPNWFDPW 33 IGHG1 │ KVY CQVWDSSSDHPYVF 1096 IGLC1 │ AGSIQY CYSTDSSGNLVVF 868 IGLC2│ -│8 1 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 5899 IGHG1 │ KVY CQVWDNSSDHPYVF 8480 IGLC1 │ AGRIQY CYSTDSSGNLVVF 8506 IGLC2│ -│9 1 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 4971 IGHG1 │ KVY CQVWDNSSDHPYVF 9705 IGLC1 │ AGRVQY CYSTDSSGNLVVF 9548 IGLC2│ -│10 1 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 3970 IGHG1 │ KVF CQVWDSSSDHPYVF 7088 IGLC1 │ AGSIQY CYSTDSSGNLVVF 9740 IGLC2│ -│11 1 │ KGSINQGSSSSVY CARDSWYTSGRNTPNWFDPW 3657 IGHG1 │ KVY CQVWDSSSDHPYVF 11497 IGLC1 │ AGSIQY CYSTDSSGNLVVF 10997 IGLC2│ -│12 1 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 374 IGHG1 │ KVY CQVWDSSSDHPYVF 1176 IGLC1 │ TGSIQY CYSTDSSGNLVVF 1384 IGLC2│ -│13 1 │ KASTNQGSSSSVY CARDSWYSSGRNTPNWFDPW 339 IGHG1 │ KVY CQVWDSSSDHPYVF 3117 IGLC1 │ AGSIQY CYSTDSSGNLVVF 4277 IGLC2│ -│14 1 │ KASIDQGSSSSLY CATDSWYSSGRNTPNWFDPW 230 IGHG1 │ KVY CQVWNSSSDHPYVF 5762 IGLC1 │ TGSIQY CYSIDSSGNLVVF 4720 IGLC2│ -│15 1 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 219 IGHA1 │ KVY CQVWDSSSDHPYVF 1132 IGLC1 │ AGSIQY CYSTDSSGNLVVF 4924 IGLC2│ -│16 1 │ KASINQDSSSSVY CARDSWYSSGRNTPNWFDPW 48 IGHG1 │ KVY CQVWDSSSDHPYVF 1180 IGLC1 │ AGSIQY CYSTDSSGNLVVF 1101 IGLC2│ -│17 1 │ TASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 36 IGHG1 │ KVY CQVWDVSSDHPYVF 12 IGLC1 │ AGSIQY CYSADSTGNLVVF 20 IGLC2│ -│18 1 │ TASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 36 IGHG1 │ KVY CQVWDVSSDHPYVF 60 IGLC1 │ AGSIQY CYSADSTGNLVVF 73 ? │ -│19 1 │ KGSINQGSSSCVY CARDSWYTSGRNTPNWFDPW 28 IGHG1 │ KVY CQVWDSSSDHPYVF 430 IGLC1 │ AGSIRY CYSTDSSGNLVVF 469 IGLC2│ -│20 1 │ KASINHDSSSSVY CARDSWYSSGRNTPNWFDPW 23 IGHG1 │ KVY CQVWDSSSDHPYVF 1347 IGLC1 │ AGSIQY CYSTDSSGNLVVF 2320 IGLC2│ -│21 1 │ KASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 55 IGHG1 │ KVY CQVWDSSSDHPYVF 860 IGLC1 │ │ -│22 1 │ TASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 16 IGHG1 │ │ AGSIQY CYSADSTGNLVVF 33 IGLC2│ -│23 1 │ TASINQGSSSSVY CARDSWYSSGRNTPNWFDPW 15 IGHG1 │ │ AGSIQY CYSADSTGNLVVF 71 IGLC2│ -│24 1 │ KASTNQGSSSSVY CARDSWYSSGRNTPNWFDPW 3 IGHG1 │ │ AGSIQY CYSTDSSGNLVVF 792 IGLC2│ -│25 1 │ │ KVY CQVWDSSSDHPYVF 282 IGLC1 │ │ -│26 1 │ │ KVY CQVWDVSSDHPYVF 5 IGLC2 │ │ -│27 1 │ │ │ AGSIQY CYSTDSSGNLVVF 81 IGLC2│ -│28 1 │ │ │ AGSIQY CYSADSTGNLVVF 3 ? │ -└───────────┴───────────────────────────────────────────────────┴────────────────────────────────────┴────────────────────────────────────┘ - -CLONOTYPE = 60 CELLS -┌───────────┬─────────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 151.1.2|IGHV3-64D ◆ 55|IGHJ4 │ 349.1.1|IGLV3-1 ◆ 309|IGLJ1│ -│ ├─────────────────────────────────────────┼─────────────────────────────┤ -│ │ 11 1111111111111111 │ 11111111111 │ -│ │ 46778900 1111112222222222 │ 6 00000111111 │ -│ │ 98151856 4567890123456789 │ 9 56789012345 │ -│ │ ══════CDR3══════ │ ════CDR3═══ │ -│reference │ SASSSYRA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ S CQAWD◦◦◦◦◦◦ │ -│donor ref │ SASSSYRA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ T CQAWD◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────────┼─────────────────────────────┤ -│# n │ ........ ................ u const │ . ........... u const │ -│1 54 │ DSTNSSGT CVKDRVTGTITELDYW 305 IGHG1 │ T CQAWDSSAGVF 3907 IGLC1 │ -│2 1 │ DSTNSSGT CVKDRVTGTITELDYW 3 IGHG1 │ │ -│3 5 │ │ T CQAWDSSAGVF 262 IGLC1 │ -└───────────┴─────────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 51 CELLS -┌───────────┬──────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 144.1.2|IGHV3-49 ◆ 53|IGHJ3 │ 279|IGKV3-11 ◆ 217|IGKJ5 │ -│ ├──────────────────────────────────────┼───────────────────────────────┤ -│ │ 1 11111111111111111 1 │ 1111111111111 │ -│ │ 51 11112222222222333 4 │ 6 0001111111111 │ -│ │ 53 67890123456789012 1 │ 4 7890123456789 │ -│ │ ═══════CDR3══════ │ ═════CDR3════ │ -│reference │ VV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W S │ R CQQ◦◦◦◦◦◦◦◦◦◦ │ -│donor ref │ FV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W S │ R CQQ◦◦◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────┼───────────────────────────────┤ -│# n │ .x ................. x u const │ x .x........... u const│ -│1 46 │ FV CTRDRDLRGATDAFDIW S 101 IGHG1 │ R CQQRSNWPPSITF 3769 IGKC │ -│2 3 │ FM CTRDRDLRGATDAFDIW S 73 IGHG1 │ R CHQRSNWPPSITF 7548 IGKC │ -│3 1 │ FV CTRDRDLRGATDAFDIW S 279 IGHG1 │ S CQQRSNWPPSITF 12446 IGKC │ -│4 1 │ FV CTRDRDLRGATDAFDIW S 33 IGHG1 │ R CQQRSNWPPSITF 116 IGKC │ -└───────────┴──────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 49 CELLS -┌───────────┬───────────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 159.1.1|IGHV3-7 ◆ 21|IGHD3-3 ◆ 55|IGHJ4 │ 374|IGLV4-69 ◆ 313|IGLJ3 │ -│ ├───────────────────────────────────────────┼───────────────────────────┤ -│ │ 1 111111111111111111 │ 11111111111 │ -│ │ 571 111111222222222233 │ 11111111122 │ -│ │ 1270 456789012345678901 │ 12345678901 │ -│ │ ═══════CDR3═══════ │ ════CDR3═══ │ -│reference │ EMYA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ CQT◦◦◦◦◦◦◦◦ │ -│donor ref │ EMYA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ CQT◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────┼───────────────────────────┤ -│# n │ xxxx .................. u const │ ........... u const│ -│1 34 │ EMFA CAREPLYYDFWSAYFDYW 863 IGHG1 │ CQTWGTGIRVF 4478 IGLC3│ -│2 2 │ EMFA CAREPLYYDFWSAYFDYW 6378 IGHG1 │ CQTWGTGIRVF 11225 IGLC3│ -│3 2 │ EMYA CAREPLYYDFWSAYFDYW 487 IGHG1 │ CQTWGTGIRVF 653 IGLC3│ -│4 1 │ EMFA CAREPLYYDFWSAYFDYW 315 IGHG1 │ CQTWGTGIRVF 1348 IGLC3│ -│5 1 │ E-FA CAREPLYYDFWSAYFDYW 53 IGHG1 │ CQTWGTGIRVF 833 IGLC3│ -│6 1 │ EMFA CAREPLYYDFWSAYFDYW 15 ? │ CQTWGTGIRVF 890 IGLC3│ -│7 1 │ EMFA CAREPLYYDFWSAYFDYW 2 IGHG1 │ │ -│8 7 │ │ CQTWGTGIRVF 700 IGLC3│ -└───────────┴───────────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 45 CELLS -┌───────────┬────────────────────────────────────────────────────────────┬───────────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 159|IGHV3-7 ◆ 53|IGHJ3 │ 376|IGLV5-37 ◆ 313|IGLJ3 │ -│ ├────────────────────────────────────────────────────────────┼───────────────────────────────────────┤ -│ │ 11 1111111111111111111 │ 11 11111111111 │ -│ │ 23344445667777788999901 1111112222222222333 │ 23556679911 11111122222 │ -│ │ 22324893380156725357903 4567890123456789012 │ 17068902403 45678901234 │ -│ │ ════════CDR3═══════ │ ════CDR3═══ │ -│reference │ LPGAGSSSLNKQEKYVRANLLQ◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ VRSYLYYAAAY CMIW◦◦◦◦◦◦◦ │ -│donor ref │ LPGAGSSSLNKQEKYVRANLLQ◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ VRSYLYYAAAY CMIW◦◦◦◦◦◦◦ │ -├───────────┼────────────────────────────────────────────────────────────┼───────────────────────────────────────┤ -│# n │ xxxxxxxxxxxxxxxxxxxxxxx .x......x........x. u const │ xxxxxxxxxxx ........... u const│ -│1 10 │ LPGAGSSSPNKEEKYVRANLLQY CARDQNFDESSGYDAFDIW 2323 IGHG1 │ VRGYLYYAAAY CMIWPSNAWVF 14585 IGLC2│ -│2 8 │ LPGAGSSSLNKEEKYMRANLLQY CARDQNFDESSGYDAFDIW 3121 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 11855 IGLC2│ -│3 6 │ LPGAKSNSLNKEQKYVRANLLQY CARDQNFDESSGYDAFDIW 1171 IGHG1 │ VRSYLYYTAAY CMIWPSNAWVF 7613 IGLC2│ -│4 5 │ LPGAGSSSLNKEEKYVRANLLQY CARDQNFDESSGYDAFDIW 11 IGHG1 │ VRSYLYYAGAY CMIWPSNAWVF 26 IGLC2│ -│5 2 │ LPGAGSSSLNKEEKYMRANLLQY CARDQNFDESSGYDAFDIW 1005 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 4779 IGLC2│ -│6 1 │ LPGAKSNSLNKEQKYVRANLLQY CARDQNFDESSGYDAFDIW 5862 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 14144 IGLC2│ -│7 1 │ LPGAGSNSLNKEEIYVRANLLEY CTRDQNFDESSGYDAFDIW 4384 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 14621 IGLC2│ -│8 1 │ LPGAGSSSLNKEEKYVRANLLQY CARDQNFDDSSGYDAFDIW 3890 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 15577 IGLC2│ -│9 1 │ LPGAGSSSLNKEEKYVRANLLQY CARDQNFDESSGYDAFDIW 3302 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 5256 IGLC2│ -│10 1 │ LPGAGSSSPNKEEKYVRANLLQY CARDQNFDESSGYDAFDIW 3067 IGHG1 │ VRGYLYYAAAY CMIWPSNAWVF 6429 IGLC2│ -│11 1 │ LPGAGRNSLNKEEKYVRGNLLQY CARDQNFDESSGYDAFDIW 2724 IGHG3 │ VRGYLYYAAAY CMIWPSNAWVF 5775 IGLC2│ -│12 1 │ LPGAGSSSLNKEEKYMRANLLQY CARDQNFDESSGYDAFDIW 2578 IGHA1 │ VRSYLYYAAAY CMIWPSNAWVF 14497 IGLC2│ -│13 1 │ LPGAGSSSPNKEEKYVRANLLQY CARDQNFDESSGYDAFDIW 839 IGHG1 │ VRGYLYYAAAY CMIWPSNAWVF 7816 IGLC2│ -│14 1 │ LPGAGSSSLNKEEKYVRANLLQY CARDQNFDESSGYDAFDIW 404 IGHG1 │ VRGYLYYAAAY CMIWPSNAWVF 3456 IGLC2│ -│15 1 │ LPGAGSSSLNKQEKYVRANLLQY CARDQNFDESSGYDAFDIW 136 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 1023 IGLC2│ -│16 1 │ LPGAGSNSLNKEEIYVRANLLEY CTRDQNFDESSGYDAFDIW 96 IGHG1 │ VRSYLYYAAAY CMIWPSNAWVF 1762 IGLC2│ -│17 1 │ │ VRSYLYYAAAY CMIWPSNAWVF 792 IGLC2│ -│18 1 │ │ VRSYLYYAAAY CMIWPSNAWVF 232 IGLC2│ -│19 1 │ │ VRSYLYYAGAY CMIWPSNAWVF 13 IGLC2│ -└───────────┴────────────────────────────────────────────────────────────┴───────────────────────────────────────┘ - -CLONOTYPE = 37 CELLS -┌───────────┬─────────────────────────────────────┬───────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ CHAIN 3 │ -│ │ 88|IGHV1-69D ◆ 57|IGHJ5 │ 88|IGHV1-69D ◆ 57|IGHJ5 │ 283|IGKV3-20 ◆ 213|IGKJ1 │ -│ ├─────────────────────────────────────┼───────────────────────────────┼─────────────────────────────┤ -│ │ 11111111111111111111 │ 1 111111111111 │ 1 11111111111 │ -│ │ 11111122222222223333 │ 1 111111222222 │ 0 00111111111 │ -│ │ 45678901234567890123 │ 1 456789012345 │ 4 89012345678 │ -│ │ ════════CDR3════════ │ ════CDR3════ │ ════CDR3═══ │ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ V ◦◦◦◦◦◦◦◦◦◦◦W │ A CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ V ◦◦◦◦◦◦◦◦◦◦◦W │ A CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────┼───────────────────────────────┼─────────────────────────────┤ -│# n │ .................... u const │ x ............ u const │ x ........... u const│ -│1 5 │ CARDSWYSSGRNTPNWFDPW 1164 IGHG1 │ V CARENYNWFDPW 553 IGHG1 │ A CQQYGSSSWTF 4113 IGKC │ -│2 2 │ CARDSWYSSGRNTPNWFDPW 158 IGHG1 │ I CARENYNWFDPW 92 IGHG1 │ E CQQYGSSSWTF 395 IGKC │ -│3 25 │ │ V CARENYNWFDPW 1227 IGHG1 │ A CQQYGSSSWTF 6225 IGKC │ -│4 2 │ │ I CARENYNWFDPW 1342 IGHG1 │ A CQQYGSSSWTF 5601 IGKC │ -│5 1 │ │ I CARENYNWFDPW 2526 IGHG1 │ E CQQYGSSSWTF 10027 IGKC │ -│6 1 │ │ V CARENYNWFDPW 2 ? │ │ -│7 1 │ │ V CARENYNWFDPW 4 IGHG1 │ │ -└───────────┴─────────────────────────────────────┴───────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 34 CELLS -┌───────────┬─────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 740.1.1|IGHV4-30-4 ◆ 53|IGHJ3 │ 253|IGKV1D-39 ◆ 217|IGKJ5│ -│ ├─────────────────────────────────────┼───────────────────────────┤ -│ │ 1 1111111111111111 │ 111111111111 │ -│ │ 25690 1111122222222223 │ 011111111112 │ -│ │ 01048 5678901234567890 │ 901234567890 │ -│ │ ══════CDR3══════ │ ════CDR3════ │ -│reference │ LDPSA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQQ◦◦◦◦◦◦◦◦◦ │ -│donor ref │ VGHSA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQQ◦◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────┼───────────────────────────┤ -│# n │ ..... ................ u const │ ............ u const │ -│1 34 │ VGHSA CARRYFGVVADAFDIW 57 IGHM │ CQQSYSTPPITF 207 IGKC │ -└───────────┴─────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 21 CELLS -┌───────────┬──────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 203|IGHV5-51 ◆ 53|IGHJ3 │ 327|IGLV1-47 ◆ 313|IGLJ3 │ -│ ├──────────────────────────────────────┼───────────────────────────────┤ -│ │ 1111111111111111 │ 11111111111 │ -│ │ 6777 1111112222222222 │ 467 00011111111 │ -│ │ 5257 4567890123456789 │ 490 78901234567 │ -│ │ ══════CDR3══════ │ ════CDR3═══ │ -│reference │ WGDR ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ SSN CAAWD◦◦◦◦◦◦ │ -│donor ref │ WGDR ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ SSN CAAWD◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────┼───────────────────────────────┤ -│# n │ x... ................ u const │ ... ........... u const│ -│1 15 │ FAHT CARPKSDYIIDAFDIW 105 IGHG1 │ NRS CAAWDDSLWVF 539 IGLC3│ -│2 1 │ FAHT CARPKSDYIIDAFDIW 8909 IGHA1 │ NRS CAAWDDSLWVF 11086 IGLC3│ -│3 1 │ FAHT CARPKSDYIIDAFDIW 20 IGHG1 │ NRS CAAWDDSLWVF 21 IGLC2│ -│4 1 │ WAHT CARPKSDYIIDAFDIW 15 IGHG1 │ NRS CAAWDDSLWVF 711 IGLC3│ -│5 1 │ FAHT CARPKSDYIIDAFDIW 6 IGHG1 │ NRS CAAWDDSLWVF 5 IGLC1│ -│6 1 │ │ NRS CAAWDDSLWVF 9 IGLC2│ -│7 1 │ │ NRS CAAWDDSLWVF 8 IGLC3│ -└───────────┴──────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 19 CELLS -┌───────────┬──────────────────────────────────────┬─────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 740.1.1|IGHV4-30-4 ◆ 55|IGHJ4 │ 390|IGLV8-61 ◆ 311|IGLJ2 │ -│ ├──────────────────────────────────────┼─────────────────────────────────┤ -│ │ 1 1111111111111 │ 11 111111111111 1 │ -│ │ 255668990 1111122222222 │ 56701 111111122222 3 │ -│ │ 015094148 5678901234567 │ 54452 345678901234 3 │ -│ │ ═════CDR3════ │ ════CDR3════ │ -│reference │ LDSPGKVSA ◦◦◦◦◦◦◦◦◦◦◦◦◦ │ STYAY CVLY◦◦◦◦◦◦◦◦ L │ -│donor ref │ VGSHGKVSA ◦◦◦◦◦◦◦◦◦◦◦◦◦ │ STYAY CVLY◦◦◦◦◦◦◦◦ L │ -├───────────┼──────────────────────────────────────┼─────────────────────────────────┤ -│# n │ ......... .x........... u const │ ..... ............ . u const│ -│1 15 │ VGIHGNLSA CASRKSGNYIIYW 42 IGHG3 │ SSHAY CVLYMGSGIVVF L 52 IGLC2│ -│2 1 │ VGIHGNLSA CASRKSGNYIIYW 17 ? │ SSHAY CVLYMGSGIVVF L 27 IGLC2│ -│3 1 │ VGIHGNLSA CASRKSGNYIIYW 9 IGHG3 │ SSHAY CVLYMGSGIVVF L 6 ? │ -│4 1 │ VGIHGNLSA CVSRKSGNYIIYW 4 IGHG3 │ SSHAY CVLYMGSGIVVF L 6 IGLC2│ -│5 1 │ VGIHGNLSA CASRKSGNYIIYW 6 IGHG3 │ │ -└───────────┴──────────────────────────────────────┴─────────────────────────────────┘ - -CLONOTYPE = 17 CELLS -┌───────────┬───────────────────────────────────────────────────────┬─────────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 194.1.1|IGHV4-59 ◆ 737|IGHJ6 │ 253|IGKV1D-39 ◆ 216|IGKJ4 │ -│ ├───────────────────────────────────────────────────────┼─────────────────────────────────────┤ -│ │ 11 11111111111111111 │ 1 111111111111 │ -│ │ 44455666777788900 11111112222222222 │ 23557770 011111111112 │ -│ │ 27838979089147979105 34567890123456789 │ 96280140 901234567890 │ -│ │ ═══════CDR3══════ │ ════CDR3════ │ -│reference │ HLLSSSQPGYIYSYPIVTLA ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ PVSQYASQ CQQ◦◦◦◦◦◦◦◦◦ │ -│donor ref │ HLLSSSQPGYIYSYPMVTLA ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ PVSQYASQ CQQ◦◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────────────────┼─────────────────────────────────────┤ -│# n │ ...xxxx.x.xxxxx.xxx. ..xx..x.......... u const │ xxxxxxxx ....x....... u const│ -│1 15 │ HLLSSSQAGRITSYPMVTLA CARVRDILTGDYGMDVW 131 IGHG1 │ PVSQYASQ CQQSYSTLSLTF 752 IGKC │ -│2 1 │ HLLSTNQAGRIASHPMVALA CARARDILTGDYGMDVW 1698 IGHG1 │ PVNQHSSQ CQQSFSTLSLTF 17171 IGKC │ -│3 1 │ HLLSSNQAGRINRYPMATVA CARTRDILTGDYGMDVW 128 IGHG1 │ PVNQYARQ CQQSFSTLSLTF 398 IGKC │ -└───────────┴───────────────────────────────────────────────────────┴─────────────────────────────────────┘ - -CLONOTYPE = 16 CELLS -┌───────────┬─────────────────────────────────────┬──────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 122.1.2|IGHV3-23 ◆ 55|IGHJ4 │ 323|IGLV1-44 ◆ 313|IGLJ3 │ -│ ├─────────────────────────────────────┼──────────────────────────────┤ -│ │ 1 1111111111111111 1 │ 1111111111111 │ -│ │ 21 1111112222222222 3 │ 8 0001111111111 │ -│ │ 531 4567890123456789 5 │ 8 7890123456789 │ -│ │ ══════CDR3══════ │ ═════CDR3════ │ -│reference │ SVV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ V │ T CAAWD◦◦◦◦◦◦◦◦ │ -│donor ref │ SLV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ V │ T CAAWD◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────┼──────────────────────────────┤ -│# n │ x.. ................ x u const │ . ............. u const│ -│1 10 │ NLL CAKWRCSGGNCHFDYW L 81 IGHG1 │ P CAAWDDSLNGWVF 1929 IGLC3│ -│2 1 │ NLL CAKWRCSGGNCHFDYW L 65 IGHA1 │ P CAAWDDSLNGWVF 624 IGLC3│ -│3 1 │ SLL CAKWRCSGGNCHFDYW L 32 IGHG1 │ P CAAWDDSLNGWVF 111 IGLC3│ -│4 1 │ NLL CAKWRCSGGNCHFDYW V 25 IGHG1 │ P CAAWDDSLNGWVF 1356 IGLC3│ -│5 1 │ NLL CAKWRCSGGNCHFDYW L 7 IGHG1 │ P CAAWDDSLNGWVF 17 IGLC2│ -│6 2 │ │ P CAAWDDSLNGWVF 607 IGLC3│ -└───────────┴─────────────────────────────────────┴──────────────────────────────┘ - -CLONOTYPE = 15 CELLS -┌───────────┬────────────────────────────────────┬──────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 67.1.1|IGHV1-2 ◆ 54|IGHJ4 │ 225|IGKV1-27 ◆ 213|IGKJ1│ -│ ├────────────────────────────────────┼──────────────────────────┤ -│ │ 1111111111111 │ 11111111111 │ -│ │ 44578 1111112222222 │ 01111111111 │ -│ │ 26025 4567890123456 │ 90123456789 │ -│ │ ═════CDR3════ │ ════CDR3═══ │ -│reference │ ATYNW ◦◦◦◦◦◦◦◦◦◦◦◦◦ │ CQK◦◦◦◦◦◦◦◦ │ -│donor ref │ ATYNR ◦◦◦◦◦◦◦◦◦◦◦◦◦ │ CQK◦◦◦◦◦◦◦◦ │ -├───────────┼────────────────────────────────────┼──────────────────────────┤ -│# n │ ..... ............. u const │ ........... u const│ -│1 15 │ TTFKR CAREYSSRMNDYW 1514 IGHG1 │ CQKYNSALWTF 8225 IGKC │ -└───────────┴────────────────────────────────────┴──────────────────────────┘ - -CLONOTYPE = 13 CELLS -┌───────────┬──────────────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 88|IGHV1-69D ◆ 56|IGHJ5 │ 233|IGKV1-5 ◆ 213|IGKJ1 │ -│ ├──────────────────────────────────────────────┼─────────────────────────────┤ -│ │ 111 1111111111111111 │ 11111111111 │ -│ │ 234456789001 1111112222222222 │ 7 01111111111 │ -│ │ 878932242071 4567890123456789 │ 1 90123456789 │ -│ │ ══════CDR3══════ │ ════CDR3═══ │ -│reference │ EKSSSGIGEEEV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ K CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ EKSSSGIGEEEV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ K CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────────────┼─────────────────────────────┤ -│# n │ xxxxxxx.xx.. ................ u const │ . ........... u const│ -│1 2 │ DRSSNGLGEDDI CARDLGGRYYGSKDPW 3083 IGHG1 │ E CQQYNSYSWTF 12484 IGKC │ -│2 1 │ ERTSNGLGEDDI CARDLGGRYYGSKDPW 4733 IGHG1 │ E CQQYNSYSWTF 12027 IGKC │ -│3 1 │ DRSSNGLGEDDI CARDLGGRYYGSKDPW 3932 IGHG1 │ E CQQYNSYSWTF 9476 IGKC │ -│4 1 │ DRSSNGLGEEDI CARDLGGRYYGSKDPW 3416 IGHG1 │ E CQQYNSYSWTF 12405 IGKC │ -│5 1 │ DRSSSGLGEDDI CARDLGGRYYGSKDPW 3345 IGHG1 │ E CQQYNSYSWTF 6365 IGKC │ -│6 1 │ DKSSNGLGEDDI CARDLGGRYYGSKDPW 3279 IGHG1 │ E CQQYNSYSWTF 2867 IGKC │ -│7 1 │ EKSSSGLGEDDI CARDLGGRYYGSKDPW 1809 IGHG1 │ E CQQYNSYSWTF 2810 IGKC │ -│8 1 │ DRSSSGLGEDDI CARDLGGRYYGSKDPW 1253 IGHG1 │ E CQQYNSYSWTF 1837 IGKC │ -│9 1 │ DKSSSGLGEDDI CARDLGGRYYGSKDPW 677 IGHG1 │ E CQQYNSYSWTF 2435 IGKC │ -│10 1 │ EKSSSGIGEDDI CARDLGGRYYGSKDPW 382 IGHG1 │ E CQQYNSYSWTF 881 IGKC │ -│11 1 │ EKSSNGLGEDDI CARDLGGRYYGSKDPW 73 IGHG1 │ E CQQYNSYSWTF 294 IGKC │ -│12 1 │ EKSSNGIGEEDI CARDLGGRYYGSKDPW 72 IGHG1 │ E CQQYNSYSWTF 249 IGKC │ -└───────────┴──────────────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 11 CELLS -┌───────────┬─────────────────────────────────────────────┬─────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 120|IGHV3-21 ◆ 11|IGHD1-7 ◆ 53|IGHJ3 │ 225|IGKV1-27 ◆ 216|IGKJ4 │ -│ ├─────────────────────────────────────────────┼─────────────────────────────────┤ -│ │ 1 1111111111111111111111 │ 11111111111 │ -│ │ 2477790 1111112222222222333333 │ 23334679 01111111111 │ -│ │ 0901367 4567890123456789012345 │ 00160628 90123456789 │ -│ │ ═════════CDR3═════════ │ ════CDR3═══ │ -│reference │ VSSSSSE ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ RSSVVKAS CQK◦◦◦◦◦◦◦◦ │ -│donor ref │ VSSSSSE ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ RSSVVKAS CQK◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────────────┼─────────────────────────────────┤ -│# n │ ....... ...................... u const │ ........ ........... u const│ -│1 9 │ VISGGAG CVRDEGGARPNKWNYEGAFDIW 38 IGHG1 │ SFFIIKAG CQKYDSAPLTF 51 IGKC │ -│2 1 │ VISGGAG CVRDEGGARPNKWNYEGAFDIW 12 ? │ SFFIIKAG CQKYDSAPLTF 19 IGKC │ -│3 1 │ VISGGAG CVRDEGGARPNKWNYEGAFDIW 3 IGHG1 │ │ -└───────────┴─────────────────────────────────────────────┴─────────────────────────────────┘ - -CLONOTYPE = 11 CELLS -┌───────────┬───────────────────────────────────────┬─────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ CHAIN 3 │ -│ │ 67.1.1|IGHV1-2 ◆ 55|IGHJ4 │ 281|IGKV3-15 ◆ 214|IGKJ2 │ 281|IGKV3-15 ◆ 214|IGKJ2 │ -│ ├───────────────────────────────────────┼─────────────────────────────────┼───────────────────────────────┤ -│ │ 11 1111111111111111 │ 11111111 │ 11111111 │ -│ │ 478900 1111112222222222 │ 3388999 00011111 │ 33488999 00011111 │ -│ │ 265502 4567890123456789 │ 2659789 78901234 │ 26459789 78901234 │ -│ │ ══════CDR3══════ │ ══CDR3══ │ ══CDR3══ │ -│reference │ ATWSES ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ VEGELQS CQQ◦◦◦◦◦ │ VEAGELQS CQQ◦◦◦◦◦ │ -│donor ref │ ATRSES ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ VEGELQS CQQ◦◦◦◦◦ │ VEAGELQS CQQ◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────┼─────────────────────────────────┼───────────────────────────────┤ -│# n │ xx.xxx .x.......x.x.... u const │ xxxxxxx ........ u const │ xxxxxxxx ........ u const│ -│1 1 │ ASRSES CERESVVGLLPMFDYW 530 IGHG1 │ VDGELQS CQQFPSTF 1221 IGKC │ VDVGDLEP CQQFPSTF 871 IGKC │ -│2 1 │ ATRIET CARESVVGLLPIFDYW 256 IGHG1 │ VEVELEP CQQFPSTF 479 IGKC │ VEAVELQS CQQFPSTF 946 IGKC │ -│3 1 │ ATRSES CARESVVGLLPIFDYW 219 IGHG1 │ VEGDLEP CQQFPSTF 453 IGKC │ VEAGELQS CQQFPSTF 908 IGKC │ -│4 4 │ ATRSES CARESVVGLLPIFDYW 162 IGHG1 │ VEGELQS CQQFPSTF 317 IGKC │ │ -│5 3 │ ATRIET CARESVVGLLPIFDYW 39 IGHG1 │ VEVELQS CQQFPSTF 339 IGKC │ │ -│6 1 │ ATRSES CARESVVGLLPIFDYW 145 IGHG1 │ VEEELQS CQQFPSTF 166 IGKC │ │ -└───────────┴───────────────────────────────────────┴─────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 11 CELLS -┌───────────┬───────────────────────────────────────────┬──────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 199|IGHV5-10-1 ◆ 20|IGHD3-22 ◆ 53|IGHJ3 │ 357|IGLV3-19 ◆ 311|IGLJ2 │ -│ ├───────────────────────────────────────────┼──────────────────────────────────┤ -│ │ 1 11111111111111111111 │ 1111111111111 │ -│ │ 3455770 11111122222222223333 │ 14689 0000011111111 │ -│ │ 0937275 45678901234567890123 │ 27530 5678901234567 │ -│ │ ════════CDR3════════ │ ═════CDR3════ │ -│reference │ KSSQSNK ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ LSISL CN◦◦◦◦◦◦◦◦◦◦◦ │ -│donor ref │ KSSQSNK ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ LSISL CN◦◦◦◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────┼──────────────────────────────────┤ -│# n │ ....... .................... u const │ ..... ............. u const│ -│1 8 │ KNTHPKT CARLGVYYDSSGYHDAFDIW 41 IGHG1 │ LNNRM CNSRDSSGNHLVF 1097 IGLC2│ -│2 3 │ │ LNNRM CNSRDSSGNHLVF 699 IGLC2│ -└───────────┴───────────────────────────────────────────┴──────────────────────────────────┘ - -CLONOTYPE = 10 CELLS -┌───────────┬───────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 106|IGHV3-11 ◆ 737|IGHJ6 │ 331|IGLV1-51 ◆ 309|IGLJ1 │ -│ ├───────────────────────────────────────┼─────────────────────────────┤ -│ │ 11111111111111111 │ 1111111111111 │ -│ │ 24677 11111122222222223 │ 5 0001111111111 │ -│ │ 26557 45678901234567890 │ 8 7890123456789 │ -│ │ ═══════CDR3══════ │ ═════CDR3════ │ -│reference │ LTWYN ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ L CGTWD◦◦◦◦◦◦◦◦ │ -│donor ref │ LTWYN ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ L CGTWD◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────┼─────────────────────────────┤ -│# n │ ..x.. ................. u const │ . ............. u const│ -│1 9 │ LIWYN CARDRIAGRFGYGMDVW 175 IGHG1 │ V CGTWDGSLSAYVL 990 IGLC1│ -│2 1 │ LICYN CARDRIAGRFGYGMDVW 8 IGHG1 │ V CGTWDGSLSAYVL 7 IGLC1│ -└───────────┴───────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 10 CELLS -┌───────────┬───────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 142|IGHV3-48 ◆ 54|IGHJ4 │ 277|IGKV2D-30 ◆ 217|IGKJ5│ -│ ├───────────────────────────────────────┼───────────────────────────┤ -│ │ 11 111111111111 │ 11111111111 │ -│ │ 345777901 111111222222 │ 11111111222 │ -│ │ 371156261 456789012345 │ 23456789012 │ -│ │ ════CDR3════ │ ════CDR3═══ │ -│reference │ GFESTINAV ◦◦◦◦◦◦◦◦◦◦◦◦ │ CMQ◦◦◦◦◦◦◦◦ │ -│donor ref │ GFESTINAV ◦◦◦◦◦◦◦◦◦◦◦◦ │ CMQ◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────┼───────────────────────────┤ -│# n │ ......x.. ............ u const │ ........... u const │ -│1 9 │ GFSGSRNDV CARGLTGHPGVW 2700 IGHG1 │ CMQGTHWPITF 9672 IGKC │ -│2 1 │ GFSGSRNDV CARGLTGHPGVW 265 IGHG1 │ CMQGTHWPITF 746 IGKC │ -└───────────┴───────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 9 CELLS -┌───────────┬─────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 126|IGHV3-33 ◆ 737|IGHJ6 │ 273|IGKV2D-28 ◆ 213|IGKJ1│ -│ ├─────────────────────────────────┼───────────────────────────┤ -│ │ 11111111111111111 │ 11111111111 │ -│ │ 11111122222222223 │ 11111111222 │ -│ │ 45678901234567890 │ 23456789012 │ -│ │ ═══════CDR3══════ │ ════CDR3═══ │ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CMQ◦◦◦◦◦◦◦◦ │ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CMQ◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────┼───────────────────────────┤ -│# n │ ................. u const │ ........... u const │ -│1 9 │ CARGYEDFTMKYGMDVW 166 IGHG1 │ CMQALQTPQTF 398 IGKC │ -└───────────┴─────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 9 CELLS -┌───────────┬───────────────────────────────────────┬────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 120|IGHV3-21 ◆ 737|IGHJ6 │ 381|IGLV5-45 ◆ 313|IGLJ3 │ -│ ├───────────────────────────────────────┼────────────────────────────┤ -│ │ 1 11111111111111111111 │ 11111111111 │ -│ │ 671 11111122222222223333 │ 4 11111122222 │ -│ │ 831 45678901234567890123 │ 2 45678901234 │ -│ │ ════════CDR3════════ │ ════CDR3═══ │ -│reference │ SSV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ L CMIW◦◦◦◦◦◦◦ │ -│donor ref │ SSV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ L CMIW◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────┼────────────────────────────┤ -│# n │ ... .................... u const │ . ........... u const│ -│1 6 │ CSV CARAPRGGSGSQYYYGMDVW 22 IGHG1 │ L CMIWHSSAWVF 1367 IGLC3│ -│2 1 │ CSV CARAPRGGSGSQYYYGMDVW 5 IGHG1 │ L CMIWHSSAWVF 10 IGLC7│ -│3 1 │ │ L CMIWHSSAWVF 5 IGLC2│ -│4 1 │ │ L CMIWHSSAWVF 28 IGLC3│ -└───────────┴───────────────────────────────────────┴────────────────────────────┘ - -CLONOTYPE = 9 CELLS -┌───────────┬───────────────────────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 124|IGHV3-30 ◆ 737|IGHJ6 │ 281|IGKV3-15 ◆ 214|IGKJ2 │ -│ ├───────────────────────────────────────────────────────┼───────────────────────────────┤ -│ │ 1111 111111111111111111111 │ 11111111111 │ -│ │ 34457777778890000 111111222222222233333 │ 2356 00011111111 │ -│ │ 54810145686781246 456789012345678901234 │ 2674 78901234567 │ -│ │ ═════════CDR3════════ │ ════CDR3═══ │ -│reference │ SGSGSYSNKYFTYMNLA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ VEQR CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ SGSGSYSNKYFTYMNLA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ VEQR CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────────────────┼───────────────────────────────┤ -│# n │ .....x..x....x..x ..................... u const │ .... ........... u const│ -│1 5 │ SGSASYGKKYITNVNPA CAKANQLLYGGRQYYYGMDVW 184 IGHG1 │ MEQG CQQYNNWPYTF 8347 IGKC │ -│2 3 │ SGSASFGKTYITNLNPV CAKANQLLYGGRQYYYGMDVW 96 IGHG1 │ MEQG CQQYNNWPYTF 275 IGKC │ -│3 1 │ │ MEQG CQQYNNWPYTF 114 IGKC │ -└───────────┴───────────────────────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 8 CELLS -┌───────────┬─────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 124|IGHV3-30 ◆ 53|IGHJ3 │ 331|IGLV1-51 ◆ 313|IGLJ3 │ -│ ├─────────────────────────────────────┼─────────────────────────────┤ -│ │ 111111111111111 1 │ 1111111111111 │ -│ │ 79 111111222222222 3 │ 0001111111111 │ -│ │ 48 456789012345678 0 │ 7890123456789 │ -│ │ ══════CDR3═════ │ ═════CDR3════ │ -│reference │ SY ◦◦◦◦◦◦◦◦◦◦◦◦◦◦W Q │ CGTWD◦◦◦◦◦◦◦◦ │ -│donor ref │ SY ◦◦◦◦◦◦◦◦◦◦◦◦◦◦W Q │ CGTWD◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────┼─────────────────────────────┤ -│# n │ .x ............... . u const │ ............. u const│ -│1 3 │ NF CANFGRGGDVAFDIW P 28 IGHG1 │ CGTWDSSLSAWVF 531 IGLC2│ -│2 3 │ NF CANFGRGGDVAFDIW P 294 IGHG2 │ CGTWDSSLSAWVF 4016 IGLC2│ -│3 1 │ NY CANFGRGGDVAFDIW P 2063 IGHG1 │ CGTWDSSLSAWVF 10908 IGLC2│ -│4 1 │ NF CANFGRGGDVAFDIW P 6 IGHG1 │ CGTWDSSLSAWVF 7 ? │ -└───────────┴─────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 8 CELLS -┌───────────┬──────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 159.1.1|IGHV3-7 ◆ 737|IGHJ6 │ 341|IGLV2-18 ◆ 309|IGLJ1 │ -│ ├──────────────────────────────────────┼───────────────────────────┤ -│ │ 1 1111111111111111111 │ 111111111111 │ -│ │ 1 1111112222222222333 │ 001111111111 │ -│ │ 10 4567890123456789012 │ 890123456789 │ -│ │ ════════CDR3═══════ │ ════CDR3════ │ -│reference │ EA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CSLYT◦◦◦◦◦◦◦ │ -│donor ref │ EA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CSLYT◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────┼───────────────────────────┤ -│# n │ .x ................... u const │ ............ u const│ -│1 6 │ EA CAREYDFANYYYYYGMDVW 90 IGHG1 │ CSLYTSSSTYVF 678 IGLC1│ -│2 1 │ EA CAREYDFANYYYYYGMDVW 140 IGHG1 │ CSLYTSSSTYVF 943 IGLC1│ -│3 1 │ │ CSLYTSSSTYVF 2710 IGLC1│ -└───────────┴──────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 8 CELLS -┌───────────┬──────────────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 194.1.1|IGHV4-59 ◆ 737|IGHJ6 │ 292|IGKV3D-20 ◆ 217|IGKJ5│ -│ ├──────────────────────────────────────────────┼───────────────────────────┤ -│ │ 11 11111111111111111 1 │ 11111111111 │ -│ │ 45677800 11111112222222222 3 │ 7 00111111111 │ -│ │ 27899818705 34567890123456789 4 │ 3 89012345678 │ -│ │ ═══════CDR3══════ │ ════CDR3═══ │ -│reference │ HLLSPYYNILA ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW T │ S CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ HLLSPYYNMLA ◦◦◦◦◦◦◦◦◦◦◦◦GMDVW T │ S CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────────────┼───────────────────────────┤ -│# n │ ........... ................. . u const │ . ........... u const│ -│1 6 │ HLLNARTKMLA CAGSGDIQLWYGGMDVW K 19 IGHG1 │ N CQQYDSSQITF 145 IGKC │ -│2 2 │ │ N CQQYDSSQITF 91 IGKC │ -└───────────┴──────────────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 7 CELLS -┌───────────┬─────────────────────────────────────┬────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 79|IGHV1-46 ◆ 737|IGHJ6 │ 281|IGKV3-15 ◆ 213|IGKJ1 │ -│ ├─────────────────────────────────────┼────────────────────────────┤ -│ │ 11111111111111111111 │ 111111111111 │ -│ │ 11111122222222223333 │ 000111111111 │ -│ │ 45678901234567890123 │ 789012345678 │ -│ │ ════════CDR3════════ │ ════CDR3════ │ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQQ◦◦◦◦◦◦◦◦◦ │ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQQ◦◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────┼────────────────────────────┤ -│# n │ .................... u const │ ............ u const│ -│1 7 │ CARVPYYYDRSYYYYGMDVW 4235 IGHG1 │ CQQYNNWPPWTF 12302 IGKC │ -└───────────┴─────────────────────────────────────┴────────────────────────────┘ - -CLONOTYPE = 7 CELLS -┌───────────┬────────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 146.1.1|IGHV3-53 ◆ 51|IGHJ2 │ 279|IGKV3-11 ◆ 215|IGKJ3 │ -│ ├────────────────────────────────────────┼─────────────────────────────┤ -│ │ 11111111111111111111 │ 1111111111111 │ -│ │ 12 11111112222222222333 │ 0001111111111 │ -│ │ 35 34567890123456789012 │ 7890123456789 │ -│ │ ════════CDR3════════ │ ═════CDR3════ │ -│reference │ ST ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦LW │ CQQ◦◦◦◦◦◦◦◦◦◦ │ -│donor ref │ LS ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦LW │ CQQ◦◦◦◦◦◦◦◦◦◦ │ -├───────────┼────────────────────────────────────────┼─────────────────────────────┤ -│# n │ .. ...........x........ u const │ ............. u const│ -│1 5 │ LS CAREGGVGVVTATDWYFDLW 2988 IGHM │ CQQRSNWPPLFTF 10387 IGKC │ -│2 1 │ LS CAREGGVGVVTTTDWYFDLW 4824 IGHM │ CQQRSNWPPLFTF 12071 IGKC │ -│3 1 │ │ CQQRSNWPPLFTF 108 IGKC │ -└───────────┴────────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬──────────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 203|IGHV5-51 ◆ 22|IGHD3-9 ◆ 737|IGHJ6 │ 253|IGKV1D-39 ◆ 216|IGKJ4│ -│ ├──────────────────────────────────────────┼───────────────────────────┤ -│ │ 1111111111111111111111111 │ 11111111111 │ -│ │ 1111112222222222333333333 │ 01111111111 │ -│ │ 4567890123456789012345678 │ 90123456789 │ -│ │ ═══════════CDR3══════════ │ ════CDR3═══ │ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────────┼───────────────────────────┤ -│# n │ ......................... u const │ ........... u const │ -│1 6 │ CARLYYDILTGYYAEDYYYYGMDVW 1647 IGHG1 │ CQQSYSTPLTF 3598 IGKC │ -└───────────┴──────────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬───────────────────────────────────────────────┬──────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 106|IGHV3-11 ◆ 20|IGHD3-22 ◆ 737|IGHJ6 │ 265|IGKV2-28 ◆ 214|IGKJ2│ -│ ├───────────────────────────────────────────────┼──────────────────────────┤ -│ │ 1 11111111111111111111111 │ 11111111111 │ -│ │ 777791 11111122222222223333333 │ 11111111222 │ -│ │ 356700 45678901234567890123456 │ 23456789012 │ -│ │ ══════════CDR3═════════ │ ════CDR3═══ │ -│reference │ SYTNRA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CMQ◦◦◦◦◦◦◦◦ │ -│donor ref │ SYTNRA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CMQ◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────────┼──────────────────────────┤ -│# n │ ...... ....................... u const │ ........... u const│ -│1 6 │ GTIYRA CARDRIDDSSGYYYAYYYGMDVW 1599 IGHG1 │ CMQALQTPGTF 7256 IGKC │ -└───────────┴───────────────────────────────────────────────┴──────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬──────────────────────────────────────┬──────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 144.1.2|IGHV3-49 ◆ 54|IGHJ4 │ 296|IGKV4-1 ◆ 216|IGKJ4 │ -│ ├──────────────────────────────────────┼──────────────────────────────┤ -│ │ 1111111111111111111 │ 11111111111 │ -│ │ 35 1111222222222233333 │ 245 11111112222 │ -│ │ 15 6789012345678901234 │ 233 34567890123 │ -│ │ ════════CDR3═══════ │ ════CDR3═══ │ -│reference │ QV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ VKN CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ QF ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ VKN CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────┼──────────────────────────────┤ -│# n │ .. ................... u const │ ... ........... u const│ -│1 5 │ KF CSRVFGNSTYYSSRVGGYW 680 IGHG1 │ ERK CQQYYSTPLTF 7756 IGKC │ -│2 1 │ KF CSRVFGNSTYYSSRVGGYW 14 IGHG1 │ │ -└───────────┴──────────────────────────────────────┴──────────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬─────────────────────────────────┬──────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 190|IGHV4-39 ◆ 54|IGHJ4 │ 386|IGLV7-43 ◆ 311|IGLJ2 │ -│ ├─────────────────────────────────┼──────────────────────────────┤ -│ │ 1 111111111111 │ 1 111111111111 │ -│ │ 55891 222222223333 │ 5570 001111111111 │ -│ │ 89149 234567890123 │ 0925 890123456789 │ -│ │ ════CDR3════ │ ════CDR3════ │ -│reference │ SYSVV ◦◦◦◦◦◦◦◦◦◦◦◦ │ GKSE CLLY◦◦◦◦◦◦◦◦ │ -│donor ref │ SYSVV ◦◦◦◦◦◦◦◦◦◦◦◦ │ GKSE CLLY◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────┼──────────────────────────────┤ -│# n │ xxxxx ............ u const │ xxxx .....x....x. u const│ -│1 1 │ SNSVV CARHLQWELPYW 17 IGHG1 │ GKNE CLLYYGGANVVF 29 IGLC2│ -│2 1 │ NYTIV CARHLQWELPYW 9 IGHG1 │ SIND CLLYYGGANVVF 7 ? │ -│3 1 │ NYTIV CARHLQWELPYW 8 IGHG1 │ SIND CLLYYGGANVVF 40 IGLC2│ -│4 1 │ SYSVV CARHLQWELPYW 5 IGHG1 │ GKSD CLLYYSGANVVF 37 IGLC2│ -│5 1 │ SYSVV CARHLQWELPYW 7 IGHG1 │ │ -│6 1 │ NYTIV CARHLQWELPYW 4 IGHG1 │ │ -└───────────┴─────────────────────────────────┴──────────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬────────────────────────────────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ CHAIN 3 │ CHAIN 4 │ -│ │ 740|IGHV4-30-4 ◆ 55|IGHJ4 │ 253|IGKV1D-39 ◆ 215|IGKJ3 │ 253|IGKV1D-39 ◆ 215|IGKJ3 │ 253|IGKV1D-39 ◆ 216|IGKJ4 │ -│ ├────────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────┼───────────────────────────────┤ -│ │ 11 11111111111111111 1 │ 11 11111111111 111 │ 11111111111 111 │ 1 11111111111 │ -│ │ 2245777778899901 11111222222222233 4 │ 13334445556788900 01111111111 222 │ 13334445556 01111111111 222 │ 555790 01111111111 │ -│ │ 0895013783815614 56789012345678901 1 │ 81462891255416724 90123456789 456 │ 81462891255 90123456789 456 │ 125474 90123456789 │ -│ │ ═══════CDR3══════ │ ════CDR3═══ │ ════CDR3═══ │ ════CDR3═══ │ -│reference │ LGSSYIYTYLTVKNK◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ S │ GSAVIQSSSNPSSSSEF CQQ◦◦◦◦◦◦◦◦ KVD │ GSAVIQSSSNP CQQ◦◦◦◦◦◦◦◦ KVD │ SSNSSF CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ LGSSYIYTYLTVKNK◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ S │ GSAVIQSSSNPSSSSEF CQQ◦◦◦◦◦◦◦◦ KVD │ GSAVIQSSSNP CQQ◦◦◦◦◦◦◦◦ KVD │ SSNSSF CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼────────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────┼───────────────────────────────┤ -│# n │ .xx.x.xx.xx.xxxx ......x.x........ x u const │ xx..xxxxx.xxxxxxx ........... xxx u const │ ........... ........... ... u const │ ...... ........... u const│ -│1 1 │ VRGSYVHSSLTVKNRF CARQQDVYTRSWYFDYW S 82 IGHG1 │ GPAVVRNGINPSSSNEV CQQSYFTPFTF EVH 69 IGKC │ GPAVVRNGINP CQQSYFTPFTF EVH 27 IGKC │ │ -│2 1 │ VGSSFVYTSLSVRHKY CARQQDVYNRSWYFDYW S 54 IGHG1 │ GSAVIQSAMNPTSSSEF CQQSYFTPFTF KVD 425 IGKC │ │ AMNTNL CQQSYSTPLTF 32 IGKC │ -│3 1 │ VRGSYVHSSLTVKNRF CARQQDVYTRSWYFDYW S 386 IGHG1 │ GPAVVRNGINPSSGNEV CQQSYFTPFTF EVH 9556 IGKC │ │ │ -│4 1 │ VGSSFVYTSLSVRHKY CARQQDVYNRSWYFDYW S 76 IGHG1 │ GSAVIQSAMNPSSSNEL CQQSYFTPFTF KVD 626 IGKC │ │ │ -│5 1 │ VGSSFVYTSLSVRHKY CARQQDVYNRSWYFDYW S 15 IGHG1 │ GSAVIQSAMNPTSSNEL CQQSYFTPFTF KVD 32 IGKC │ │ │ -│6 1 │ VRGSYVHSSLTVKNRF CARQQDVYTRSWYFDYW S 4 IGHG1 │ │ │ │ -└───────────┴────────────────────────────────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬───────────────────────────────────────────────┬──────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 67.1.1|IGHV1-2 ◆ 55|IGHJ4 │ 283|IGKV3-20 ◆ 213|IGKJ1│ -│ ├───────────────────────────────────────────────┼──────────────────────────┤ -│ │ 11 11111111111111111 │ 1111111 │ -│ │ 123388999911 11111122222222223 │ 57 0011111 │ -│ │ 820615245813 45678901234567890 │ 41 8901234 │ -│ │ ═══════CDR3══════ │ ══CDR3═ │ -│reference │ SLKVKWTISYV◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ AA CQQ◦◦◦◦ │ -│donor ref │ SLKVKRTISYV◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ AA CQQ◦◦◦◦ │ -├───────────┼───────────────────────────────────────────────┼──────────────────────────┤ -│# n │ xxxxx.xxxxxx .........x.x..... u const │ xx ....... u const│ -│1 2 │ SLKVKRTISYVY CAREVEQWLERNTLDYW 531 IGHG1 │ AA CQQPWTF 1226 IGKC │ -│2 1 │ SLKVKRTISYVF CAREVEQWLVRDTLDYW 5529 IGHG1 │ TA CQQPWTF 11854 IGKC │ -│3 1 │ CLEVKRTISYVY CAREVEQWLERNTLDYW 4976 IGHG1 │ AA CQQPWTF 16146 IGKC │ -│4 1 │ SLKVKRTITYVY CAREVEQWLERNTLDYW 4715 IGHG1 │ AT CQQPWTF 16479 IGKC │ -│5 1 │ SLKVKRTFSYVY CAREVEQWLERNTLDYW 791 IGHG1 │ AA CQQPWTF 1569 IGKC │ -└───────────┴───────────────────────────────────────────────┴──────────────────────────┘ - -CLONOTYPE = 6 CELLS -┌───────────┬──────────────────────────────┬────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 88|IGHV1-69D ◆ 55|IGHJ4 │ 381|IGLV5-45 ◆ 311|IGLJ2 │ -│ ├──────────────────────────────┼────────────────────────────┤ -│ │ 1111111111111 │ 11111111111 │ -│ │ 7 1111112222222 │ 2 11111122222 │ -│ │ 1 4567890123456 │ 6 45678901234 │ -│ │ ═════CDR3════ │ ════CDR3═══ │ -│reference │ P ◦◦◦◦◦◦◦◦◦◦◦◦◦ │ S CMIW◦◦◦◦◦◦◦ │ -│donor ref │ P ◦◦◦◦◦◦◦◦◦◦◦◦◦ │ S CMIW◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────┼────────────────────────────┤ -│# n │ x ............. u const │ . ........... u const│ -│1 3 │ P CGWGYYYEPFDYW 43 IGHG1 │ A CMIWHSSASVF 1956 IGLC2│ -│2 3 │ P CGWGYYYEPFDYW 44 IGHG1 │ A CMIWHSSASVF 637 IGLC2│ -└───────────┴──────────────────────────────┴────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬──────────────────────────────────────────┬────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 122.1.2|IGHV3-23 ◆ 737|IGHJ6 │ 265|IGKV2-28 ◆ 214|IGKJ2 │ -│ ├──────────────────────────────────────────┼────────────────────────────┤ -│ │ 11111111111111111111111 │ 11111111111 │ -│ │ 27 11111122222222223333333 │ 67 11111111222 │ -│ │ 35 45678901234567890123456 │ 45 23456789012 │ -│ │ ══════════CDR3═════════ │ ════CDR3═══ │ -│reference │ VS ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ PG CMQ◦◦◦◦◦◦◦◦ │ -│donor ref │ LS ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ PG CMQ◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────────┼────────────────────────────┤ -│# n │ .. ....................... u const │ .. ........... u const│ -│1 5 │ LN CAKDKVPRRSSWSVFDYYGMDVW 138 IGHG1 │ PA CMQALQTPYSF 397 IGKC │ -└───────────┴──────────────────────────────────────────┴────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬───────────────────────────────────────────┬──────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 88|IGHV1-69D ◆ 737|IGHJ6 │ 283|IGKV3-20 ◆ 215|IGKJ3 │ -│ ├───────────────────────────────────────────┼──────────────────────────────────┤ -│ │ 111111111111111111111 │ 11111111111 1 │ -│ │ 7789 111111222222222233333 │ 1125 00111111111 2 │ -│ │ 1612 456789012345678901234 │ 6740 89012345678 3 │ -│ │ ═════════CDR3════════ │ ════CDR3═══ │ -│reference │ PAKE ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ DTTS CQQ◦◦◦◦◦◦◦◦ K │ -│donor ref │ PAKE ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ DTTS CQQ◦◦◦◦◦◦◦◦ K │ -├───────────┼───────────────────────────────────────────┼──────────────────────────────────┤ -│# n │ xxxx ..................... u const │ ...x ........... . u const│ -│1 2 │ PAKE CAVTIFGVRTALPYYYALDVW 2678 IGHG1 │ EIAG CQQYGSSPFTF R 15544 IGKC │ -│2 1 │ PAKK CAVTIFGVRTALPYYYALDVW 1015 IGHG1 │ EIAG CQQYGSSPFTF R 12946 IGKC │ -│3 1 │ PAKE CAVTIFGVRTALPYYYALDVW 359 IGHG1 │ EIAS CQQYGSSPFTF R 1162 IGKC │ -│4 1 │ LTEK CAVTIFGVRTALPYYYALDVW 60 IGHG1 │ EIAG CQQYGSSPFTF R 827 IGKC │ -└───────────┴───────────────────────────────────────────┴──────────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬───────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 98|IGHV2-5 ◆ 57|IGHJ5 │ 349|IGLV3-1 ◆ 311|IGLJ2 │ -│ ├───────────────────────────────────────┼─────────────────────────────┤ -│ │ 11111111111111111111 │ 11111111111 │ -│ │ 8 11111222222222233333 │ 6 00000111111 │ -│ │ 5 56789012345678901234 │ 2 56789012345 │ -│ │ ════════CDR3════════ │ ════CDR3═══ │ -│reference │ S ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ V CQAWD◦◦◦◦◦◦ │ -│donor ref │ S ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ V CQAWD◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────┼─────────────────────────────┤ -│# n │ x .................... u const │ . ........... u const│ -│1 3 │ S CALMGTYCSGDNCYSWFDPW 592 IGHM │ V CQAWDSSVVVF 2995 IGLC2│ -│2 1 │ S CALMGTYCSGDNCYSWFDPW 6218 IGHG1 │ V CQAWDSSVVVF 15182 IGLC2│ -│3 1 │ T CALMGTYCSGDNCYSWFDPW 4033 IGHG1 │ V CQAWDSSVVVF 6777 IGLC2│ -└───────────┴───────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬──────────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 124|IGHV3-30 ◆ 55|IGHJ4 │ 253|IGKV1D-39 ◆ 216|IGKJ4 │ -│ ├──────────────────────────────────────────┼───────────────────────────────┤ -│ │ 1111111111111111111 │ 11111111111 │ -│ │ 45677 1111112222222222333 │ 458 01111111111 │ -│ │ 91859 4567890123456789012 │ 926 90123456789 │ -│ │ ════════CDR3═══════ │ ════CDR3═══ │ -│reference │ SGVNA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ SSS CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ SGVNA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ SSS CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────────┼───────────────────────────────┤ -│# n │ .x... ................... u const │ ..x ........... u const│ -│1 2 │ IGISV CAKDLVAVAGSGGERFDYW 1712 IGHG1 │ TTT CQQSSSTPLTF 17200 IGKC │ -│2 2 │ IGISV CAKDLVAVAGSGGERFDYW 292 IGHG1 │ TTS CQQSSSTPLTF 726 IGKC │ -│3 1 │ IAISV CAKDLVAVAGSGGERFDYW 79 IGHG1 │ TTT CQQSSSTPLTF 252 IGKC │ -└───────────┴──────────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬─────────────────────────────────────────────┬────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 122.1.2|IGHV3-23 ◆ 13|IGHD2-15 ◆ 53|IGHJ3 │ 283|IGKV3-20 ◆ 213|IGKJ1 │ -│ ├─────────────────────────────────────────────┼────────────────────────────────┤ -│ │ 1111111111111111111 │ 11111111111 │ -│ │ 122446 1111112222222222333 │ 13667 00111111111 │ -│ │ 513598 4567890123456789012 │ 96793 89012345678 │ -│ │ ════════CDR3═══════ │ ════CDR3═══ │ -│reference │ GQVFSA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ GELYS CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ GQLFSA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ GELYS CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────────────┼────────────────────────────────┤ -│# n │ ...... ................... u const │ .xxxx ........... u const│ -│1 2 │ VRLLNT CAKDPYCSGGSCLHAFDIW 343 IGHG1 │ GELYS CQQYGSSPETF 2812 IGKC │ -│2 2 │ VRLLNT CAKDPYCSGGSCLHAFDIW 172 IGHG1 │ GDLYS CQQYGSSPETF 250 IGKC │ -│3 1 │ VRLLNT CAKDPYCSGGSCLHAFDIW 27 IGHG1 │ GDINT CQQYGSSPETF 150 IGKC │ -└───────────┴─────────────────────────────────────────────┴────────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬─────────────────────────────────────────┬──────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 740.1.1|IGHV4-30-4 ◆ 737|IGHJ6 │ 279|IGKV3-11 ◆ 215|IGKJ3 │ -│ ├─────────────────────────────────────────┼──────────────────────────────┤ -│ │ 1 111111111111111111 │ 111111111 │ -│ │ 25690 111112222222222333 │ 1377 000111111 │ -│ │ 01048 567890123456789012 │ 7412 789012345 │ -│ │ ═══════CDR3═══════ │ ═══CDR3══ │ -│reference │ LDPSA ◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ TPSN CQQ◦◦◦◦◦◦ │ -│donor ref │ VGHSA ◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ TPSN CQQ◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────────┼──────────────────────────────┤ -│# n │ ..... .................. u const │ ..xx ......... u const│ -│1 3 │ VGHSA CARQGRAGNYYYYGMDVW 1524 IGHG1 │ APYN CQHRSNWPF 15177 IGKC │ -│2 2 │ VGHSA CARQGRAGNYYYYGMDVW 444 IGHG1 │ APSN CQHRSNWPF 3371 IGKC │ -└───────────┴─────────────────────────────────────────┴──────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬─────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 85|IGHV1-69 ◆ 737|IGHJ6 │ 273|IGKV2D-28 ◆ 214|IGKJ2│ -│ ├─────────────────────────────────┼───────────────────────────┤ -│ │ 1111111111111111 │ 11111111111 │ -│ │ 1111112222222222 │ 11111111222 │ -│ │ 4567890123456789 │ 23456789012 │ -│ │ ══════CDR3══════ │ ════CDR3═══ │ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CMQ◦◦◦◦◦◦◦◦ │ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CMQ◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────┼───────────────────────────┤ -│# n │ ................ u const │ ........... u const │ -│1 5 │ CARAGNSGYGQTMDVW 1860 IGHM │ CMQALQTPSTF 4672 IGKC │ -└───────────┴─────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬───────────────────────────────────────────┬─────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 122.1.2|IGHV3-23 ◆ 55|IGHJ4 │ 267|IGKV2-30 ◆ 213|IGKJ1 │ -│ ├───────────────────────────────────────────┼─────────────────────────────┤ -│ │ 1111 11111111111 │ 11111111111 │ -│ │ 25677799990011 11111122222 │ 79 11111111222 │ -│ │ 33815656790612 45678901234 │ 43 23456789012 │ -│ │ ════CDR3═══ │ ════CDR3═══ │ -│reference │ VSAGSTNTLLQAV◦ ◦◦◦◦◦◦◦◦◦◦◦ │ KT CMQ◦◦◦◦◦◦◦◦ │ -│donor ref │ LSAGSTNTLLQAV◦ ◦◦◦◦◦◦◦◦◦◦◦ │ KT CMQ◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────┼─────────────────────────────┤ -│# n │ ......xxx..... ........... u const │ .. ........... u const│ -│1 4 │ LSSASRSTLLQVVF CAKGRSSLDYW 1953 IGHG1 │ MS CMQGTHWPQTF 9526 IGKC │ -│2 1 │ LSSASRSMLLQVVF CAKGRSSLDYW 2553 IGHG1 │ MS CMQGTHWPQTF 8589 IGKC │ -└───────────┴───────────────────────────────────────────┴─────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬─────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 126|IGHV3-33 ◆ 737|IGHJ6 │ 339|IGLV2-14 ◆ 311|IGLJ2 │ -│ ├─────────────────────────────────────┼───────────────────────────────┤ -│ │ 1 11111111111111 │ 111111111111 │ -│ │ 467790 11111122222222 │ 567 001111111111 │ -│ │ 445742 45678901234567 │ 106 890123456789 │ -│ │ ═════CDR3═════ │ ════CDR3════ │ -│reference │ GENYKN ◦◦◦◦◦◦◦◦◦GMDVW │ NPS CSSYTSS◦◦◦◦◦ │ -│donor ref │ GENYKN ◦◦◦◦◦◦◦◦◦GMDVW │ NPS CSSYTSS◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────┼───────────────────────────────┤ -│# n │ ...... .............. u const │ ... ............ u const│ -│1 4 │ EEEYNS CARESAVAGDMDVW 212 IGHG1 │ DPS CSSHTSSSTVIF 3378 IGLC2│ -│2 1 │ │ DPS CSSHTSSSTVIF 13 IGLC2│ -└───────────┴─────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬────────────────────────────────────────────────────────┬─────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 86|IGHV1-69-2 ◆ 55|IGHJ4 │ 337|IGLV2-11 ◆ 311|IGLJ2 │ -│ ├────────────────────────────────────────────────────────┼─────────────────────────────────┤ -│ │ 11 111111111111111111 │ 111111111111 │ -│ │ 22334455666777788801 111111222222222233 │ 44566 001111111111 │ -│ │ 13481202247235618951 456789012345678901 │ 19136 890123456789 │ -│ │ ═══════CDR3═══════ │ ════CDR3════ │ -│reference │ QVAIKVYMGEGEDETKITRV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ TGNAL CCSYAG◦◦◦◦◦◦ │ -│donor ref │ QVAIKVYMGEGEDETKITRV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦ │ TGNAL CCSYAG◦◦◦◦◦◦ │ -├───────────┼────────────────────────────────────────────────────────┼─────────────────────────────────┤ -│# n │ xxxxxxxxxxxx.xxx.xxx ..........xx...... u const │ xxxx. ......x...x. u const│ -│1 1 │ QVAIKVYMGEGEAETKLTRV CATLRGSSWYGDYYFHYW 1798 IGHG1 │ TGNAV CCSYAGSYTLVF 6010 IGLC2│ -│2 1 │ QVTVKISIGEGEAQTKLIRV CATLRGSSWYGDYYFHYW 1727 IGHG1 │ TGNVV CCSYAGSYTLVF 8252 IGLC2│ -│3 1 │ QVAVRVYMGQGAAETRLTKV CATLRGSSWYGEYYFHYW 15 IGHG1 │ TSNVV CCSYAGSYTLVF 133 IGLC2│ -│4 1 │ │ TGNVV CCSYAGSYTLVF 7 IGLC2│ -│5 1 │ │ TGNAV CCSYAGSYTLVF 5 IGLC2│ -└───────────┴────────────────────────────────────────────────────────┴─────────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬───────────────────────────────────────────────────────┬───────────────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 85|IGHV1-69 ◆ 737|IGHJ6 │ 227|IGKV1-33 ◆ 214|IGKJ2 │ -│ ├───────────────────────────────────────────────────────┼───────────────────────────────────────────┤ -│ │ 1111 111111111111111111111 11 │ 111 11111111111 1 │ -│ │ 4577778990001 111111222222222233333 34 │ 5567777899000 01111111111 2 │ -│ │ 5124677261241 456789012345678901234 94 │ 3814578968246 90123456789 6 │ -│ │ ═════════CDR3════════ │ ════CDR3═══ │ -│reference │ GAIGANTKTLSLV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW TS │ YQPNLTGGISEIT CQQ◦◦◦◦◦◦◦◦ E │ -│donor ref │ GAIGANTKTLSLV ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW TS │ YQPNLTGGISEIT CQQ◦◦◦◦◦◦◦◦ E │ -├───────────┼───────────────────────────────────────────────────────┼───────────────────────────────────────────┤ -│# n │ xx........... ..................... .. u const │ ............. ........... . u const│ -│1 3 │ DSVGPNTQILNLV CARAQRHDFWGGYYHYGMDVW TS 93 IGHG1 │ HQPNLAGGVGGVT CQQYDNLPHTF G 502 IGKC │ -│2 1 │ GAVGPNTQILNLV CARAQRHDFWGGYYHYGMDVW TS 3328 IGHG1 │ HQPNLAGGVGGVT CQQYDNLPHTF G 17713 IGKC │ -│3 1 │ │ HQPNLAGGVGGVT CQQYDNLPHTF G 3209 IGKC │ -└───────────┴───────────────────────────────────────────────────────┴───────────────────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬───────────────────────────────────────────┬───────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 124|IGHV3-30 ◆ 737|IGHJ6 │ 219|IGKV1-12 ◆ 216|IGKJ4 │ -│ ├───────────────────────────────────────────┼───────────────────────────────┤ -│ │ 1 111111111111111111111 │ 11111111111 │ -│ │ 770 111111222222222233333 │ 779 01111111111 │ -│ │ 2366 456789012345678901234 │ 028 90123456789 │ -│ │ ═════════CDR3════════ │ ════CDR3═══ │ -│reference │ FGKA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ YAS CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ FGKA ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ YAS CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼───────────────────────────────────────────┼───────────────────────────────┤ -│# n │ xxxx ..................... u const │ xxx ....x...... u const│ -│1 2 │ FGKA CAKTRLSGDYVGDYYYGMDVW 1302 IGHG1 │ YAS CQQANSFPLTF 14847 IGKC │ -│2 1 │ SGNA CAKTRLSGDYVGDYYYGMDVW 464 IGHG1 │ YAR CQQANSFPLTF 16188 IGKC │ -│3 1 │ FGKG CAKTRLSGDYVGDYYYGMDVW 13 IGHG1 │ SAS CQQAHSFPLTF 43 IGKC │ -│4 1 │ │ SAS CQQAHSFPLTF 15 IGKC │ -└───────────┴───────────────────────────────────────────┴───────────────────────────────┘ - -CLONOTYPE = 5 CELLS -┌───────────┬────────────────────────────────────┬──────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 120|IGHV3-21 ◆ 53|IGHJ3 │ 279|IGKV3-11 ◆ 217|IGKJ5│ -│ ├────────────────────────────────────┼──────────────────────────┤ -│ │ 111111111111111111 │ 11111111111 │ -│ │ 23 111111222222222233 │ 00011111111 │ -│ │ 22 456789012345678901 │ 78901234567 │ -│ │ ═══════CDR3═══════ │ ════CDR3═══ │ -│reference │ LP ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQQ◦◦◦◦◦◦◦◦ │ -│donor ref │ LP ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQQ◦◦◦◦◦◦◦◦ │ -├───────────┼────────────────────────────────────┼──────────────────────────┤ -│# n │ .. .................. u const │ ........... u const │ -│1 4 │ LT CARPPAMSGYNRDAFDIW 21 IGHG1 │ CQQRSNWPLTF 20 IGKC │ -│2 1 │ │ CQQRSNWPLTF 40 IGKC │ -└───────────┴────────────────────────────────────┴──────────────────────────┘ - -CLONOTYPE = 4 CELLS -┌───────────┬─────────────────────────────────────────────────────────────┬───────────────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 190.1.1|IGHV4-39 ◆ 737|IGHJ6 │ 281|IGKV3-15 ◆ 216|IGKJ4 │ -│ ├─────────────────────────────────────────────────────────────┼───────────────────────────────────┤ -│ │ 1111111 11111111111111111111 │ 1111111111 │ -│ │ 12255577778889990000112 22222222333333333344 │ 44567777 0001111111 │ -│ │ 67905807890671784689091 23456789012345678901 │ 79590569 7890123456 │ -│ │ ════════CDR3════════ │ ═══CDR3═══ │ -│reference │ LLLSSSKSIYYYNKSVQSKLSV◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ SSYGATGA CQQ◦◦◦◦◦◦◦ │ -│donor ref │ VLLSSSKSIYYYNKSVQSKLSV◦ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ SSYGATGA CQQ◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────────────────────────────┼───────────────────────────────────┤ -│# n │ .xx...xxx.xxxxx.x.xxxxx ...........xx....... u const │ xxxxxxxx ..x.x..... u const│ -│1 1 │ VLVSRNKTVYSSNTSLQSKLRRY CEIMLYNSSGSDYYYDMDVW 4951 IGHG1 │ NSLGATGA CQQYNNWVTF 15982 IGKC │ -│2 1 │ VLLSRNRSIYYYSKSLQSNLTVY CEIMLYNSSGSDYYYDMDVW 102 IGHG1 │ SSYSATGT CQQYNNWVTF 230 IGKC │ -│3 1 │ VLVSRNKTVYSSNTSLQSKLRRY CEIMLYNSSGSDYYYDMDVW 20 IGHG1 │ NSLSATGT CQQYNNWVTF 123 IGKC │ -│4 1 │ VLLSRNKSIYYYNKSLHSRLSVF CEIMLYNSSGSDYYYDMDVW 9 IGHG1 │ SSYSATGT CQQYSNWVTF 15 IGKC │ -└───────────┴─────────────────────────────────────────────────────────────┴───────────────────────────────────┘ - -CLONOTYPE = 4 CELLS -┌───────────┬─────────────────────────────────────────┬───────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 120|IGHV3-21 ◆ 16|IGHD2-8 ◆ 737|IGHJ6 │ 225|IGKV1-27 ◆ 216|IGKJ4 │ -│ ├─────────────────────────────────────────┼───────────────────────────┤ -│ │ 111111111111111111111111 │ 11111111111 │ -│ │ 111111222222222233333333 │ 01111111111 │ -│ │ 456789012345678901234567 │ 90123456789 │ -│ │ ══════════CDR3══════════ │ ════CDR3═══ │ -│reference │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQK◦◦◦◦◦◦◦◦ │ -│donor ref │ ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQK◦◦◦◦◦◦◦◦ │ -├───────────┼─────────────────────────────────────────┼───────────────────────────┤ -│# n │ ........................ u const │ ........... u const│ -│1 4 │ CARDPEDIVLMVYAMGGNYGMDVW 1640 IGHG1 │ CQKYNSAPRTF 11655 IGKC │ -└───────────┴─────────────────────────────────────────┴───────────────────────────┘ - -CLONOTYPE = 4 CELLS -┌───────────┬──────────────────────────────────────────┬──────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 116|IGHV3-20 ◆ 32|IGHD6-13 ◆ 737|IGHJ6 │ 279|IGKV3-11 ◆ 216|IGKJ4│ -│ ├──────────────────────────────────────────┼──────────────────────────┤ -│ │ 11111111111111111111111 │ 111111111111 │ -│ │ 4 11111122222222223333333 │ 000111111111 │ -│ │ 0 45678901234567890123456 │ 789012345678 │ -│ │ ══════════CDR3═════════ │ ════CDR3════ │ -│reference │ F ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQQ◦◦◦◦◦◦◦◦◦ │ -│donor ref │ F ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦GMDVW │ CQQ◦◦◦◦◦◦◦◦◦ │ -├───────────┼──────────────────────────────────────────┼──────────────────────────┤ -│# n │ . ....................... u const │ ............ u const│ -│1 4 │ C CARVLSGRIAAAGTYYYYGMDVW 66 IGHG1 │ CQQRSNWPPLTF 257 IGKC │ -└───────────┴──────────────────────────────────────────┴──────────────────────────┘ - -CLONOTYPE = 4 CELLS -┌───────────┬───────────────────────────────────────────┬──────────────────────────┐ -│ │ CHAIN 1 │ CHAIN 2 │ -│ │ 67.1.1|IGHV1-2 ◆ 20|IGHD3-22 ◆ 53|IGHJ3 │ 219|IGKV1-12 ◆ 216|IGKJ4│ -│ ├───────────────────────────────────────────┼──────────────────────────┤ -│ │ 1111111111111111111111 │ 1111111 │ -│ │ 8 1111112222222222333333 │ 0111111 │ -│ │ 5 4567890123456789012345 │ 9012345 │ -│ │ ═════════CDR3═════════ │ ══CDR3═ │ -│reference │ W ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQQ◦◦◦◦ │ -│donor ref │ R ◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦◦W │ CQQ◦◦◦◦ │ -├───────────┼───────────────────────────────────────────┼──────────────────────────┤ -│# n │ . ...................... u const │ ....... u const │ -│1 4 │ R CAREMPDYYDSSGYSRDAFDIW 3252 IGHG1 │ CQQGVTF 12045 IGKC │ -└───────────┴───────────────────────────────────────────┴──────────────────────────┘ diff --git a/test b/test index 9aa996e4ce..c0bb419e25 100755 --- a/test +++ b/test @@ -51,7 +51,7 @@ if ( $status != 0 ) then exit 1 endif cargo test --bin traceback1 --test enclone_test1 --test enclone_test2 --test enclone_test3 \ - --test enclone_test4 --test enclone_test_peak_mem --no-run >& /dev/null + --test enclone_test4 --no-run >& /dev/null if ( $status != 0 ) then echo "compilation failed 2" exit 1 @@ -93,7 +93,7 @@ if ( $arg1 != linkless ) then endif else cargo test --bin traceback1 --test enclone_test1 --test enclone_test2 --test enclone_test3 \ - --test enclone_test4 --test enclone_test_peak_mem --features linkless \ + --test enclone_test4 --features linkless \ -- --nocapture |& post_process_test if ( $status != 0 ) then echo "FAILED!"