diff --git a/Cargo.lock b/Cargo.lock index 8d7757f..32dfb12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,15 +4,15 @@ version = 4 [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -25,44 +25,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "once_cell", - "windows-sys", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "arc-swap" @@ -84,9 +84,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base64" @@ -111,9 +111,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" [[package]] name = "bitvec" @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.23.0" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" [[package]] name = "byteorder-lite" @@ -141,15 +141,15 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "clap" -version = "4.5.37" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" dependencies = [ "clap_builder", "clap_derive", @@ -157,9 +157,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" dependencies = [ "anstream", "anstyle", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" dependencies = [ "heck", "proc-macro2", @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "color_quant" @@ -193,9 +193,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "compact-genome" @@ -230,24 +230,24 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "data-url" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", ] @@ -275,18 +275,18 @@ dependencies = [ [[package]] name = "enum-iterator" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635" +checksum = "a4549325971814bda7a44061bf3fe7e487d447cba01e4220a4b454d630d7a016" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" +checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842" dependencies = [ "proc-macro2", "quote", @@ -299,6 +299,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "euclid" +version = "0.22.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +dependencies = [ + "num-traits", +] + [[package]] name = "extend_map" version = "0.14.4" @@ -316,9 +325,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -332,9 +341,9 @@ checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" [[package]] name = "fontconfig-parser" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" +checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" dependencies = [ "roxmltree", ] @@ -373,9 +382,9 @@ dependencies = [ [[package]] name = "gif" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" dependencies = [ "color_quant", "weezl", @@ -383,9 +392,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" [[package]] name = "heck" @@ -395,9 +404,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "image-webp" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" dependencies = [ "byteorder-lite", "quick-error", @@ -411,9 +420,9 @@ checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" [[package]] name = "indexmap" -version = "2.9.0" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "92119844f513ffa41556430369ab02c295a3578af21cf945caa3e9e0c2481ac3" dependencies = [ "equivalent", "hashbrown", @@ -440,19 +449,14 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - [[package]] name = "kurbo" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1077d333efea6170d9ccb96d3c3026f300ca0773da4938cc4c811daa6df68b0c" +checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" dependencies = [ "arrayvec", + "euclid", "smallvec", ] @@ -499,9 +503,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libm" @@ -511,15 +515,15 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -527,15 +531,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" dependencies = [ "libc", ] @@ -551,9 +555,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", @@ -642,6 +646,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "pico-args" version = "0.5.0" @@ -663,9 +673,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -684,9 +694,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -695,6 +705,7 @@ dependencies = [ name = "py_lib_tsalign" version = "0.3.1" dependencies = [ + "compact-genome", "lib_tsalign", "lib_tsshow", "pyo3", @@ -851,9 +862,9 @@ dependencies = [ [[package]] name = "rgb" -version = "0.8.50" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" dependencies = [ "bytemuck", ] @@ -870,7 +881,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.4", "bytemuck", "core_maths", "log", @@ -894,18 +905,28 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.225" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" dependencies = [ "proc-macro2", "quote", @@ -914,9 +935,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -964,9 +985,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "strict-num" @@ -1021,9 +1042,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.101" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -1044,9 +1065,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" +checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" [[package]] name = "termcolor" @@ -1059,18 +1080,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", @@ -1079,12 +1100,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" dependencies = [ "deranged", - "itoa", "libc", "num-conv", "num_threads", @@ -1096,15 +1116,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -1138,9 +1158,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -1153,9 +1173,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -1165,18 +1185,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.26" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "serde", @@ -1188,9 +1208,9 @@ dependencies = [ [[package]] name = "toml_write" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "traitsequence" @@ -1252,9 +1272,9 @@ checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" [[package]] name = "unicode-properties" @@ -1321,34 +1341,56 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "weezl" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.61.0", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + [[package]] name = "windows-sys" -version = "0.59.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link 0.1.3", "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", @@ -1361,57 +1403,57 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" [[package]] name = "windows_i686_gnullvm" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.10" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ "memchr", ] @@ -1439,9 +1481,9 @@ checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" [[package]] name = "zune-jpeg" -version = "0.4.14" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" dependencies = [ "zune-core", ] diff --git a/lib_tsalign/src/a_star_aligner.rs b/lib_tsalign/src/a_star_aligner.rs index 97a841f..9116076 100644 --- a/lib_tsalign/src/a_star_aligner.rs +++ b/lib_tsalign/src/a_star_aligner.rs @@ -154,7 +154,7 @@ pub fn template_switch_distance_a_star_align< reference_name: &str, query_name: &str, range: Option, - config: config::TemplateSwitchConfig< + config: &config::TemplateSwitchConfig< Strategies::Alphabet, ::Cost, >, @@ -170,7 +170,7 @@ where template_switch_min_length: Default::default(), chaining: <::Chaining as ChainingStrategy< ::Cost, - >>::initialise_memory(reference, query, &config, 20), + >>::initialise_memory(reference, query, config, 20), template_switch_count: template_switch_count_memory, shortcut: (), primary_match: (), @@ -195,9 +195,9 @@ where info!("Extending template switches"); let mut range = range; - result.extend_beyond_range_with_equal_cost(reference, query, &mut range, &config); + result.extend_beyond_range_with_equal_cost(reference, query, &mut range, config); let range = range; - result.compute_ts_equal_cost_ranges(reference, query, &range, &config); + result.compute_ts_equal_cost_ranges(reference, query, &range, config); result } diff --git a/lib_tsalign/src/a_star_aligner/configurable_a_star_align.rs b/lib_tsalign/src/a_star_aligner/configurable_a_star_align.rs index 6053545..02832c0 100644 --- a/lib_tsalign/src/a_star_aligner/configurable_a_star_align.rs +++ b/lib_tsalign/src/a_star_aligner/configurable_a_star_align.rs @@ -1,19 +1,8 @@ -use std::fmt::Debug; +use std::{fmt::Debug, str::FromStr}; use compact_genome::{ - implementation::{ - alphabets::{ - dna_alphabet::DnaAlphabet, dna_alphabet_or_n::DnaAlphabetOrN, - dna_iupac_nucleic_acid_alphabet::DnaIupacNucleicAcidAlphabet, - rna_alphabet::RnaAlphabet, rna_alphabet_or_n::RnaAlphabetOrN, - rna_iupac_nucleic_acid_alphabet::RnaIupacNucleicAcidAlphabet, - }, - vec_sequence::VectorGenome, - }, - interface::{ - alphabet::Alphabet, - sequence::{GenomeSequence, OwnedGenomeSequence}, - }, + implementation::{alphabets::dna_alphabet_or_n::DnaAlphabetOrN, vec_sequence::VectorGenome}, + interface::sequence::{GenomeSequence, OwnedGenomeSequence}, }; use generic_a_star::cost::U64Cost; @@ -35,7 +24,7 @@ use super::{ AlignmentType, strategies::{ chaining::{ChainingStrategy, LowerBoundChainingStrategy, NoChainingStrategy}, - node_ord::{AntiDiagonalNodeOrdStrategy, NodeOrdStrategy}, + node_ord::AntiDiagonalNodeOrdStrategy, primary_match::AllowPrimaryMatchStrategy, template_switch_count::{ MaxTemplateSwitchCountStrategy, NoTemplateSwitchCountStrategy, @@ -53,344 +42,251 @@ use super::{ }, }; -#[derive(Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] -pub struct Config { - pub alphabet: InputAlphabet, - pub reference_name: String, - pub query_name: String, - /// Costs specification in plain text format. - /// - /// This is the same format that the `.tsa` config files use. - pub costs: String, - - pub node_ord_strategy: NodeOrdStrategySelector, - pub min_length_strategy: MinLengthStrategySelector, - pub chaining_strategy: ChainingStrategySelector, - pub total_length_strategy: TotalLengthStrategySelector, - pub no_ts: bool, - - pub cost_limit: Option, - /// Approximate memory limit in bytes. - pub memory_limit: Option, - pub range: Option, -} - -impl Default for Config { - fn default() -> Self { - Self { - alphabet: InputAlphabet::DnaN, - reference_name: "reference".to_owned(), - query_name: "query".to_owned(), - costs: TemplateSwitchConfig::::default().to_string(), - node_ord_strategy: NodeOrdStrategySelector::AntiDiagonal, - min_length_strategy: MinLengthStrategySelector::Lookahead, - chaining_strategy: ChainingStrategySelector::None, - total_length_strategy: TotalLengthStrategySelector::Maximise, - no_ts: false, - cost_limit: None, - memory_limit: None, - range: None, - } - } -} - -#[derive(Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] -pub enum InputAlphabet { - Dna, - DnaN, - Rna, - RnaN, - DnaIupac, - RnaIupac, -} - -#[derive(Debug)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] -pub enum NodeOrdStrategySelector { - // CostOnly, - AntiDiagonal, -} +pub use compact_genome::implementation::alphabets; +pub use compact_genome::interface::alphabet::Alphabet; -#[derive(Debug)] +#[derive(Debug, Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] pub enum MinLengthStrategySelector { None, + #[default] Lookahead, } -#[derive(Debug)] +#[derive(Debug, Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] pub enum ChainingStrategySelector { + #[default] None, // PrecomputeOnly, LowerBound, } -#[derive(Debug)] +#[derive(Debug, Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] pub enum TotalLengthStrategySelector { None, + #[default] Maximise, } -/// Align `query` to `reference` with the given `config`. -/// -/// `query` and `reference` must be ASCII strings restricted to the characters specified by `config.alphabet`. -pub fn a_star_align( - reference: &[u8], - query: &[u8], - config: &Config, -) -> AlignmentResult { - match config.alphabet { - InputAlphabet::Dna => { - a_star_align_select_node_ord_strategy::(reference, query, config) - } - InputAlphabet::DnaN => { - a_star_align_select_node_ord_strategy::(reference, query, config) - } - InputAlphabet::Rna => { - a_star_align_select_node_ord_strategy::(reference, query, config) - } - InputAlphabet::RnaN => { - a_star_align_select_node_ord_strategy::(reference, query, config) - } - InputAlphabet::DnaIupac => a_star_align_select_node_ord_strategy::< - DnaIupacNucleicAcidAlphabet, - >(reference, query, config), - InputAlphabet::RnaIupac => a_star_align_select_node_ord_strategy::< - RnaIupacNucleicAcidAlphabet, - >(reference, query, config), - } +/// Just used in this file to bundle the query parameters to make the code more readable +struct QueryData<'a> { + reference_name: &'a str, + reference: &'a [u8], + query_name: &'a str, + query: &'a [u8], + ranges: Option, + cost_limit: Option, + memory_limit: Option, } -fn a_star_align_select_node_ord_strategy( - reference: &[u8], - query: &[u8], - config: &Config, -) -> AlignmentResult { - let reference = VectorGenome::::from_slice_u8(reference).unwrap(); - let query = VectorGenome::from_slice_u8(query).unwrap(); - let costs = TemplateSwitchConfig::read_plain(config.costs.as_bytes()).unwrap(); +#[cfg_attr(feature = "serde", derive(serde::Deserialize))] // Mostly used for kwargs in python bindings +#[cfg_attr(feature = "serde", serde(default))] +pub struct Aligner { + #[cfg_attr(feature = "serde", serde(skip))] // Not deserializable + costs: TemplateSwitchConfig, - match config.node_ord_strategy { - /*NodeOrdStrategySelector::CostOnly => { - a_star_align_select_template_switch_min_length_strategy::<_, _, CostOnlyNodeOrdStrategy>( - reference.as_genome_subsequence(), - query.as_genome_subsequence(), - config, - costs, - ) - unimplemented!("The other option appears to always be better."); - }*/ - NodeOrdStrategySelector::AntiDiagonal => { - a_star_align_select_template_switch_min_length_strategy::< - _, - _, - AntiDiagonalNodeOrdStrategy, - >( - reference.as_genome_subsequence(), - query.as_genome_subsequence(), - config, - costs, - ) - } - } + // ↓ Settings for how the alignment (definition) + min_length_strategy: MinLengthStrategySelector, + chaining_strategy: ChainingStrategySelector, + total_length_strategy: TotalLengthStrategySelector, + no_ts: bool, } -fn a_star_align_select_template_switch_min_length_strategy< - AlphabetType: Alphabet + Debug + Clone + Eq, - SubsequenceType: GenomeSequence + ?Sized, - NodeOrd: NodeOrdStrategy, ->( - reference: &SubsequenceType, - query: &SubsequenceType, - config: &Config, - costs: TemplateSwitchConfig, -) -> AlignmentResult { - match config.min_length_strategy { - MinLengthStrategySelector::None => a_star_align_select_chaining_strategy::< - _, - _, - NodeOrd, - NoTemplateSwitchMinLengthStrategy, - >(reference, query, config, costs), - MinLengthStrategySelector::Lookahead => a_star_align_select_chaining_strategy::< - _, - _, - NodeOrd, - LookaheadTemplateSwitchMinLengthStrategy, - >(reference, query, config, costs), +impl Aligner { + #[must_use] + pub fn new() -> Self { + Self::default() } } -fn a_star_align_select_chaining_strategy< - AlphabetType: Alphabet + Debug + Clone + Eq, - SubsequenceType: GenomeSequence + ?Sized, - NodeOrd: NodeOrdStrategy, - TemplateSwitchMinLength: TemplateSwitchMinLengthStrategy, ->( - reference: &SubsequenceType, - query: &SubsequenceType, - config: &Config, - costs: TemplateSwitchConfig, -) -> AlignmentResult { - match config.chaining_strategy { - ChainingStrategySelector::None => a_star_align_select_no_ts_strategy::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - NoChainingStrategy, - >(reference, query, config, costs), - /*ChainingStrategySelector::PrecomputeOnly => { - a_star_align_select_no_ts_strategy::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - PrecomputeOnlyChainingStrategy, - >(reference, query, config, costs) - unimplemented!("No reason to precompute without using the information."); - }*/ - ChainingStrategySelector::LowerBound => a_star_align_select_no_ts_strategy::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - LowerBoundChainingStrategy, - >(reference, query, config, costs), +/// We implement this ourselves to avoid the overly restrictive trait bound +/// `AlphabetType: Default` that would be generated with the derive macro +impl Default for Aligner { + fn default() -> Self { + Self { + costs: TemplateSwitchConfig::::default(), + min_length_strategy: MinLengthStrategySelector::default(), + chaining_strategy: ChainingStrategySelector::default(), + total_length_strategy: TotalLengthStrategySelector::default(), + no_ts: false, + } } } -fn a_star_align_select_no_ts_strategy< - AlphabetType: Alphabet + Debug + Clone + Eq, - SubsequenceType: GenomeSequence + ?Sized, - NodeOrd: NodeOrdStrategy, - TemplateSwitchMinLength: TemplateSwitchMinLengthStrategy, - Chaining: ChainingStrategy, ->( - reference: &SubsequenceType, - query: &SubsequenceType, - config: &Config, - costs: TemplateSwitchConfig, -) -> AlignmentResult { - if config.no_ts { - a_star_align_select_total_length_strategy::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - Chaining, - MaxTemplateSwitchCountStrategy, - >(reference, query, config, costs, 0) - } else { - a_star_align_select_total_length_strategy::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - Chaining, - NoTemplateSwitchCountStrategy, - >(reference, query, config, costs, ()) +impl Aligner { + /// Parse a cost string and update the aligner cost + /// + /// # Errors + /// Returns an error if the string cannot be parsed as `TemplateSwitchConfig` + pub fn set_costs_parse(&mut self, costs: &str) -> Result<&mut Self, crate::error::Error> { + self.costs = TemplateSwitchConfig::from_str(costs)?; + Ok(self) } -} -fn a_star_align_select_total_length_strategy< - AlphabetType: Alphabet + Debug + Clone + Eq, - SubsequenceType: GenomeSequence + ?Sized, - NodeOrd: NodeOrdStrategy, - TemplateSwitchMinLength: TemplateSwitchMinLengthStrategy, - Chaining: ChainingStrategy, - TemplateSwitchCount: TemplateSwitchCountStrategy, ->( - reference: &SubsequenceType, - query: &SubsequenceType, - config: &Config, - costs: TemplateSwitchConfig, - template_switch_count_memory: ::Memory, -) -> AlignmentResult { - match config.total_length_strategy { - TotalLengthStrategySelector::None => a_star_align_call::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - Chaining, - TemplateSwitchCount, - NoTemplateSwitchTotalLengthStrategy, - >( - reference, - query, - config, - costs, - template_switch_count_memory, - ), - TotalLengthStrategySelector::Maximise => a_star_align_call::< - _, - _, - NodeOrd, - TemplateSwitchMinLength, - Chaining, - TemplateSwitchCount, - MaxTemplateSwitchTotalLengthStrategy, - >( + pub fn set_costs(&mut self, costs: TemplateSwitchConfig) -> &mut Self { + self.costs = costs; + self + } + + pub fn set_min_length_strategy( + &mut self, + min_length_strategy: MinLengthStrategySelector, + ) -> &mut Self { + self.min_length_strategy = min_length_strategy; + self + } + + pub fn set_chaining_strategy( + &mut self, + chaining_strategy: ChainingStrategySelector, + ) -> &mut Self { + self.chaining_strategy = chaining_strategy; + self + } + + pub fn set_total_length_strategy( + &mut self, + total_length_strategy: TotalLengthStrategySelector, + ) -> &mut Self { + self.total_length_strategy = total_length_strategy; + self + } + + pub fn set_no_ts(&mut self, no_ts: bool) -> &mut Self { + self.no_ts = no_ts; + self + } + + /// This performs the actual alignment and is, depending on the inputs, potentially taking quite long. + /// Consider spawning tasks to not block the user application. + #[allow( + clippy::too_many_arguments, + reason = "For now, this is the intended API" + )] + #[must_use] + pub fn align( + &self, + reference_name: &str, + reference: &[u8], + query_name: &str, + query: &[u8], + ranges: Option, + cost_limit: Option, + memory_limit: Option, + ) -> AlignmentResult { + let data = QueryData { + reference_name, reference, + query_name, query, - config, - costs, - template_switch_count_memory, - ), + ranges, + cost_limit, + memory_limit, + }; + self.align_select_min_length_strategy(data) } -} -fn a_star_align_call< - AlphabetType: Alphabet + Debug + Clone + Eq, - SubsequenceType: GenomeSequence + ?Sized, - NodeOrd: NodeOrdStrategy, - TemplateSwitchMinLength: TemplateSwitchMinLengthStrategy, - Chaining: ChainingStrategy, - TemplateSwitchCount: TemplateSwitchCountStrategy, - TemplateSwitchTotalLength: TemplateSwitchTotalLengthStrategy, ->( - reference: &SubsequenceType, - query: &SubsequenceType, - config: &Config, - costs: TemplateSwitchConfig, - template_switch_count_memory: ::Memory, -) -> AlignmentResult { - template_switch_distance_a_star_align::< - AlignmentStrategySelection< - AlphabetType, - U64Cost, - NodeOrd, - TemplateSwitchMinLength, - Chaining, - TemplateSwitchCount, - AllowSecondaryDeletionStrategy, - NoShortcutStrategy, - AllowPrimaryMatchStrategy, - NoPrunePrimaryRangeStrategy, - TemplateSwitchTotalLength, - >, - _, + fn align_select_min_length_strategy( + &self, + data: QueryData, + ) -> AlignmentResult { + match self.min_length_strategy { + MinLengthStrategySelector::None => self + .align_select_chaining_strategy::>(data), + MinLengthStrategySelector::Lookahead => self.align_select_chaining_strategy::>(data), + } + } + + fn align_select_chaining_strategy>( + &self, + data: QueryData, + ) -> AlignmentResult { + match self.chaining_strategy { + ChainingStrategySelector::None => { + self.align_select_total_length_strategy::>(data) + } + ChainingStrategySelector::LowerBound => self + .align_select_total_length_strategy::>( + data, + ), + } + } + + fn align_select_total_length_strategy< + ML: TemplateSwitchMinLengthStrategy, + CH: ChainingStrategy, >( - reference, - query, - &config.reference_name, - &config.query_name, - config.range.clone(), - costs, - config.cost_limit, - config.memory_limit, - false, - template_switch_count_memory, - ) + &self, + data: QueryData, + ) -> AlignmentResult { + match self.total_length_strategy { + TotalLengthStrategySelector::None => self + .align_select_no_ts_strategy::(data), + TotalLengthStrategySelector::Maximise => self + .align_select_no_ts_strategy::(data), + } + } + + fn align_select_no_ts_strategy< + ML: TemplateSwitchMinLengthStrategy, + CH: ChainingStrategy, + TL: TemplateSwitchTotalLengthStrategy, + >( + &self, + data: QueryData, + ) -> AlignmentResult { + if self.no_ts { + self.align_call::(data, 0) + } else { + self.align_call::(data, ()) + } + } + + fn align_call< + ML: TemplateSwitchMinLengthStrategy, + CH: ChainingStrategy, + TL: TemplateSwitchTotalLengthStrategy, + TC: TemplateSwitchCountStrategy, + >( + &self, + data: QueryData, + count_strategy_memory: TC::Memory, + ) -> AlignmentResult { + // TODO error handling + let reference = VectorGenome::::from_slice_u8(data.reference).unwrap(); + let query = VectorGenome::from_slice_u8(data.query).unwrap(); + let cost_limit = data.cost_limit.map(U64Cost::from); + template_switch_distance_a_star_align::< + AlignmentStrategySelection< + AlphabetType, + U64Cost, + AntiDiagonalNodeOrdStrategy, + ML, + CH, + TC, + AllowSecondaryDeletionStrategy, + NoShortcutStrategy, + AllowPrimaryMatchStrategy, + NoPrunePrimaryRangeStrategy, + TL, + >, + _, + >( + reference.as_genome_subsequence(), + query.as_genome_subsequence(), + data.reference_name, + data.query_name, + data.ranges, + &self.costs, + cost_limit, + data.memory_limit, + false, + count_strategy_memory, + ) + } } diff --git a/lib_tsalign/src/config/io.rs b/lib_tsalign/src/config/io.rs index 9658c3d..f4d062a 100644 --- a/lib_tsalign/src/config/io.rs +++ b/lib_tsalign/src/config/io.rs @@ -258,6 +258,18 @@ impl std::fmt::Display } } +impl FromStr for TemplateSwitchConfig { + type Err = crate::error::Error; + + fn from_str(s: &str) -> Result { + let result = Self::parse_plain(s) + .map(|(_, result)| result) + .map_err(translate_nom_error)?; + result.verify()?; + Ok(result) + } +} + #[cfg(test)] mod tests { use compact_genome::implementation::alphabets::dna_alphabet_or_n::DnaAlphabetOrN; diff --git a/python_bindings/Cargo.toml b/python_bindings/Cargo.toml index 58f4338..86dcbad 100644 --- a/python_bindings/Cargo.toml +++ b/python_bindings/Cargo.toml @@ -17,11 +17,10 @@ doc = false crate-type = ["cdylib"] [dependencies] -pyo3 = "0.26.0" -lib_tsalign = { version = "0.18.1", path = "../lib_tsalign", features = [ - "serde", -] } -lib_tsshow = { version = "0.18.1", path = "../lib_tsshow" } +pyo3 = "0.26" +lib_tsalign = { path = "../lib_tsalign", features = ["serde"] } +lib_tsshow = { path = "../lib_tsshow" } serde.workspace = true -pythonize = "0.26.0" -pyo3-log = "0.13.2" +pythonize = "0.26" +pyo3-log = "0.13" +compact-genome.workspace = true diff --git a/python_bindings/src/lib.rs b/python_bindings/src/lib.rs index fcbfe0b..fbbd85f 100644 --- a/python_bindings/src/lib.rs +++ b/python_bindings/src/lib.rs @@ -1,9 +1,11 @@ use std::io; +use compact_genome::implementation::alphabets::dna_alphabet_or_n::DnaAlphabetOrN; use lib_tsalign::{ a_star_aligner::{ + alignment_geometry::{AlignmentCoordinates, AlignmentRange}, alignment_result::AlignmentResult, - configurable_a_star_align::{Config, a_star_align}, + configurable_a_star_align::Aligner, template_switch_distance::AlignmentType, }, costs::U64Cost, @@ -53,40 +55,89 @@ fn py_to_str(o: Bound<'_, PyAny>) -> PyResult> { Ok(str) } -/// Creates a config object by amending the default by values present in the python dictionary -fn create_config(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult { - let Some(kwargs) = kwargs else { - return Ok(Config::default()); - }; +#[pyclass(name = "Aligner")] +struct TSAligner { + aligner: Aligner, +} + +#[pymethods] +impl TSAligner { + #[new] + #[pyo3(signature = (**kwargs))] + fn new(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult { + let Some(kwargs) = kwargs else { + return Ok(Self { + aligner: Aligner::new(), + }); + }; - let config = depythonize::(kwargs)?; + let costs_str = if let Some(costs) = kwargs.get_item("costs")? { + let py_str: &str = costs.extract()?; + kwargs.del_item("costs")?; + Some(py_str.to_string()) + } else { + None + }; - Ok(config) -} + let mut aligner: Aligner = depythonize(kwargs)?; -/// Align two sequences, accounting for template switches -/// -/// The function takes a reference and a query string, and performs a global alignment on both. The output alignment may contain (short-range) template switches. -/// Optionally, settings can be specified. See the (configuration struct)[lib_tsalign::a_star_aligner::configurable_a_star_align::Config] for the available keys and values. -#[pyfunction] -#[pyo3(signature = (reference, query, **kwargs))] -fn align( - reference: Bound<'_, PyAny>, // Accepting PyAny instead of PyString to allow using e.g. `Bio.Seq` types and alike. String representation will be used. - query: Bound<'_, PyAny>, - kwargs: Option<&Bound<'_, PyDict>>, -) -> PyResult> { - let reference = py_to_str(reference)?; - let query = py_to_str(query)?; - let config = create_config(kwargs)?; - - let r = a_star_align(&reference, &query, &config); - - match r { - result @ AlignmentResult::WithTarget { .. } => { - let ts_alignment = TSPairwiseAlignment { result }; - Ok(Some(ts_alignment)) + if let Some(costs_str) = costs_str { + aligner + .set_costs_parse(&costs_str) + .map_err(|e| PyRuntimeError::new_err(e.to_string()))?; + } + + Ok(Self { aligner }) + } + + /// Align two sequences, accounting for template switches + /// + /// The function takes a reference and a query string, and performs a global alignment on both. The output alignment may contain (short-range) template switches. + /// Optionally, settings can be specified on this aligner. + #[pyo3(signature = (reference, query, reference_name="reference", query_name="query", reference_start=None, reference_limit=None, query_start=None, query_limit=None, cost_limit=None, memory_limit=None))] + #[allow(clippy::too_many_arguments)] + fn align( + &self, + reference: Bound<'_, PyAny>, // Accepting PyAny instead of PyString to allow using e.g. `Bio.Seq` types and alike. String representation will be used. + query: Bound<'_, PyAny>, + reference_name: &str, + query_name: &str, + reference_start: Option, + reference_limit: Option, + query_start: Option, + query_limit: Option, + cost_limit: Option, + memory_limit: Option, + ) -> PyResult> { + let reference = py_to_str(reference)?; + let query = py_to_str(query)?; + + let reference_start = reference_start.unwrap_or(0); + let reference_limit = reference_limit.unwrap_or(reference.len()); + let query_start = query_start.unwrap_or(0); + let query_limit = query_limit.unwrap_or(query.len()); + let ranges = AlignmentRange::new_offset_limit( + AlignmentCoordinates::new(reference_start, query_start), + AlignmentCoordinates::new(reference_limit, query_limit), + ); + + let result = self.aligner.align( + reference_name, + &reference, + query_name, + &query, + Some(ranges), + cost_limit, + memory_limit, + ); + + match result { + result @ AlignmentResult::WithTarget { .. } => { + let ts_alignment = TSPairwiseAlignment { result }; + Ok(Some(ts_alignment)) + } + AlignmentResult::WithoutTarget { .. } => Ok(None), } - AlignmentResult::WithoutTarget { .. } => Ok(None), } } @@ -95,6 +146,6 @@ fn align( fn tsalign(m: &Bound<'_, PyModule>) -> PyResult<()> { pyo3_log::init(); m.add_class::()?; - m.add_function(wrap_pyfunction!(align, m)?)?; + m.add_class::()?; Ok(()) } diff --git a/tsalign/src/align/template_switch_distance_type_selectors.rs b/tsalign/src/align/template_switch_distance_type_selectors.rs index e10d23c..08ab39b 100644 --- a/tsalign/src/align/template_switch_distance_type_selectors.rs +++ b/tsalign/src/align/template_switch_distance_type_selectors.rs @@ -323,7 +323,7 @@ fn align_a_star_template_switch_distance_call< reference_name, query_name, range, - costs, + &costs, cli.cost_limit, cli.memory_limit, cli.force_label_correcting,