Copy disabled (too large)
Download .txt
Showing preview only (11,503K chars total). Download the full file to get everything.
Repository: dib-lab/sourmash
Branch: latest
Commit: a376482d9945
Files: 707
Total size: 10.9 MB
Directory structure:
gitextract_wdvkn2_7/
├── .cargo/
│ └── config.toml
├── .envrc
├── .git-blame-ignore-revs
├── .git_archival.txt
├── .gitattributes
├── .github/
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── asv.yml
│ ├── build_wheel.yml
│ ├── build_wheel_all_archs.yml
│ ├── codspeed.yml
│ ├── dev_envs.yml
│ ├── draft-pdf.yml
│ ├── hypothesis.yml
│ ├── metadata.yml
│ ├── python.yml
│ └── rust.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yml
├── .sonarcloud.properties
├── .zenodo.json
├── CITATION.cff
├── CODE_OF_CONDUCT.rst
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── asv.conf.json
├── benchmarks/
│ ├── README.md
│ ├── __init__.py
│ └── benchmarks.py
├── binder/
│ ├── README.md
│ └── environment.yml
├── codecov.yml
├── codemeta.json
├── data/
│ └── README.md
├── default.nix
├── deny.toml
├── dev.yml
├── doc/
│ ├── Makefile
│ ├── README.md
│ ├── _static/
│ │ ├── custom.css
│ │ ├── ecoli-cmp.Rmd
│ │ ├── ecoli-cmp.html
│ │ └── ecoli.cmp.csv
│ ├── _templates/
│ │ └── .empty
│ ├── api-example.md
│ ├── api.md
│ ├── cite.md
│ ├── classifying-signatures.md
│ ├── command-line.md
│ ├── conf.py
│ ├── databases-advanced.md
│ ├── databases-md/
│ │ ├── gtdb220.md
│ │ ├── gtdb226.md
│ │ ├── ncbi_euks_2025_01.md
│ │ └── ncbi_viruses_2025_01.md
│ ├── databases.md
│ ├── dev_plugins.md
│ ├── developer.md
│ ├── faq.md
│ ├── funding.md
│ ├── howto-rocksdb.md
│ ├── index.md
│ ├── kmers-and-minhash.ipynb
│ ├── legacy-databases.md
│ ├── more-info.md
│ ├── other-languages.md
│ ├── plotting-compare.ipynb
│ ├── podar-lineage.csv
│ ├── publications.md
│ ├── release-notes/
│ │ ├── releases.md
│ │ ├── sourmash-2.0.md
│ │ ├── sourmash-3.0.md
│ │ ├── sourmash-4.0.md
│ │ └── sourmash-5.0.md
│ ├── release.md
│ ├── requirements.md
│ ├── runtime.txt
│ ├── sidebar.md
│ ├── sourmash-collections.ipynb
│ ├── sourmash-examples.ipynb
│ ├── sourmash-internals.md
│ ├── sourmash-sketch.md
│ ├── storage.md
│ ├── support.md
│ ├── toc.md
│ ├── tutorial-basic.md
│ ├── tutorial-install.md
│ ├── tutorial-lemonade.md
│ ├── tutorial-lin-taxonomy.md
│ ├── tutorial-long.md
│ ├── tutorials-lca.md
│ ├── tutorials.md
│ ├── using-LCA-database-API.ipynb
│ └── using-sourmash-a-guide.md
├── flake.nix
├── include/
│ └── sourmash.h
├── matplotlibrc
├── paper.bib
├── paper.md
├── pyproject.toml
├── requirements.txt
├── shell.nix
├── src/
│ ├── core/
│ │ ├── CHANGELOG.md
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── benches/
│ │ │ ├── compute.rs
│ │ │ ├── gather.rs
│ │ │ ├── minhash.rs
│ │ │ └── nodegraph.rs
│ │ ├── build.rs
│ │ ├── cbindgen.toml
│ │ ├── examples/
│ │ │ └── generate_mqfs.rs
│ │ ├── src/
│ │ │ ├── ani_utils.rs
│ │ │ ├── cmd.rs
│ │ │ ├── collection.rs
│ │ │ ├── encodings.rs
│ │ │ ├── errors.rs
│ │ │ ├── ffi/
│ │ │ │ ├── cmd/
│ │ │ │ │ ├── compute.rs
│ │ │ │ │ └── mod.rs
│ │ │ │ ├── hyperloglog.rs
│ │ │ │ ├── index/
│ │ │ │ │ ├── mod.rs
│ │ │ │ │ └── revindex.rs
│ │ │ │ ├── manifest.rs
│ │ │ │ ├── minhash.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── nodegraph.rs
│ │ │ │ ├── signature.rs
│ │ │ │ ├── storage.rs
│ │ │ │ └── utils.rs
│ │ │ ├── index/
│ │ │ │ ├── linear.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── revindex/
│ │ │ │ │ ├── disk_revindex.rs
│ │ │ │ │ ├── mem_revindex.rs
│ │ │ │ │ └── mod.rs
│ │ │ │ └── search.rs
│ │ │ ├── lib.rs
│ │ │ ├── manifest.rs
│ │ │ ├── prelude.rs
│ │ │ ├── selection.rs
│ │ │ ├── signature.rs
│ │ │ ├── sketch/
│ │ │ │ ├── hyperloglog/
│ │ │ │ │ ├── estimators.rs
│ │ │ │ │ └── mod.rs
│ │ │ │ ├── minhash.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── nodegraph.rs
│ │ │ ├── storage/
│ │ │ │ ├── mod.rs
│ │ │ │ └── rocksdb.rs
│ │ │ └── wasm.rs
│ │ └── tests/
│ │ ├── dedicated_worker.rs
│ │ ├── finch.rs
│ │ ├── minhash.rs
│ │ ├── node.rs
│ │ ├── service_worker.rs
│ │ ├── shared_worker.rs
│ │ ├── storage.rs
│ │ ├── test.rs
│ │ └── web.rs
│ └── sourmash/
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── categorize.py
│ │ ├── compare.py
│ │ ├── compute.py
│ │ ├── gather.py
│ │ ├── import_csv.py
│ │ ├── index.py
│ │ ├── info.py
│ │ ├── lca/
│ │ │ ├── __init__.py
│ │ │ ├── classify.py
│ │ │ ├── compare_csv.py
│ │ │ ├── index.py
│ │ │ ├── rankinfo.py
│ │ │ └── summarize.py
│ │ ├── migrate.py
│ │ ├── multigather.py
│ │ ├── plot.py
│ │ ├── prefetch.py
│ │ ├── sbt_combine.py
│ │ ├── scripts/
│ │ │ └── __init__.py
│ │ ├── search.py
│ │ ├── sig/
│ │ │ ├── __init__.py
│ │ │ ├── cat.py
│ │ │ ├── check.py
│ │ │ ├── collect.py
│ │ │ ├── describe.py
│ │ │ ├── downsample.py
│ │ │ ├── export.py
│ │ │ ├── extract.py
│ │ │ ├── fileinfo.py
│ │ │ ├── filter.py
│ │ │ ├── flatten.py
│ │ │ ├── grep.py
│ │ │ ├── inflate.py
│ │ │ ├── ingest.py
│ │ │ ├── intersect.py
│ │ │ ├── kmers.py
│ │ │ ├── manifest.py
│ │ │ ├── merge.py
│ │ │ ├── overlap.py
│ │ │ ├── rename.py
│ │ │ ├── split.py
│ │ │ └── subtract.py
│ │ ├── sketch/
│ │ │ ├── __init__.py
│ │ │ ├── dna.py
│ │ │ ├── fromfile.py
│ │ │ ├── protein.py
│ │ │ └── translate.py
│ │ ├── storage/
│ │ │ ├── __init__.py
│ │ │ └── convert.py
│ │ ├── tax/
│ │ │ ├── __init__.py
│ │ │ ├── annotate.py
│ │ │ ├── genome.py
│ │ │ ├── grep.py
│ │ │ ├── metagenome.py
│ │ │ ├── prepare.py
│ │ │ └── summarize.py
│ │ ├── utils.py
│ │ └── watch.py
│ ├── command_compute.py
│ ├── command_sketch.py
│ ├── commands.py
│ ├── compare.py
│ ├── distance_utils.py
│ ├── exceptions.py
│ ├── fig.py
│ ├── hll.py
│ ├── index/
│ │ ├── __init__.py
│ │ ├── revindex.py
│ │ └── sqlite_index.py
│ ├── lca/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── command_classify.py
│ │ ├── command_compare_csv.py
│ │ ├── command_index.py
│ │ ├── command_rankinfo.py
│ │ ├── command_summarize.py
│ │ ├── lca_db.py
│ │ └── lca_utils.py
│ ├── logging.py
│ ├── manifest.py
│ ├── minhash.py
│ ├── nodegraph.py
│ ├── np_utils.py
│ ├── picklist.py
│ ├── plugins.py
│ ├── save_load.py
│ ├── sbt.py
│ ├── sbt_storage.py
│ ├── sbtmh.py
│ ├── search.py
│ ├── sig/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ └── grep.py
│ ├── signature.py
│ ├── sketchcomparison.py
│ ├── sourmash_args.py
│ ├── sqlite_utils.py
│ ├── tax/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ └── tax_utils.py
│ └── utils.py
├── tests/
│ ├── conftest.py
│ ├── sourmash_tst_utils.py
│ ├── test-data/
│ │ ├── .sbt.leaves/
│ │ │ ├── 0107d767a345eff67ecdaed2ee5cd7ba
│ │ │ ├── 4e94e60265e04f0763142e20b52c0da1
│ │ │ ├── 60f7e23c24a8d94791cc7a8680c493f9
│ │ │ ├── 6d6e87e1154e95b279e5e7db414bc37b
│ │ │ ├── b59473c94ff2889eca5d7165936e64b3
│ │ │ ├── f0c834bc306651d2b9321fb21d3e8d8f
│ │ │ └── f71e78178af9e45e6f1d87a0c53c465c
│ │ ├── .sbt.subset/
│ │ │ ├── 004459575e3657bca8a3d0424545f082
│ │ │ ├── 01bb2bac3849b82dee57a6ecf8725432
│ │ │ ├── 0382590e3740e4c94455b4d52fff9143
│ │ │ ├── 0418b8351b86bb41c8224d9d15474614
│ │ │ ├── 09cc8e435e5570a5ba3b086bed8c831f
│ │ │ ├── 0d5e85e6ec8d82f2ae38ecb7f1394a04
│ │ │ ├── 0f6508728e178731f3884f59dc7ff3c3
│ │ │ ├── 1131a68ec746703c8c4a2bd13557bf6a
│ │ │ ├── 133743f147335b4d31b0e91480606339
│ │ │ ├── 175e67b69e1833bdee0859a3a99495b1
│ │ │ ├── 1bc3dc1d05e30383d4d098b7de944951
│ │ │ ├── 1f86e7c6c52baed6ce168b05f23013fc
│ │ │ ├── 1fb580f790c207278b55c408a68ff391
│ │ │ ├── 205c4b9623e7331a907f293865925dfa
│ │ │ ├── 20c1ca3c7ff0bb437afd69042bb5f852
│ │ │ ├── 2ac8b6220c4d44ae3dbbbfc7e939df61
│ │ │ ├── 2b28f083395d8f5e7b88c1899ff4a212
│ │ │ ├── 2d8b4d96cf9d790c1b225e681f8d57dd
│ │ │ ├── 3685ee5f820ab6e840ec6b0fe090e754
│ │ │ ├── 38cf0b7d644963ee846734251e9c0175
│ │ │ ├── 3988811e454e96213af488031d84eed9
│ │ │ ├── 3e18cd65bcc35fa150185fea0f162549
│ │ │ ├── 43637330e78d1518b4d8f7603fdb6899
│ │ │ ├── 43fcce1eeeebc8d40162d5247202aef8
│ │ │ ├── 46656e34e01f58e22f22a622f44fa658
│ │ │ ├── 4b57274be5a768732716b9dc600a1f14
│ │ │ ├── 4f1bf83d739fa4d420ceb0aae9403400
│ │ │ ├── 56b9e7bddb830ebe3faaf9923322b51e
│ │ │ ├── 57256c01ec9b9980ecda5b97acb236c3
│ │ │ ├── 57c3b9f54148e7ea9ebfdabbe530f131
│ │ │ ├── 58459874f43a5d202d46018eb8f06e4c
│ │ │ ├── 589cddfc349d8950af5bbd90f5db7060
│ │ │ ├── 5c07a864e3f86a705a73b89bd517979f
│ │ │ ├── 5d19af7826508594c035efe76443138c
│ │ │ ├── 5d813a4d317f9ad17154a99d296d081b
│ │ │ ├── 633f4c15ae21310dac488c09d66c2d38
│ │ │ ├── 6381609c5cdcd210887f5add4bab44d9
│ │ │ ├── 66d40738bd608b83ef35b205a561eaa5
│ │ │ ├── 736138545b801b99385439231a69ab77
│ │ │ ├── 7574dd67e829221b9ae553692c2d5258
│ │ │ ├── 7d859a1c0be4c97c9e1c6c8272950772
│ │ │ ├── 7ddb71d74edc6d1e0c724a8f1bd3c8cc
│ │ │ ├── 7e22d796abc7a6c49dadb94c4dae16b3
│ │ │ ├── 802dc6bf5787992180db6ca259313edf
│ │ │ ├── 81d3020367359d305b0e21933faece1b
│ │ │ ├── 826776746a37223786ffec552e769c88
│ │ │ ├── 8276440e3138e74a1c91b4d91f21072b
│ │ │ ├── 82e0290a438650db9a93ce29276f931b
│ │ │ ├── 849cf867719c1edecd4ec5cf2fb01a32
│ │ │ ├── 857129e817ea9f95c22893d652c98a23
│ │ │ ├── 85ac23fb1585cbe148318b4947a702b7
│ │ │ ├── 8963a3ad29f88d2b9869c51ac102ddf6
│ │ │ ├── 896f1c578904fad60f17061146946732
│ │ │ ├── 8b5bef6feeb06603e70fde66df521edf
│ │ │ ├── 8bdbd61dd2e99b7716968338bcfe9660
│ │ │ ├── 8f9573dec32c97fe824c06edaa16c979
│ │ │ ├── 91fea76b0361f4f812c07e7d43f434f3
│ │ │ ├── 95fd78a08b85bfc006555fe7cbd7e3de
│ │ │ ├── 972d83aa010954aaf5ad0a56f30f43b6
│ │ │ ├── 978c4674f45437d4e84d0a0fc11c424b
│ │ │ ├── 97c19c413385bc830c6b2ddc855ac23a
│ │ │ ├── 9893ff8c4def73d5566baa3541b0a806
│ │ │ ├── 9d3cbd4300d2ca17479b351d152ea677
│ │ │ ├── 9f1f319740e92e9632ce9255f0c57114
│ │ │ ├── a04ede5f60924719bfaabef59c1de821
│ │ │ ├── a20adff6c30627dc22e74d57d7f9b7db
│ │ │ ├── a448b639491a6f75649c2b1c960780d9
│ │ │ ├── a532ca6bf98299efeb2915715b9a21c3
│ │ │ ├── a573351886e921b7204064508010fde0
│ │ │ ├── a893a18ca62dd4e2bcb3c9aaf9c1957b
│ │ │ ├── a897a797fc00c21ec3ef5062b38cfb90
│ │ │ ├── b1ffa01e0fa86ef9025003261eb181e3
│ │ │ ├── b23715f6943b9a84bd64315d27cc8bd5
│ │ │ ├── b3068619013f7ce1bddaa4a67305a571
│ │ │ ├── b476935e55355147395b4d4ac5c7fc8d
│ │ │ ├── bd0ce2248788b643ddfb8276aea4b659
│ │ │ ├── bf69634e838466bf0b83aa42a5fd1cd1
│ │ │ ├── c0c13a28a687b655688f8e10551e8df1
│ │ │ ├── c2e8e26fb3377705376b1d6d434e1233
│ │ │ ├── c3569a0e65500c3fd92ae9b8c3ac617b
│ │ │ ├── c4bcae8b1308ed48980134bb4d83f804
│ │ │ ├── c6487fc895704808bfbd28461eb5406d
│ │ │ ├── c787b5e7ee5160e73735755b872c0a41
│ │ │ ├── d719ca7fca663697fd096fb757b89920
│ │ │ ├── da939f28327bdd52576eec2c516a9ad3
│ │ │ ├── de7c51531b29594960229029a8eb6bd3
│ │ │ ├── e0de0a27b7e73c2def0370febf06b399
│ │ │ ├── e1595bc3bec4961c61a5304c1df226f0
│ │ │ ├── e2057ff9c72f6820163717d7ca69bf55
│ │ │ ├── e32a1cc092043108ec5025c1098a1dc8
│ │ │ ├── e4521446df02458bd88840687af212c5
│ │ │ ├── e5e9f136633ee06623a457e6c5bd9eac
│ │ │ ├── e6c06dd6393e96514f79db5d3bca100a
│ │ │ ├── ea077bf729e6510381278c68ee7c2b07
│ │ │ ├── ecc266c69b70073c8b0f6682498d0675
│ │ │ ├── edbfe6ac404682ef420377507d52ca4d
│ │ │ ├── f13c7b1cf4a5280dcc066d583c09bf78
│ │ │ ├── f20e83bfa143ade475b9403b9e21641f
│ │ │ ├── f8f0617cdbe162dec828ac596feae35d
│ │ │ ├── fcc0a2c84b265a77211ff0d4bd4a413a
│ │ │ ├── internal.0
│ │ │ ├── internal.1
│ │ │ ├── internal.10
│ │ │ ├── internal.11
│ │ │ ├── internal.12
│ │ │ ├── internal.13
│ │ │ ├── internal.14
│ │ │ ├── internal.15
│ │ │ ├── internal.16
│ │ │ ├── internal.17
│ │ │ ├── internal.18
│ │ │ ├── internal.19
│ │ │ ├── internal.2
│ │ │ ├── internal.20
│ │ │ ├── internal.21
│ │ │ ├── internal.22
│ │ │ ├── internal.23
│ │ │ ├── internal.24
│ │ │ ├── internal.25
│ │ │ ├── internal.26
│ │ │ ├── internal.27
│ │ │ ├── internal.28
│ │ │ ├── internal.29
│ │ │ ├── internal.3
│ │ │ ├── internal.30
│ │ │ ├── internal.31
│ │ │ ├── internal.32
│ │ │ ├── internal.33
│ │ │ ├── internal.34
│ │ │ ├── internal.35
│ │ │ ├── internal.36
│ │ │ ├── internal.37
│ │ │ ├── internal.38
│ │ │ ├── internal.39
│ │ │ ├── internal.4
│ │ │ ├── internal.40
│ │ │ ├── internal.41
│ │ │ ├── internal.42
│ │ │ ├── internal.43
│ │ │ ├── internal.44
│ │ │ ├── internal.45
│ │ │ ├── internal.46
│ │ │ ├── internal.47
│ │ │ ├── internal.48
│ │ │ ├── internal.49
│ │ │ ├── internal.5
│ │ │ ├── internal.50
│ │ │ ├── internal.51
│ │ │ ├── internal.52
│ │ │ ├── internal.53
│ │ │ ├── internal.54
│ │ │ ├── internal.55
│ │ │ ├── internal.56
│ │ │ ├── internal.57
│ │ │ ├── internal.58
│ │ │ ├── internal.59
│ │ │ ├── internal.6
│ │ │ ├── internal.60
│ │ │ ├── internal.61
│ │ │ ├── internal.62
│ │ │ ├── internal.63
│ │ │ ├── internal.64
│ │ │ ├── internal.65
│ │ │ ├── internal.66
│ │ │ ├── internal.67
│ │ │ ├── internal.68
│ │ │ ├── internal.69
│ │ │ ├── internal.7
│ │ │ ├── internal.70
│ │ │ ├── internal.71
│ │ │ ├── internal.72
│ │ │ ├── internal.73
│ │ │ ├── internal.74
│ │ │ ├── internal.75
│ │ │ ├── internal.76
│ │ │ ├── internal.77
│ │ │ ├── internal.78
│ │ │ ├── internal.79
│ │ │ ├── internal.8
│ │ │ ├── internal.80
│ │ │ ├── internal.81
│ │ │ ├── internal.82
│ │ │ ├── internal.83
│ │ │ ├── internal.84
│ │ │ ├── internal.85
│ │ │ ├── internal.86
│ │ │ ├── internal.87
│ │ │ ├── internal.88
│ │ │ ├── internal.89
│ │ │ ├── internal.9
│ │ │ ├── internal.90
│ │ │ ├── internal.91
│ │ │ ├── internal.92
│ │ │ ├── internal.93
│ │ │ ├── internal.94
│ │ │ ├── internal.95
│ │ │ ├── internal.96
│ │ │ ├── internal.97
│ │ │ └── internal.98
│ │ ├── .sbt.v2/
│ │ │ ├── v2.0107d767a345eff67ecdaed2ee5cd7ba.sbt
│ │ │ ├── v2.4e94e60265e04f0763142e20b52c0da1.sbt
│ │ │ ├── v2.60f7e23c24a8d94791cc7a8680c493f9.sbt
│ │ │ ├── v2.6d6e87e1154e95b279e5e7db414bc37b.sbt
│ │ │ ├── v2.b59473c94ff2889eca5d7165936e64b3.sbt
│ │ │ ├── v2.f0c834bc306651d2b9321fb21d3e8d8f.sbt
│ │ │ ├── v2.f71e78178af9e45e6f1d87a0c53c465c.sbt
│ │ │ ├── v2.internal.0.sbt
│ │ │ ├── v2.internal.1.sbt
│ │ │ ├── v2.internal.2.sbt
│ │ │ ├── v2.internal.3.sbt
│ │ │ ├── v2.internal.4.sbt
│ │ │ └── v2.internal.5.sbt
│ │ ├── .sbt.v3/
│ │ │ ├── 0107d767a345eff67ecdaed2ee5cd7ba
│ │ │ ├── 4e94e60265e04f0763142e20b52c0da1
│ │ │ ├── 60f7e23c24a8d94791cc7a8680c493f9
│ │ │ ├── 6d6e87e1154e95b279e5e7db414bc37b
│ │ │ ├── b59473c94ff2889eca5d7165936e64b3
│ │ │ ├── f0c834bc306651d2b9321fb21d3e8d8f
│ │ │ ├── f71e78178af9e45e6f1d87a0c53c465c
│ │ │ ├── internal.0
│ │ │ ├── internal.1
│ │ │ ├── internal.2
│ │ │ ├── internal.3
│ │ │ ├── internal.4
│ │ │ └── internal.5
│ │ ├── .sbt.v5_mhmt/
│ │ │ ├── 0107d767a345eff67ecdaed2ee5cd7ba
│ │ │ ├── 4e94e60265e04f0763142e20b52c0da1
│ │ │ ├── 60f7e23c24a8d94791cc7a8680c493f9
│ │ │ ├── 6d6e87e1154e95b279e5e7db414bc37b
│ │ │ ├── b59473c94ff2889eca5d7165936e64b3
│ │ │ ├── f0c834bc306651d2b9321fb21d3e8d8f
│ │ │ ├── f71e78178af9e45e6f1d87a0c53c465c
│ │ │ ├── internal.0
│ │ │ ├── internal.1
│ │ │ ├── internal.2
│ │ │ ├── internal.3
│ │ │ ├── internal.4
│ │ │ └── internal.5
│ │ ├── 10x-example/
│ │ │ ├── barcodes.tsv
│ │ │ ├── barcodes_renamer.tsv
│ │ │ ├── possorted_genome_bam.bam
│ │ │ ├── possorted_genome_bam.bam.bai
│ │ │ └── possorted_genome_bam_filtered.bam
│ │ ├── 2sigs.branch_0913.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── 3sigs.branch_0913.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── compare/
│ │ │ └── labels_from-test.csv
│ │ ├── duplicate-sigs/
│ │ │ └── README.md
│ │ ├── ecoli.faa
│ │ ├── ecoli.genes.fna
│ │ ├── fake-abund/
│ │ │ └── README.md
│ │ ├── gather/
│ │ │ ├── all-picklist.csv
│ │ │ ├── campy-picklist.csv
│ │ │ ├── salmonella-picklist-diffcolumn.csv
│ │ │ ├── salmonella-picklist.csv
│ │ │ └── thermotoga-picklist.csv
│ │ ├── genome-s11.fa.gz.msh.json_dump
│ │ ├── hmp-sigs/
│ │ │ ├── G36354-matches.lineages.csv
│ │ │ └── README.md
│ │ ├── lca/
│ │ │ ├── 47+63.lca.json
│ │ │ ├── bad-spreadsheet-2.csv
│ │ │ ├── bad-spreadsheet-3.csv
│ │ │ ├── bad-spreadsheet.csv
│ │ │ ├── both.lca.json
│ │ │ ├── classify-by-both.csv
│ │ │ ├── delmont-1.csv
│ │ │ ├── delmont-1.lca.json
│ │ │ ├── delmont-1.tsv
│ │ │ ├── delmont-2.csv
│ │ │ ├── delmont-2.lca.json
│ │ │ ├── delmont-3.csv
│ │ │ ├── delmont-4.csv
│ │ │ ├── delmont-5.csv
│ │ │ ├── delmont-6.csv
│ │ │ ├── dir1.lca.json
│ │ │ ├── dir2.lca.json
│ │ │ ├── old-db-format-1.json
│ │ │ ├── podar-lineage.csv
│ │ │ ├── separate.csv
│ │ │ ├── tara-delmont-SuppTable3.csv
│ │ │ ├── tully-genome-sigs.classify.csv
│ │ │ └── tully-query.delmont-db.sigs.classify.csv
│ │ ├── lca-root/
│ │ │ └── tax.csv
│ │ ├── leaves.sbt.json
│ │ ├── picklist/
│ │ │ └── empty.csv
│ │ ├── prot/
│ │ │ ├── build.sh
│ │ │ ├── dayhoff.rocksdb/
│ │ │ │ ├── 000008.log
│ │ │ │ ├── 000009.sst
│ │ │ │ ├── 000010.sst
│ │ │ │ ├── CURRENT
│ │ │ │ ├── IDENTITY
│ │ │ │ ├── LOCK
│ │ │ │ ├── MANIFEST-000005
│ │ │ │ └── OPTIONS-000007
│ │ │ ├── dna-sig.noext
│ │ │ ├── gtdb-subset-lineages.csv
│ │ │ ├── hp.rocksdb/
│ │ │ │ ├── 000008.log
│ │ │ │ ├── 000009.sst
│ │ │ │ ├── 000010.sst
│ │ │ │ ├── CURRENT
│ │ │ │ ├── IDENTITY
│ │ │ │ ├── LOCK
│ │ │ │ ├── MANIFEST-000005
│ │ │ │ └── OPTIONS-000007
│ │ │ └── protein.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── scaled/
│ │ │ ├── all.lca.json
│ │ │ ├── empty-lineage.csv
│ │ │ ├── mf.csv
│ │ │ └── pathlist.txt
│ │ ├── shewanella.faa
│ │ ├── short.fa.msh.dump
│ │ ├── sketch_fromfile/
│ │ │ ├── salmonella-badseq.csv
│ │ │ ├── salmonella-missing.csv
│ │ │ ├── salmonella-mult.csv
│ │ │ ├── salmonella-noname.csv
│ │ │ └── salmonella.csv
│ │ ├── sqlite/
│ │ │ ├── README.md
│ │ │ ├── delmont-6.csv
│ │ │ ├── index.sqldb
│ │ │ ├── lca-2.sqldb
│ │ │ ├── lca.sqldb
│ │ │ ├── prot.sqlmf
│ │ │ └── shewanella-lineage.csv
│ │ ├── subset.sbt.json
│ │ ├── tax/
│ │ │ ├── 47+63_x_gtdb-rs202.gather.csv
│ │ │ ├── bacteria_refseq_lineage.csv
│ │ │ ├── lemonade-MAG3.x.gtdb.csv
│ │ │ ├── lemonade-MAG3.x.gtdb.matches.tax.csv
│ │ │ ├── protozoa_genbank_lineage.csv
│ │ │ ├── test-empty-line.taxonomy.csv
│ │ │ ├── test-empty-ranks-2.taxonomy.csv
│ │ │ ├── test-empty-ranks-3.taxonomy.csv
│ │ │ ├── test-empty-ranks.taxonomy.csv
│ │ │ ├── test-missing-ranks.taxonomy.csv
│ │ │ ├── test-strain.taxonomy.csv
│ │ │ ├── test.LIN-taxonomy.csv
│ │ │ ├── test.ictv-taxonomy.csv
│ │ │ ├── test.ncbi-taxonomy.csv
│ │ │ ├── test.taxonomy.csv
│ │ │ ├── test1.gather.csv
│ │ │ ├── test1.gather.v450.csv
│ │ │ ├── test1.gather.with-lineages.csv
│ │ │ ├── test1.gather_old.csv
│ │ │ └── test1_x_gtdbrs202_genbank_euks.gather.csv
│ │ ├── track_abund/
│ │ │ └── 47+63.abund.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── v1.sbt.json
│ │ ├── v2.sbt.json
│ │ ├── v3.sbt.json
│ │ ├── v4.sbt.json
│ │ ├── v5.sbt.json
│ │ ├── v5_mhmt.sbt.json
│ │ ├── v6.sbt.json
│ │ └── v6.sbt.zip.mf.csv
│ ├── test__minhash_hypothesis.py
│ ├── test_api.py
│ ├── test_bugs.py
│ ├── test_cmd_index.py
│ ├── test_cmd_signature.py
│ ├── test_cmd_signature_collect.py
│ ├── test_cmd_signature_fileinfo.py
│ ├── test_cmd_signature_grep.py
│ ├── test_compare.py
│ ├── test_deprecated.py
│ ├── test_distance_utils.py
│ ├── test_hll.py
│ ├── test_index.py
│ ├── test_index_protocol.py
│ ├── test_jaccard.py
│ ├── test_lca.py
│ ├── test_lca_db_protocol.py
│ ├── test_lca_functions.py
│ ├── test_manifest.py
│ ├── test_manifest_protocol.py
│ ├── test_minhash.py
│ ├── test_moltypes.py
│ ├── test_nodegraph.py
│ ├── test_np_utils.py
│ ├── test_picklist.py
│ ├── test_plugin_framework.py
│ ├── test_prefetch.py
│ ├── test_revindex.py
│ ├── test_rustobj.py
│ ├── test_sbt.py
│ ├── test_search.py
│ ├── test_signature.py
│ ├── test_sketchcomparison.py
│ ├── test_sourmash.py
│ ├── test_sourmash_args.py
│ ├── test_sourmash_compute.py
│ ├── test_sourmash_sketch.py
│ ├── test_sqlite_index.py
│ ├── test_tax.py
│ ├── test_tax_utils.py
│ └── test_test_framework.py
├── tox.ini
└── utils/
├── .gitignore
├── README.md
├── cardinality_estimate_confidence.py
├── check-tree.py
├── compute-dna-mh-another-way.py
├── compute-input-prot-another-way.py
├── compute-prot-mh-another-way.py
├── toml-to-zenodo-json.py
└── trim-noV.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .cargo/config.toml
================================================
[target.x86_64-unknown-linux-musl]
rustflags = ["-C", "target-feature=-crt-static"]
[target.aarch64-unknown-linux-musl]
rustflags = ["-C", "target-feature=-crt-static"]
================================================
FILE: .envrc
================================================
#use flake
PATH=~/.pixi/bin:$PATH
watch_file pixi.lock
eval "$(pixi shell-hook)"
================================================
FILE: .git-blame-ignore-revs
================================================
# Pre-commit updates (#2427)
fee62922d8857ce93f1d4e90fd7240629d606997
================================================
FILE: .git_archival.txt
================================================
ref-names: $Format:%D$
================================================
FILE: .gitattributes
================================================
.git_archival.txt export-subst
tests/test-data/*.sig linguist-detectable=false
tests/test-data/*/*.sig linguist-detectable=false
tests/test-data/*/*/*.sig linguist-detectable=false
tests/test-data/.sbt.v2/*.sbt linguist-detectable=false
include/sourmash.h linguist-language=C
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
Please replace this text with:
* a brief description of your changes in this PR
* which issues this fixes in the issue tracker, if any ("Fixes #XXX")
* which issues this PR is related to, if any ("Ref #XXX")
Please also be sure to note here if file formats, command-line
interface, and/or the top-level sourmash API will change because of
this PR.
If you are a new contributor, please add your name and
[your ORCID](https://orcid.org) to the `pyproject.toml` author list
(maintaining alphabetical order by last name).
If you don't have an ORCID, please
[register for one](https://orcid.org/register).
Once the items above are done, and all checks pass, request a review!
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
commit-message:
prefix: Build(deps-py)
groups:
dependencies:
patterns:
- "*"
- package-ecosystem: cargo
directory: "/"
schedule:
interval: weekly
allow:
- dependency-type: "direct"
open-pull-requests-limit: 10
commit-message:
prefix: Build(deps-rs)
ignore:
- dependency-name: "byteorder"
- dependency-name: "wasm-bindgen"
- dependency-name: "once_cell"
- dependency-name: "chrono"
- dependency-name: "js-sys"
- dependency-name: "web-sys"
groups:
dependencies:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
commit-message:
prefix: Build(ci)
schedule:
interval: weekly
================================================
FILE: .github/workflows/asv.yml
================================================
name: asv benchmarks
permissions:
contents: read
on:
push:
branches: [latest]
pull_request:
merge_group:
schedule:
- cron: "0 0 * * *" # daily
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: make latest branch available
run: |
git checkout latest
git checkout -
- name: Set up Python 3.11
uses: actions/setup-python@v6
with:
python-version: "3.11"
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Runs benchmarks against latest
run: tox -e asv
================================================
FILE: .github/workflows/build_wheel.yml
================================================
name: cibuildwheel
permissions:
contents: write
on:
push:
branches: [latest]
tags: v*
pull_request:
merge_group:
schedule:
- cron: "0 0 * * *" # daily
jobs:
build_wheels:
name: Build wheels for ${{ matrix.os }}-${{ matrix.arch }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
build: [
linux-x86_64,
macos-x86_64,
macos-arm64,
]
include:
- build: linux-x86_64
os: ubuntu-latest
arch: x86_64
macos_target: ''
- build: macos-x86_64
os: macos-latest
arch: x86_64
macos_target: 'MACOSX_DEPLOYMENT_TARGET=11.0 CARGO_BUILD_TARGET=x86_64-apple-darwin'
- build: macos-arm64
os: macos-latest
arch: arm64
macos_target: 'MACOSX_DEPLOYMENT_TARGET=11.0 CARGO_BUILD_TARGET=aarch64-apple-darwin'
fail-fast: false
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-python@v6
name: Install Python
with:
python-version: '3.13'
- name: Build wheels
uses: pypa/cibuildwheel@v3.4.1
env:
CIBW_ENVIRONMENT_MACOS: ${{ matrix.macos_target }}
CIBW_ARCHS_LINUX: ${{ matrix.arch }}
CIBW_ARCHS_MACOS: ${{ matrix.arch }}
- uses: actions/upload-artifact@v7
with:
name: wheel-${{ matrix.build }}-${{ matrix.os }}
path: './wheelhouse/sourmash*.whl'
build_wasm:
runs-on: ubuntu-latest
if: false # disable for now, need to fix emsdk with Rust: https://github.com/emscripten-core/emscripten/pull/24359
steps:
- uses: actions/checkout@v6
- name: Build wheels
uses: pypa/cibuildwheel@v3.4.1
env:
CIBW_PLATFORM: pyodide
CIBW_BUILD: 'cp313-pyodide_wasm32'
- uses: actions/upload-artifact@v7
with:
name: wheel-wasm
path: './wheelhouse/sourmash*.whl'
release:
name: Publish wheels
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
# needs: [build_wheels, build_wasm]
needs: [build_wheels]
steps:
- name: Fetch wheels from artifacts
id: fetch_artifacts
uses: actions/download-artifact@v8
with:
path: 'wheels/'
# if it matches a Python release tag, upload to github releases
- name: Release
uses: softprops/action-gh-release@v3
with:
files: |
${{steps.fetch_artifacts.outputs.download-path}}/wheel-*/*
================================================
FILE: .github/workflows/build_wheel_all_archs.yml
================================================
name: maturin wheels
permissions:
contents: write
on:
pull_request: # use for testing modifications to this action
merge_group:
push:
branches: [latest]
tags: v*
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # daily
jobs:
linux:
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64]
#target: [aarch64, ppc64le]
#target: [aarch64, s390x, ppc64le]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist --find-interpreter --zig --strip
sccache: 'true'
manylinux: auto
container: 'off'
- name: Upload wheels
uses: actions/upload-artifact@v7
with:
name: wheel-${{ matrix.target }}
path: dist
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with:
python-version: '3.12'
architecture: ${{ matrix.target }}
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: x64
args: --release --out dist --find-interpreter
sccache: 'true'
- name: Upload wheels
uses: actions/upload-artifact@v7
with:
name: wheel-win64
path: dist
release:
name: Publish wheels
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
needs: [linux, windows]
steps:
- name: Fetch wheels from artifacts
id: fetch_artifacts
uses: actions/download-artifact@v8
with:
path: 'wheels/'
# if it matches a Python release tag, upload to github releases
- name: Release
uses: softprops/action-gh-release@v3
with:
files: |
${{steps.fetch_artifacts.outputs.download-path}}/wheel-*/*
================================================
FILE: .github/workflows/codspeed.yml
================================================
name: codspeed-benchmarks
permissions:
contents: read
on:
# Run on pushes to the main branch
push:
branches:
- "latest"
# Run on pull requests
pull_request:
# TODO: Disabled temporarily for https://github.com/CodSpeedHQ/runner/issues/55
# merge_group:
# `workflow_dispatch` allows CodSpeed to trigger backtest
# performance analysis in order to generate initial data.
workflow_dispatch:
jobs:
benchmarks-rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup rust toolchain, cache and cargo-codspeed binary
uses: moonrepo/setup-rust@v1
with:
channel: stable
cache-target: release
bins: cargo-codspeed
- name: Build the benchmark target(s)
run: cargo codspeed build -p sourmash
- name: Run the benchmarks
uses: CodSpeedHQ/action@v4
with:
run: "cd src/core && cargo codspeed run"
token: ${{ secrets.CODSPEED_TOKEN }}
================================================
FILE: .github/workflows/dev_envs.yml
================================================
name: "Dev env instructions"
on:
pull_request:
merge_group:
push:
branches: [latest]
concurrency:
group: ${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/latest' }}
permissions:
contents: read
env:
PIXI_VERSION: "v0.66.0"
jobs:
nix:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install Nix
uses: samueldr/lix-gha-installer-action@7b7f14d320d6aacfb65bd1ef761566b3b69e474c
- run: nix run .# -- --version
- run: nix develop --command bash -c "tox -e py313"
pixi:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-14]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: set up pixi
uses: prefix-dev/setup-pixi@v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
frozen: true
- name: run tests for 3.12
shell: pixi run bash {0}
run: tox -e py312
mamba:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-14]
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: cache conda
uses: actions/cache@v5
env:
CACHE_NUMBER: 0
with:
path: ~/conda_pkgs_dir
key:
${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }}
- name: setup conda
uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167
with:
python-version: "3.12"
miniforge-version: latest
environment-file: dev.yml
activate-environment: sourmash_dev
auto-activate-base: false
- name: run tests for 3.12
shell: bash -l {0}
run: tox -e py312
================================================
FILE: .github/workflows/draft-pdf.yml
================================================
on: [push]
permissions:
contents: read
jobs:
paper:
runs-on: ubuntu-latest
name: Paper Draft
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Build draft PDF
uses: openjournals/openjournals-draft-action@master
with:
journal: joss
# This should be the path to the paper within your repo.
paper-path: paper.md
- name: Upload
uses: actions/upload-artifact@v7
with:
name: paper
# This is the output path where Pandoc will write the compiled
# PDF. Note, this should be the same directory as the input
# paper.md
path: paper.pdf
================================================
FILE: .github/workflows/hypothesis.yml
================================================
name: Hypothesis tests
permissions:
contents: read
on:
push:
branches: [latest]
pull_request:
merge_group:
schedule:
- cron: "0 0 * * *" # daily
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python 3.12
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Run Hypothesis tests
run: tox -e hypothesis,coverage
- name: Upload Python coverage to codecov
uses: codecov/codecov-action@v3
with:
flags: hypothesis-py
fail_ci_if_error: true
files: .tox/coverage.xml
================================================
FILE: .github/workflows/metadata.yml
================================================
name: Metadata checks
permissions:
contents: read
on:
push:
branches: [latest]
pull_request:
merge_group:
schedule:
- cron: "0 0 * * *" # daily
jobs:
archive:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v6
- name: Trigger new archival in software heritage on new tags
if: startsWith(github.ref, 'refs/tags/')
run: curl https://archive.softwareheritage.org/api/1/origin/save/git/url/https://github.com/sourmash-bio/sourmash.git/
================================================
FILE: .github/workflows/python.yml
================================================
# note: to invalidate caches, adjust the pip-v? number below.
name: Python tests
on:
push:
branches: [latest]
pull_request:
merge_group:
schedule:
- cron: "0 0 * * *" # daily
permissions:
contents: read
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
py: ["3.12", "3.11", "3.13"]
fail-fast: false
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.py }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.py }}
- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
- name: pip cache
uses: actions/cache@v5
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ runner.os }}-pip-v4-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-v4-
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
- name: Set up Pandoc
uses: r-lib/actions/setup-pandoc@v2
- name: Set up IPFS
if: startsWith(runner.os, 'Linux') && (matrix.py == '3.11')
uses: ibnesayeed/setup-ipfs@master
with:
ipfs_version: 0.6
run_daemon: true
- name: Start Redis
if: startsWith(runner.os, 'Linux') && (matrix.py == '3.11')
uses: supercharge/redis-github-action@v2
with:
redis-version: 6
- name: tox cache
uses: actions/cache@v5
with:
path: .tox/
key: ${{ runner.os }}-tox-v4-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-tox-v4-
- name: Test with tox
run: tox
env:
PYTHONDEVMODE: 1
- name: Upload Python coverage to codecov
uses: codecov/codecov-action@v3
with:
flags: python
fail_ci_if_error: true
files: .tox/coverage.xml
================================================
FILE: .github/workflows/rust.yml
================================================
name: Rust checks
on:
push:
branches: [latest]
tags:
- 'r*'
pull_request:
merge_group:
schedule:
- cron: "0 0 * * *" # daily
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
PIXI_VERSION: "v0.66.0"
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Run cargo check
run: |
pixi run cargo check
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
build: [beta, stable, windows, macos]
include:
- build: macos
os: macos-latest
rust: stable
continue: false
- build: windows
os: windows-latest
rust: stable
continue: true
- build: beta
os: ubuntu-latest
rust: beta
continue: false
- build: stable
os: ubuntu-latest
rust: stable
continue: false
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Run tests
if: matrix.os != 'windows-latest'
run: |
pixi run rust-tests
- name: Run tests (windows)
if: matrix.os == 'windows-latest'
run: |
# branchwater feature triggers a rocksdb error on windows,
# need to debug. For now using just default features
pixi run cargo nextest run
test_all_features:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Run tests for all feature combinations
run: pixi run check-features
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Collect coverage data
run: pixi run coverage-rust
- name: Upload Rust coverage to codecov
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
with:
flags: rust
fail_ci_if_error: true
files: lcov.info
lints:
name: Lints
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
build: [beta, stable]
include:
- build: beta
rust: beta
- build: stable
rust: stable
steps:
- name: Checkout sources
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Run cargo fmt
run: |
pixi run cargo fmt --all -- --check
- name: Run cargo clippy
run: |
pixi run cargo clippy --all -- -D warnings
wasm-pack:
name: Check if wasm-pack builds a valid package for the sourmash crate
runs-on: ubuntu-latest
permissions:
id-token: write # needed to publish to NPM
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: run wasm tests
continue-on-error: true ## TODO: remove this when tests works again...
run: pixi run -e wasm test-wasm
- name: run wasm-pack build
run: pixi run -e wasm build-wasm
- name: Prepare package for NPM publishing
run: pixi run -e wasm pack-npm
- name: Publish to NPM
if: startsWith(github.ref, 'refs/tags/r')
run: pixi run -e wasm publish-npm
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
path: 'pkg/sourmash*.tgz'
publish:
name: Publish (on tags, dry-run otherwise)
runs-on: ubuntu-latest
permissions:
id-token: write # needed to publish to crates.io
steps:
- name: Checkout sources
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Check semver
run: pixi run semver-check
- name: Make sure we can publish the sourmash crate
run: pixi run cargo publish --dry-run --manifest-path src/core/Cargo.toml
# Publish to crates.io on tags
- name: Publish to crates.io
if: startsWith(github.ref, 'refs/tags/r')
run: pixi run cargo publish --manifest-path src/core/Cargo.toml
minimum_rust_version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: check if README matches MSRV defined here
run: grep '1.85.0' src/core/README.md
- name: Check if it builds properly
run: pixi run check-msrv
check_cbindgen:
name: "Check if cbindgen runs cleanly for generating the C headers"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: set up pixi
uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5
with:
pixi-version: ${{ env.PIXI_VERSION }}
cache: true
cache-write: ${{ github.event_name == 'push' && github.ref_name == 'latest' }}
frozen: true
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- run: pixi run cbindgen-generate
- name: check if headers have the same content
run: |
git update-index --refresh
git diff
git diff-index --quiet HEAD -- include/sourmash.h || echo "::error file=include/sourmash.h::Header doesn't match committed file, did you forget to rerun cbindgen?"
================================================
FILE: .gitignore
================================================
*~
*.fa
*.fastq.gz
*.abundtrim
*.keep
*.pyc
*.sig
*.png
*.labels.txt
distances
*.npy
dist
build
sourmash.egg-info
.ipynb_checkpoints
.cache
*.so
.coverage
.pytest_cache
**/*.pyc
.python-version
src/sourmash/version.py
*.DS_Store
.tox
src/sourmash/_lowlevel/*
.env
target/
.eggs
.asv
pkg/
wasm-pack.log
.hypothesis
# IDEs
.vscode/
# nix
.direnv/
result
# pixi
.pixi/
================================================
FILE: .pre-commit-config.yaml
================================================
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-ast
- id: check-builtin-literals
- id: check-docstring-first
- id: check-merge-conflict
- id: check-yaml
- id: check-toml
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.11
hooks:
- id: ruff-format
- id: ruff
args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"]
# - repo: https://github.com/tox-dev/tox-ini-fmt
# rev: "1.3.1"
# hooks:
# - id: tox-ini-fmt
# args: ["-p", "fix_lint"]
- repo: meta
hooks:
- id: check-hooks-apply
- id: check-useless-excludes
================================================
FILE: .readthedocs.yml
================================================
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
build:
os: ubuntu-22.04
tools:
python: "3.14"
rust: "1.86"
apt_packages:
- llvm-dev
- libclang-dev
- clang
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: doc/conf.py
python:
install:
- method: pip
path: .
extra_requirements:
- doc
================================================
FILE: .sonarcloud.properties
================================================
================================================
FILE: .zenodo.json
================================================
{"creators": [{"name": "Luiz Irber", "orcid": "0000-0003-4371-9659"}, {"name": "N. Tessa Pierce-Ward", "orcid": "0000-0002-2942-5331"}, {"name": "Mohamed Abuelanin", "orcid": "0000-0002-3419-4785"}, {"name": "Harriet Alexander", "orcid": "0000-0003-1308-8008"}, {"name": "Abhishek Anant", "orcid": "0000-0002-5751-2010"}, {"name": "Keya Barve", "orcid": "0000-0003-3241-2117"}, {"name": "Colton Baumler", "orcid": "0000-0002-5926-7792"}, {"name": "Olga Botvinnik", "orcid": "0000-0003-4412-7970"}, {"name": "Phillip Brooks", "orcid": "0000-0003-3987-244X"}, {"name": "Peter Cock", "orcid": "0000-0001-9513-9993"}, {"name": "Daniel Dsouza", "orcid": "0000-0001-7843-8596"}, {"name": "Jade Gardner", "orcid": "0009-0005-0787-5752"}, {"name": "Laurent Gautier", "orcid": "0000-0003-0638-3391"}, {"name": "Tim Head", "orcid": "0000-0003-0931-3698"}, {"name": "Mahmudur Rahman Hera", "orcid": "0000-0002-5992-9012"}, {"name": "Hannah Eve Houts", "orcid": "0000-0002-7954-4793"}, {"name": "Lisa K. Johnson", "orcid": "0000-0002-3600-7218"}, {"name": "Fabian Kl\u00f6tzl", "orcid": "0000-0002-6930-0592"}, {"name": "David Koslicki", "orcid": "0000-0002-0640-954X"}, {"name": "Katrin Leinweber", "orcid": "0000-0001-5135-5758"}, {"name": "Marisa Lim", "orcid": "0000-0003-2097-8818"}, {"name": "Ricky Lim", "orcid": "0000-0003-1313-7076"}, {"name": "Bradley Nelson", "orcid": "0009-0001-1553-932X"}, {"name": "Ivan Ogasawara", "orcid": "0000-0001-5049-4289"}, {"name": "Taylor Reiter", "orcid": "0000-0002-7388-421X"}, {"name": "Camille Scott", "orcid": "0000-0001-8822-8779"}, {"name": "Andreas Sj\u00f6din", "orcid": "0000-0001-5350-4219"}, {"name": "Connor T. Skennerton", "orcid": "0000-0003-1320-4873"}, {"name": "Jason Stajich", "orcid": "0000-0002-7591-0020"}, {"name": "Daniel Standage", "orcid": "0000-0003-0342-8531"}, {"name": "S. Joshua Swamidass", "orcid": "0000-0003-2191-0778"}, {"name": "Connor Tiffany", "orcid": "0000-0001-8188-7720"}, {"name": "Pranathi Vemuri", "orcid": "0000-0002-5748-9594"}, {"name": "Erik Young", "orcid": "0000-0002-9195-9801"}, {"name": "Nick H", "orcid": "0000-0002-1685-302X"}, {"name": "C. Titus Brown", "orcid": "0000-0001-6001-2677"}]}
================================================
FILE: CITATION.cff
================================================
cff-version: "1.2.0"
authors:
- family-names: Irber
given-names: Luiz
orcid: "https://orcid.org/0000-0003-4371-9659"
- family-names: Pierce-Ward
given-names: N. Tessa
orcid: "https://orcid.org/0000-0002-2942-5331"
- family-names: Abuelanin
given-names: Mohamed
orcid: "https://orcid.org/0000-0002-3419-4785"
- family-names: Alexander
given-names: Harriet
orcid: "https://orcid.org/0000-0003-1308-8008"
- family-names: Anant
given-names: Abhishek
orcid: "https://orcid.org/0000-0002-5751-2010"
- family-names: Barve
given-names: Keya
orcid: "https://orcid.org/0000-0003-3241-2117"
- family-names: Baumler
given-names: Colton
orcid: "https://orcid.org/0000-0002-5926-7792"
- family-names: Botvinnik
given-names: Olga
orcid: "https://orcid.org/0000-0003-4412-7970"
- family-names: Brooks
given-names: Phillip
orcid: "https://orcid.org/0000-0003-3987-244X"
- family-names: Dsouza
given-names: Daniel
orcid: "https://orcid.org/0000-0001-7843-8596"
- family-names: Gautier
given-names: Laurent
orcid: "https://orcid.org/0000-0003-0638-3391"
- family-names: Rahman Hera
given-names: Mahmudur
orcid: "https://orcid.org/0000-0002-5992-9012"
- family-names: Houts
given-names: Hannah Eve
orcid: "https://orcid.org/0000-0002-7954-4793"
- family-names: Johnson
given-names: Lisa K.
orcid: "https://orcid.org/0000-0002-3600-7218"
- family-names: Klötzl
given-names: Fabian
orcid: "https://orcid.org/0000-0002-6930-0592"
- family-names: Koslicki
given-names: David
orcid: "https://orcid.org/0000-0002-0640-954X"
- family-names: Lim
given-names: Marisa
orcid: "https://orcid.org/0000-0003-2097-8818"
- family-names: Lim
given-names: Ricky
orcid: "https://orcid.org/0000-0003-1313-7076"
- family-names: Nelson
given-names: Bradley
orcid: "https://orcid.org/0009-0001-1553-932X"
- family-names: Ogasawara
given-names: Ivan
orcid: "https://orcid.org/0000-0001-5049-4289"
- family-names: Reiter
given-names: Taylor
orcid: "https://orcid.org/0000-0002-7388-421X"
- family-names: Scott
given-names: Camille
orcid: "https://orcid.org/0000-0001-8822-8779"
- family-names: Sjödin
given-names: Andreas
orcid: "https://orcid.org/0000-0001-5350-4219"
- family-names: Standage
given-names: Daniel
orcid: "https://orcid.org/0000-0003-0342-8531"
- family-names: Swamidass
given-names: S. Joshua
orcid: "https://orcid.org/0000-0003-2191-0778"
- family-names: Tiffany
given-names: Connor
orcid: "https://orcid.org/0000-0001-8188-7720"
- family-names: Vemuri
given-names: Pranathi
orcid: "https://orcid.org/0000-0002-5748-9594"
- family-names: Young
given-names: Erik
orcid: "https://orcid.org/0000-0002-9195-9801"
- family-names: Brown
given-names: C. Titus
orcid: "https://orcid.org/0000-0001-6001-2677"
contact:
- family-names: Brown
given-names: C. Titus
orcid: "https://orcid.org/0000-0001-6001-2677"
doi: 10.5281/zenodo.11557883
message: If you use this software, please cite our article in the
Journal of Open Source Software.
preferred-citation:
authors:
- family-names: Irber
given-names: Luiz
orcid: "https://orcid.org/0000-0003-4371-9659"
- family-names: Pierce-Ward
given-names: N. Tessa
orcid: "https://orcid.org/0000-0002-2942-5331"
- family-names: Abuelanin
given-names: Mohamed
orcid: "https://orcid.org/0000-0002-3419-4785"
- family-names: Alexander
given-names: Harriet
orcid: "https://orcid.org/0000-0003-1308-8008"
- family-names: Anant
given-names: Abhishek
orcid: "https://orcid.org/0000-0002-5751-2010"
- family-names: Barve
given-names: Keya
orcid: "https://orcid.org/0000-0003-3241-2117"
- family-names: Baumler
given-names: Colton
orcid: "https://orcid.org/0000-0002-5926-7792"
- family-names: Botvinnik
given-names: Olga
orcid: "https://orcid.org/0000-0003-4412-7970"
- family-names: Brooks
given-names: Phillip
orcid: "https://orcid.org/0000-0003-3987-244X"
- family-names: Dsouza
given-names: Daniel
orcid: "https://orcid.org/0000-0001-7843-8596"
- family-names: Gautier
given-names: Laurent
orcid: "https://orcid.org/0000-0003-0638-3391"
- family-names: Hera
given-names: Mahmudur Rahman
orcid: "https://orcid.org/0000-0002-5992-9012"
- family-names: Houts
given-names: Hannah Eve
orcid: "https://orcid.org/0000-0002-7954-4793"
- family-names: Johnson
given-names: Lisa K.
orcid: "https://orcid.org/0000-0002-3600-7218"
- family-names: Klötzl
given-names: Fabian
orcid: "https://orcid.org/0000-0002-6930-0592"
- family-names: Koslicki
given-names: David
orcid: "https://orcid.org/0000-0002-0640-954X"
- family-names: Lim
given-names: Marisa
orcid: "https://orcid.org/0000-0003-2097-8818"
- family-names: Lim
given-names: Ricky
orcid: "https://orcid.org/0000-0003-1313-7076"
- family-names: Nelson
given-names: Bradley
orcid: "https://orcid.org/0009-0001-1553-932X"
- family-names: Ogasawara
given-names: Ivan
orcid: "https://orcid.org/0000-0001-5049-4289"
- family-names: Reiter
given-names: Taylor
orcid: "https://orcid.org/0000-0002-7388-421X"
- family-names: Scott
given-names: Camille
orcid: "https://orcid.org/0000-0001-8822-8779"
- family-names: Sjödin
given-names: Andreas
orcid: "https://orcid.org/0000-0001-5350-4219"
- family-names: Standage
given-names: Daniel
orcid: "https://orcid.org/0000-0003-0342-8531"
- family-names: Swamidass
given-names: S. Joshua
orcid: "https://orcid.org/0000-0003-2191-0778"
- family-names: Tiffany
given-names: Connor
orcid: "https://orcid.org/0000-0001-8188-7720"
- family-names: Vemuri
given-names: Pranathi
orcid: "https://orcid.org/0000-0002-5748-9594"
- family-names: Young
given-names: Erik
orcid: "https://orcid.org/0000-0002-9195-9801"
- family-names: Brown
given-names: C. Titus
orcid: "https://orcid.org/0000-0001-6001-2677"
date-published: 2024-06-28
doi: 10.21105/joss.06830
issn: 2475-9066
issue: 98
journal: Journal of Open Source Software
publisher:
name: Open Journals
start: 6830
title: "sourmash v4: A multitool to quickly search, compare, and
analyze genomic and metagenomic data sets"
type: article
url: "https://joss.theoj.org/papers/10.21105/joss.06830"
volume: 9
title: "sourmash v4: A multitool to quickly search, compare, and analyze
genomic and metagenomic data sets"
================================================
FILE: CODE_OF_CONDUCT.rst
================================================
Contributor Code of Conduct
===========================
As contributors and maintainers of this project, we pledge to respect
all people who contribute through reporting issues, posting feature
requests, updating documentation, submitting pull requests or patches,
and other activities.
We are committed to making participation in this project a
harassment-free experience for everyone, regardless of level of
experience, gender, gender identity and expression, sexual orientation,
disability, personal appearance, body size, race, age, or religion.
Examples of unacceptable behavior by participants include the use of
sexual language or imagery, derogatory comments or personal attacks,
trolling, public or private harassment, insults, or other unprofessional
conduct.
Project maintainers have the right and responsibility to remove, edit,
or reject comments, commits, code, wiki edits, issues, and other
contributions that are not aligned to this Code of Conduct. Project
maintainers or contributors who do not follow the Code of Conduct may be
removed from the project team.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by emailing `titus@idyll.org <mailto:titus@idyll.org>`__ which only
goes to C. Titus Brown. To report an issue involving Titus please email `Judi
Brown Clarke, Ph.D. <mailto:jbc@egr.msu.edu>`__ the Diversity Director at the
BEACON Center for the Study of Evolution in Action, an NSF Center for Science
and Technology.
This Code of Conduct is adapted from the `Contributor
Covenant <http://contributor-covenant.org>`__, version 1.0.0, available at
http://contributor-covenant.org/version/1/0/0/
================================================
FILE: CONTRIBUTING.md
================================================
We welcome contributions! We use
[GitHub Flow style development](https://guides.github.com/introduction/flow/).
Please set up a pull request against our `latest` branch with any changes
you want us to consider merging.
For more info, check the [developer information](https://sourmash.readthedocs.io/en/latest/developer.html)
section in our docs.
================================================
FILE: Cargo.toml
================================================
[workspace]
members = [
"src/core",
]
default-members = ["src/core"]
resolver = "2"
[profile.test]
opt-level = 1
================================================
FILE: LICENSE
================================================
=======
License
=======
Files: *
Copyright: 2016, The Regents of the University of California.
License: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Regents of the University of
California, nor the names of contributors may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Files: third-party/smhasher/*
Copyright: none.
License: public-domain
Quoting from the file header: "MurmurHash3 was written by Austin Appleby,
and is placed in the public domain. The author hereby disclaims copyright to
this source code."
================================================
FILE: MANIFEST.in
================================================
include LICENSE Makefile README.md requirements.txt
include Cargo.toml
include include/sourmash.h
prune .eggs
global-exclude *.rlib
global-exclude *.orig
global-exclude *.pyc
global-exclude *.so
prune tests/test-data
global-exclude *.git
================================================
FILE: Makefile
================================================
PYTHON ?= python
all: build
.PHONY:
build: .PHONY
$(PYTHON) -m pip install -e .
clean:
$(PYTHON) -m pip uninstall -y sourmash
rm -rf src/sourmash/_lowlevel
cd doc && make clean
install: build
offline:
pip install -e . --no-index --find-links '.' --no-build-isolation
dist: FORCE
$(PYTHON) -m build --sdist
wheel:
$(PYTHON) -m maturin build -r
test: .PHONY
tox -e py311
cargo nextest run
doc: .PHONY
tox -e docs
include/sourmash.h: src/core/src/lib.rs \
src/core/src/ffi/mod.rs \
src/core/src/ffi/hyperloglog.rs \
src/core/src/ffi/minhash.rs \
src/core/src/ffi/signature.rs \
src/core/src/ffi/nodegraph.rs \
src/core/src/ffi/index/mod.rs \
src/core/src/ffi/index/revindex.rs \
src/core/src/ffi/storage.rs \
src/core/src/ffi/manifest.rs \
src/core/src/errors.rs \
src/core/cbindgen.toml
cd src/core && \
RUSTC_BOOTSTRAP=1 cbindgen -c cbindgen.toml . -o ../../$@ -v && \
touch ../../$@
coverage: all
tox -e coverage
benchmark:
tox -e asv
cargo bench
check:
cargo build
cargo nextest run
cargo bench
last-tag:
git fetch -p -q; git tag -l | sort -V | tail -1
wasm:
wasm-pack build src/core -d ../../pkg -- --features 'niffler/wasm'
wasm-test:
wasm-pack test --node src/core -- --features 'niffler/wasm'
wasi:
cargo wasi build
FORCE:
================================================
FILE: README.md
================================================
# sourmash
Quickly search, compare, and analyze genomic and metagenomic data sets.
[](https://www.repostatus.org/#active)
<a href="https://github.com/sourmash-bio/sourmash/blob/latest/LICENSE"><img alt="License: 3-Clause BSD" src="https://img.shields.io/badge/License-BSD%203--Clause-blue.svg"></a>
[](http://sourmash.readthedocs.io/en/latest/)
[](https://gitter.im/sourmash-bio/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[](https://doi.org/10.21105/joss.06830)
[](https://github.com/pyOpenSci/software-submission/issues/129)
[](https://anaconda.org/bioconda/sourmash)
<a href="https://pypi.org/project/sourmash/"><img alt="PyPI" src="https://badge.fury.io/py/sourmash.svg"></a>
[](https://anaconda.org/conda-forge/sourmash-minimal)
[](https://packages.debian.org/testing/sourmash) [](https://packages.debian.org/unstable/sourmash)



[](https://github.com/sourmash-bio/sourmash/actions/)
[](https://codecov.io/gh/sourmash-bio/sourmash)
<p align="center"><img src="https://raw.githubusercontent.com/sourmash-bio/sourmash/latest/doc/_static/logo.png" height="256" /></p>
Usage:
sourmash sketch dna *.fq.gz
sourmash compare *.sig -o distances.cmp -k 31
sourmash plot distances.cmp
sourmash 1.0 is [published on JOSS](https://doi.org/10.21105/joss.06830); please cite that paper if you use sourmash (`doi: 10.21105/joss.06830`):.
The latest major release is sourmash v4, which has several
command-line and Python incompatibilities with previous
versions. Please
[visit our migration guide](https://sourmash.readthedocs.io/en/latest/support.html#migrating-from-sourmash-v3-x-to-sourmash-4-x)
to upgrade!
----
sourmash is a k-mer analysis multitool, and we aim to provide stable, robust programmatic and command-line APIs for a variety of sequence comparisons. Some of our special sauce includes:
- `FracMinHash` sketching, which enables accurate comparisons (including ANI) between data sets of different sizes
- `sourmash gather`, a combinatorial k-mer approach for more accurate metagenomic profiling
Please see the [sourmash publications](https://sourmash.readthedocs.io/en/latest/publications.html#sourmash-fundamentals) for details.
The name is a riff off of [Mash](https://github.com/marbl/Mash),
combined with @ctb's love of whiskey.
([Sour mash](https://en.wikipedia.org/wiki/Sour_mash) is used in
making whiskey.)
Maintainers: [C. Titus Brown](mailto:titus@idyll.org) ([@ctb](http://github.com/ctb)), [Luiz C. Irber, Jr](mailto:luiz@sourmash.bio) ([@luizirber](http://github.com/luizirber)), and [N. Tessa Pierce-Ward](mailto:tessa@sourmash.bio) ([@bluegenes](http://github.com/bluegenes)).
sourmash was initially developed by the
[Lab for Data-Intensive Biology](http://ivory.idyll.org/lab/) at the
[UC Davis School of Veterinary Medicine](http://www.vetmed.ucdavis.edu),
and now includes contributions from the global research and developer
community.
## Installation
We recommend using conda-forge to install sourmash:
```
conda install -c conda-forge sourmash-minimal
```
This will install the latest stable version of sourmash 4.
You can also use pip to install sourmash:
```
pip install sourmash
```
A quickstart tutorial [is available](https://sourmash.readthedocs.io/en/latest/tutorials.html).
### Requirements
sourmash runs under Python 3.11 and later on Windows, Mac OS X, and
Linux. The base requirements are screed, cffi, numpy, matplotlib, and
scipy. Conda will install everything necessary, and is
our recommended installation method (see below).
### Installation with conda
conda-forge is a community maintained channel for the
[conda](http://conda.pydata.org/docs/intro.html) package manager.
[installing conda](https://docs.conda.io/projects/conda/en/latest/user-guide/install/),
you can install sourmash by running:
```bash
$ conda create -n sourmash_env -c conda-forge sourmash-minimal
$ conda activate sourmash_env
$ sourmash --help
```
which will install
[the latest released version](https://github.com/sourmash-bio/sourmash/releases).
## Support
For questions, please open an issue [on Github](https://github.com/sourmash-bio/sourmash/issues), or ask in our [chat](https://gitter.im/sourmash-bio/community?utm_source=share-link&utm_medium=link&utm_campaign=share-link).
## Development
Development happens on github at
[sourmash-bio/sourmash](https://github.com/sourmash-bio/sourmash).
sourmash is developed in Python and Rust, and you will need a Rust
environment to build it; see [the developer notes](doc/developer.md)
for our suggested development setup.
After installation, `sourmash` is the main command-line entry point;
run it with `python -m sourmash`, or do `pip install -e /path/to/repo` to
do a developer install in a virtual environment.
The `sourmash/` directory contains the Python library and command-line interface code.
The `src/core/` directory contains the Rust library implementing core
functionality.
Tests require py.test and can be run with `make test`.
Please see [the developer notes](doc/developer.md) for more information
on getting set up with a development environment.
CTB
Jan 2024
================================================
FILE: asv.conf.json
================================================
{
"version": 1,
"project": "sourmash",
"project_url": "https://github.com/sourmash-bio/sourmash",
"repo": ".",
"branches": ["latest"],
"dvcs": "git",
"environment_type": "virtualenv",
"env_dir": ".asv/env",
"results_dir": ".asv/results",
"html_dir": ".asv/html",
"build_cache_size": 8,
"build_command": [
"python -m pip install 'setuptools_scm[toml]>=4,<6' milksnake maturin",
"PIP_NO_BUILD_ISOLATION=false python -mpip wheel --no-deps --no-index -w {build_cache_dir} {build_dir}"
]
}
================================================
FILE: benchmarks/README.md
================================================
# benchmarks for asv ([airspeed velocity](https://asv.readthedocs.io/en/stable/index.html))
The code in here is run by GitHub Actions during continuous integration.
To test quickly, run:
```
asv run --show-stderr --quick
```
================================================
FILE: benchmarks/__init__.py
================================================
================================================
FILE: benchmarks/benchmarks.py
================================================
import random
from tempfile import NamedTemporaryFile
from sourmash.sbt_storage import ZipStorage
from sourmash.minhash import MinHash
RANDOM_SEQ_SIZE = 3000
RANDOM_SEQ_NUMBER = 300
MINHASH_NUM = 500
MINHASH_K = 21
GET_MINS_RANGE = 500
ADD_HASH_RANGE = 10_000
ADD_MANY_RANGE = 1000
SIMILARITY_TIMES = 500
COUNT_COMMON_TIMES = 500
MERGE_TIMES = 500
COPY_TIMES = 500
CONCAT_TIMES = 500
SET_ABUNDANCES_RANGE = 500
ZIP_STORAGE_WRITE = 100_000
ZIP_STORAGE_LOAD = 20
def load_sequences():
sequences = []
for i in range(10):
random_seq = random.sample(
"A,C,G,T".split(",") * RANDOM_SEQ_SIZE, RANDOM_SEQ_NUMBER
)
sequences.append("".join(random_seq))
return sequences
class TimeMinHashSuite:
def setup(self):
self.mh = MinHash(MINHASH_NUM, MINHASH_K, track_abundance=False)
self.protein_mh = MinHash(
MINHASH_NUM, MINHASH_K, is_protein=True, track_abundance=False
)
self.sequences = load_sequences()
self.populated_mh = MinHash(MINHASH_NUM, MINHASH_K, track_abundance=False)
for seq in self.sequences:
self.populated_mh.add_sequence(seq)
def time_add_sequence(self):
mh = self.mh
sequences = self.sequences
for seq in sequences:
mh.add_sequence(seq)
def time_add_protein(self):
mh = self.protein_mh
sequences = self.sequences
for seq in sequences:
mh.add_protein(seq)
def time_get_mins(self):
mh = self.populated_mh
for i in range(GET_MINS_RANGE):
mh.get_mins()
def time_add_hash(self):
mh = self.mh
for i in range(ADD_HASH_RANGE):
mh.add_hash(i)
def time_add_many(self):
mh = self.mh
mh.add_many(list(range(ADD_MANY_RANGE)))
def time_similarity(self):
mh = self.mh
other_mh = self.populated_mh
for i in range(SIMILARITY_TIMES):
mh.similarity(other_mh)
def time_count_common(self):
mh = self.mh
other_mh = self.populated_mh
for i in range(COUNT_COMMON_TIMES):
mh.count_common(other_mh)
def time_merge(self):
mh = self.mh
other_mh = self.populated_mh
for i in range(MERGE_TIMES):
mh.merge(other_mh)
def time_copy(self):
mh = self.populated_mh
for i in range(COPY_TIMES):
mh.__copy__()
def time_concat(self):
mh = self.mh
other_mh = self.populated_mh
for i in range(CONCAT_TIMES):
mh += other_mh
class PeakmemMinHashSuite:
def setup(self):
self.mh = MinHash(MINHASH_NUM, MINHASH_K, track_abundance=True)
self.protein_mh = MinHash(
MINHASH_NUM, MINHASH_K, is_protein=True, track_abundance=True
)
self.sequences = load_sequences()
def peakmem_add_sequence(self):
mh = self.mh
sequences = self.sequences
for seq in sequences:
mh.add_sequence(seq)
def peakmem_add_protein(self):
mh = self.protein_mh
sequences = self.sequences
for seq in sequences:
mh.add_protein(seq)
def peakmem_add_hash(self):
mh = self.mh
for i in range(ADD_HASH_RANGE):
mh.add_hash(i)
def peakmem_add_many(self):
mh = self.mh
mh.add_many(list(range(ADD_MANY_RANGE)))
####################
class TimeMinAbundanceSuite(TimeMinHashSuite):
def setup(self):
TimeMinHashSuite.setup(self)
self.mh = MinHash(MINHASH_NUM, MINHASH_K, track_abundance=True)
self.populated_mh = MinHash(MINHASH_NUM, MINHASH_K, track_abundance=True)
for seq in self.sequences:
self.populated_mh.add_sequence(seq)
def time_get_mins_abundance(self):
mh = self.populated_mh
for i in range(GET_MINS_RANGE):
mh.get_mins(with_abundance=True)
def time_set_abundances(self):
mh = self.mh
mins = self.populated_mh.get_mins(with_abundance=True)
for i in range(SET_ABUNDANCES_RANGE):
mh.set_abundances(mins)
def time_set_abundances_noclear(self):
mh = self.mh
mins = self.populated_mh.get_mins(with_abundance=True)
for i in range(SET_ABUNDANCES_RANGE):
mh.set_abundances(mins, clear=False)
class PeakmemMinAbundanceSuite(PeakmemMinHashSuite):
def setup(self):
PeakmemMinHashSuite.setup(self)
self.mh = MinHash(MINHASH_NUM, MINHASH_K, track_abundance=True)
####################
class TimeZipStorageSuite:
def setup(self):
import zipfile
self.zipfile = NamedTemporaryFile()
with zipfile.ZipFile(
self.zipfile, mode="w", compression=zipfile.ZIP_STORED
) as storage:
for i in range(ZIP_STORAGE_WRITE):
# just so we have lots of entries
storage.writestr(str(i), b"0")
# one big-ish entry
storage.writestr("sig1", b"9" * 1_000_000)
def time_load_from_zipstorage(self):
with ZipStorage(self.zipfile.name) as storage:
for i in range(ZIP_STORAGE_LOAD):
storage.load("sig1")
def time_load_small_from_zipstorage(self):
with ZipStorage(self.zipfile.name) as storage:
for i in range(ZIP_STORAGE_LOAD):
storage.load("99999")
def teardown(self):
self.zipfile.close()
class PeakmemZipStorageSuite:
def setup(self):
import zipfile
self.zipfile = NamedTemporaryFile()
with zipfile.ZipFile(
self.zipfile, mode="w", compression=zipfile.ZIP_STORED
) as storage:
for i in range(ZIP_STORAGE_WRITE):
# just so we have lots of entries
storage.writestr(str(i), b"0")
# one big-ish entry
storage.writestr("sig1", b"9" * 1_000_000)
def peakmem_load_from_zipstorage(self):
with ZipStorage(self.zipfile.name) as storage:
for i in range(ZIP_STORAGE_LOAD):
storage.load("sig1")
def peakmem_load_small_from_zipstorage(self):
with ZipStorage(self.zipfile.name) as storage:
for i in range(ZIP_STORAGE_LOAD):
storage.load("99999")
def teardown(self):
self.zipfile.close()
================================================
FILE: binder/README.md
================================================
# binder directory
Configuration files for [mybinder](https://mybinder.org).
================================================
FILE: binder/environment.yml
================================================
channels:
- conda-forge
- bioconda
- defaults
dependencies:
- python>=3.11
- sourmash>=4.8.11
- screed
- matplotlib
- pandas
- pip
- pip:
- matplotlib_venn
- mmh3
================================================
FILE: codecov.yml
================================================
# config file for codecov, https://app.codecov.io/gh/sourmash-bio/sourmash/
# use path fixing to properly report code coverage on source code
# per https://docs.codecov.io/docs/fixing-paths
fixes:
- "sourmash::src/sourmash"
ignores:
- "src/core/src/ffi"
codecov:
token: 66273971-681c-44a5-b93a-f60249a2a70c
================================================
FILE: codemeta.json
================================================
{
"@context": "https://raw.githubusercontent.com/mbjones/codemeta/master/codemeta.jsonld",
"@type": "Code",
"author": [
],
"identifier": "",
"codeRepository": "https://github.com/sourmash-bio/sourmash",
"datePublished": "2016-06-07",
"dateModified": "2016-06-07",
"dateCreated": "2016-06-07",
"description": "Generate, compare, and manipulate MinHash sketches of genomic data",
"keywords": "MinHash, k-mers, Python",
"license": "BSD 3-clause",
"title": "sourmash",
"version": "v1.0.0"
}
================================================
FILE: data/README.md
================================================
# The data subdir
Data files for various and sundry purposes.
The following files are used by the doctests in doc/ & may also be useful
for developers who are benchmarking:
```
GCF_000005845.2_ASM584v2_genomic.fna.gz
GCF_000006945.1_ASM694v1_genomic.fna.gz
GCF_000783305.1_ASM78330v1_genomic.fna.gz
```
CTB 6/16
================================================
FILE: default.nix
================================================
(import
(
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz";
sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2";
}
)
{
src = ./.;
}).defaultNix
================================================
FILE: deny.toml
================================================
all-features = true
feature-depth = 1
[advisories]
db-path = "~/.cargo/advisory-db"
db-urls = ["https://github.com/rustsec/advisory-db"]
vulnerability = "deny"
unmaintained = "warn"
yanked = "warn"
notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
#"RUSTSEC-0000-0000",
]
[licenses]
unlicensed = "deny"
allow = [
"MIT",
"Apache-2.0",
"Apache-2.0 WITH LLVM-exception",
"BSD-3-Clause",
"Unicode-DFS-2016",
]
copyleft = "warn"
allow-osi-fsf-free = "neither"
default = "deny"
confidence-threshold = 0.8
exceptions = [
{ allow = ["Zlib"], name = "piz", version = "*" },
{ allow = ["ISC"], name = "libloading", version = "*" },
]
[bans]
multiple-versions = "deny"
wildcards = "allow"
highlight = "all"
workspace-default-features = "allow"
external-default-features = "allow"
[sources]
unknown-registry = "warn"
unknown-git = "warn"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
================================================
FILE: dev.yml
================================================
name: sourmash_dev
channels:
- conda-forge
dependencies:
- clangdev >=16.0.6,<16.1
- cxx-compiler >=1.7.0,<1.8
- git 2.41.0.*
- libclang >=16.0.6,<16.1
- pandoc 3.1.3.*
- python 3.12.*
- rust >=1.85.0,<1.94
- tox >=4.11.0,<5
================================================
FILE: doc/Makefile
================================================
# Makefile for Sphinx documentation
#
all: html
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don\'t have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " epub3 to make an epub3"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
@echo " dummy to check syntax errors of document sources"
.PHONY: clean
clean:
rm -rf $(BUILDDIR)/*
.PHONY: html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
.PHONY: qthelp
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sourmash.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sourmash.qhc"
.PHONY: applehelp
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/sourmash"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sourmash"
@echo "# devhelp"
.PHONY: epub
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: epub3
epub3:
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
@echo
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
.PHONY: latex
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: latexpdfja
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
.PHONY: gettext
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
.PHONY: doctest
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
.PHONY: coverage
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
.PHONY: dummy
dummy:
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."
================================================
FILE: doc/README.md
================================================
# Documentation on the docs
We use
[MyST](https://myst-parser.readthedocs.io/en/latest/sphinx/intro.html)
to generate Sphinx doc output from Markdown input.
## Useful tips and tricks:
### Linking internally between sections in the docs
For linking within the sourmash docs, you should use the
[auto-generated header anchors](https://myst-parser.readthedocs.io/en/latest/syntax/optional.html#auto-generated-header-anchors)
provided by MyST.
You can generate a list of these for a given document with:
```
myst-anchors -l 3 command-line.md
```
================================================
FILE: doc/_static/custom.css
================================================
div.sphinxsidebar ul {
list-style-type: disc;
list-style: disc;
margin-left: 10px;
}
div.sphinxsidebar ul li.toctree-l1 > a {
font-size: 100%;
}
================================================
FILE: doc/_static/ecoli-cmp.Rmd
================================================
---
title: "Working with matrix output by sourmash compare"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
### Load a comparison matrix into R
```{r chunk1}
sourmash_comp_matrix <- read.csv("ecoli.cmp.csv")
# Label the rows
rownames(sourmash_comp_matrix) <- colnames(sourmash_comp_matrix)
# Transform for plotting
sourmash_comp_matrix <- as.matrix(sourmash_comp_matrix)
```
### Make an MDS plot
```{r mds}
fit <- dist(sourmash_comp_matrix)
fit <- cmdscale(fit)
x <- fit[, 1]
y <- fit[, 2]
plot(fit[ , 1], fit[ , 2], xlab = "Dimension 1", ylab = "Dimension 2")
```
### Make a tSNE plot
```{r tSNE}
library(Rtsne)
tsne_model <- Rtsne(sourmash_comp_matrix, check_duplicates=FALSE, pca=TRUE, perplexity=5, theta=0.5, dims=2)
d_tsne = as.data.frame(tsne_model$Y)
plot(d_tsne$V1, d_tsne$V2)
```
### Make an unclustered heatmap
```{r heatmap}
heatmap(sourmash_comp_matrix, Colv=F, scale='none')
```
### Make a clustered heatmap
```{r clustered-heatmap}
hc.rows <- hclust(dist(sourmash_comp_matrix))
hc.cols <- hclust(dist(t(sourmash_comp_matrix)))
heatmap(sourmash_comp_matrix[cutree(hc.rows,k=2)==1,], Colv=as.dendrogram(hc.cols), scale='none')
```
================================================
FILE: doc/_static/ecoli-cmp.html
================================================
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="pandoc" />
<title>Working with matrix output by sourmash compare</title>
<script src="data:application/x-javascript;base64,LyohIGpRdWVyeSB2MS4xMS4zIHwgKGMpIDIwMDUsIDIwMTUgalF1ZXJ5IEZvdW5kYXRpb24sIEluYy4gfCBqcXVlcnkub3JnL2xpY2Vuc2UgKi8KIWZ1bmN0aW9uKGEsYil7Im9iamVjdCI9PXR5cGVvZiBtb2R1bGUmJiJvYmplY3QiPT10eXBlb2YgbW9kdWxlLmV4cG9ydHM/bW9kdWxlLmV4cG9ydHM9YS5kb2N1bWVudD9iKGEsITApOmZ1bmN0aW9uKGEpe2lmKCFhLmRvY3VtZW50KXRocm93IG5ldyBFcnJvcigialF1ZXJ5IHJlcXVpcmVzIGEgd2luZG93IHdpdGggYSBkb2N1bWVudCIpO3JldHVybiBiKGEpfTpiKGEpfSgidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdz93aW5kb3c6dGhpcyxmdW5jdGlvbihhLGIpe3ZhciBjPVtdLGQ9Yy5zbGljZSxlPWMuY29uY2F0LGY9Yy5wdXNoLGc9Yy5pbmRleE9mLGg9e30saT1oLnRvU3RyaW5nLGo9aC5oYXNPd25Qcm9wZXJ0eSxrPXt9LGw9IjEuMTEuMyIsbT1mdW5jdGlvbihhLGIpe3JldHVybiBuZXcgbS5mbi5pbml0KGEsYil9LG49L15bXHNcdUZFRkZceEEwXSt8W1xzXHVGRUZGXHhBMF0rJC9nLG89L14tbXMtLyxwPS8tKFtcZGEtel0pL2dpLHE9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYi50b1VwcGVyQ2FzZSgpfTttLmZuPW0ucHJvdG90eXBlPXtqcXVlcnk6bCxjb25zdHJ1Y3RvcjptLHNlbGVjdG9yOiIiLGxlbmd0aDowLHRvQXJyYXk6ZnVuY3Rpb24oKXtyZXR1cm4gZC5jYWxsKHRoaXMpfSxnZXQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG51bGwhPWE/MD5hP3RoaXNbYSt0aGlzLmxlbmd0aF06dGhpc1thXTpkLmNhbGwodGhpcyl9LHB1c2hTdGFjazpmdW5jdGlvbihhKXt2YXIgYj1tLm1lcmdlKHRoaXMuY29uc3RydWN0b3IoKSxhKTtyZXR1cm4gYi5wcmV2T2JqZWN0PXRoaXMsYi5jb250ZXh0PXRoaXMuY29udGV4dCxifSxlYWNoOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG0uZWFjaCh0aGlzLGEsYil9LG1hcDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5wdXNoU3RhY2sobS5tYXAodGhpcyxmdW5jdGlvbihiLGMpe3JldHVybiBhLmNhbGwoYixjLGIpfSkpfSxzbGljZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLnB1c2hTdGFjayhkLmFwcGx5KHRoaXMsYXJndW1lbnRzKSl9LGZpcnN0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZXEoMCl9LGxhc3Q6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5lcSgtMSl9LGVxOmZ1bmN0aW9uKGEpe3ZhciBiPXRoaXMubGVuZ3RoLGM9K2ErKDA+YT9iOjApO3JldHVybiB0aGlzLnB1c2hTdGFjayhjPj0wJiZiPmM/W3RoaXNbY11dOltdKX0sZW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucHJldk9iamVjdHx8dGhpcy5jb25zdHJ1Y3RvcihudWxsKX0scHVzaDpmLHNvcnQ6Yy5zb3J0LHNwbGljZTpjLnNwbGljZX0sbS5leHRlbmQ9bS5mbi5leHRlbmQ9ZnVuY3Rpb24oKXt2YXIgYSxiLGMsZCxlLGYsZz1hcmd1bWVudHNbMF18fHt9LGg9MSxpPWFyZ3VtZW50cy5sZW5ndGgsaj0hMTtmb3IoImJvb2xlYW4iPT10eXBlb2YgZyYmKGo9ZyxnPWFyZ3VtZW50c1toXXx8e30saCsrKSwib2JqZWN0Ij09dHlwZW9mIGd8fG0uaXNGdW5jdGlvbihnKXx8KGc9e30pLGg9PT1pJiYoZz10aGlzLGgtLSk7aT5oO2grKylpZihudWxsIT0oZT1hcmd1bWVudHNbaF0pKWZvcihkIGluIGUpYT1nW2RdLGM9ZVtkXSxnIT09YyYmKGomJmMmJihtLmlzUGxhaW5PYmplY3QoYyl8fChiPW0uaXNBcnJheShjKSkpPyhiPyhiPSExLGY9YSYmbS5pc0FycmF5KGEpP2E6W10pOmY9YSYmbS5pc1BsYWluT2JqZWN0KGEpP2E6e30sZ1tkXT1tLmV4dGVuZChqLGYsYykpOnZvaWQgMCE9PWMmJihnW2RdPWMpKTtyZXR1cm4gZ30sbS5leHRlbmQoe2V4cGFuZG86ImpRdWVyeSIrKGwrTWF0aC5yYW5kb20oKSkucmVwbGFjZSgvXEQvZywiIiksaXNSZWFkeTohMCxlcnJvcjpmdW5jdGlvbihhKXt0aHJvdyBuZXcgRXJyb3IoYSl9LG5vb3A6ZnVuY3Rpb24oKXt9LGlzRnVuY3Rpb246ZnVuY3Rpb24oYSl7cmV0dXJuImZ1bmN0aW9uIj09PW0udHlwZShhKX0saXNBcnJheTpBcnJheS5pc0FycmF5fHxmdW5jdGlvbihhKXtyZXR1cm4iYXJyYXkiPT09bS50eXBlKGEpfSxpc1dpbmRvdzpmdW5jdGlvbihhKXtyZXR1cm4gbnVsbCE9YSYmYT09YS53aW5kb3d9LGlzTnVtZXJpYzpmdW5jdGlvbihhKXtyZXR1cm4hbS5pc0FycmF5KGEpJiZhLXBhcnNlRmxvYXQoYSkrMT49MH0saXNFbXB0eU9iamVjdDpmdW5jdGlvbihhKXt2YXIgYjtmb3IoYiBpbiBhKXJldHVybiExO3JldHVybiEwfSxpc1BsYWluT2JqZWN0OmZ1bmN0aW9uKGEpe3ZhciBiO2lmKCFhfHwib2JqZWN0IiE9PW0udHlwZShhKXx8YS5ub2RlVHlwZXx8bS5pc1dpbmRvdyhhKSlyZXR1cm4hMTt0cnl7aWYoYS5jb25zdHJ1Y3RvciYmIWouY2FsbChhLCJjb25zdHJ1Y3RvciIpJiYhai5jYWxsKGEuY29uc3RydWN0b3IucHJvdG90eXBlLCJpc1Byb3RvdHlwZU9mIikpcmV0dXJuITF9Y2F0Y2goYyl7cmV0dXJuITF9aWYoay5vd25MYXN0KWZvcihiIGluIGEpcmV0dXJuIGouY2FsbChhLGIpO2ZvcihiIGluIGEpO3JldHVybiB2b2lkIDA9PT1ifHxqLmNhbGwoYSxiKX0sdHlwZTpmdW5jdGlvbihhKXtyZXR1cm4gbnVsbD09YT9hKyIiOiJvYmplY3QiPT10eXBlb2YgYXx8ImZ1bmN0aW9uIj09dHlwZW9mIGE/aFtpLmNhbGwoYSldfHwib2JqZWN0Ijp0eXBlb2YgYX0sZ2xvYmFsRXZhbDpmdW5jdGlvbihiKXtiJiZtLnRyaW0oYikmJihhLmV4ZWNTY3JpcHR8fGZ1bmN0aW9uKGIpe2EuZXZhbC5jYWxsKGEsYil9KShiKX0sY2FtZWxDYXNlOmZ1bmN0aW9uKGEpe3JldHVybiBhLnJlcGxhY2UobywibXMtIikucmVwbGFjZShwLHEpfSxub2RlTmFtZTpmdW5jdGlvbihhLGIpe3JldHVybiBhLm5vZGVOYW1lJiZhLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT1iLnRvTG93ZXJDYXNlKCl9LGVhY2g6ZnVuY3Rpb24oYSxiLGMpe3ZhciBkLGU9MCxmPWEubGVuZ3RoLGc9cihhKTtpZihjKXtpZihnKXtmb3IoO2Y+ZTtlKyspaWYoZD1iLmFwcGx5KGFbZV0sYyksZD09PSExKWJyZWFrfWVsc2UgZm9yKGUgaW4gYSlpZihkPWIuYXBwbHkoYVtlXSxjKSxkPT09ITEpYnJlYWt9ZWxzZSBpZihnKXtmb3IoO2Y+ZTtlKyspaWYoZD1iLmNhbGwoYVtlXSxlLGFbZV0pLGQ9PT0hMSlicmVha31lbHNlIGZvcihlIGluIGEpaWYoZD1iLmNhbGwoYVtlXSxlLGFbZV0pLGQ9PT0hMSlicmVhaztyZXR1cm4gYX0sdHJpbTpmdW5jdGlvbihhKXtyZXR1cm4gbnVsbD09YT8iIjooYSsiIikucmVwbGFjZShuLCIiKX0sbWFrZUFycmF5OmZ1bmN0aW9uKGEsYil7dmFyIGM9Ynx8W107cmV0dXJuIG51bGwhPWEmJihyKE9iamVjdChhKSk/bS5tZXJnZShjLCJzdHJpbmciPT10eXBlb2YgYT9bYV06YSk6Zi5jYWxsKGMsYSkpLGN9LGluQXJyYXk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBkO2lmKGIpe2lmKGcpcmV0dXJuIGcuY2FsbChiLGEsYyk7Zm9yKGQ9Yi5sZW5ndGgsYz1jPzA+Yz9NYXRoLm1heCgwLGQrYyk6YzowO2Q+YztjKyspaWYoYyBpbiBiJiZiW2NdPT09YSlyZXR1cm4gY31yZXR1cm4tMX0sbWVyZ2U6ZnVuY3Rpb24oYSxiKXt2YXIgYz0rYi5sZW5ndGgsZD0wLGU9YS5sZW5ndGg7d2hpbGUoYz5kKWFbZSsrXT1iW2QrK107aWYoYyE9PWMpd2hpbGUodm9pZCAwIT09YltkXSlhW2UrK109YltkKytdO3JldHVybiBhLmxlbmd0aD1lLGF9LGdyZXA6ZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZCxlPVtdLGY9MCxnPWEubGVuZ3RoLGg9IWM7Zz5mO2YrKylkPSFiKGFbZl0sZiksZCE9PWgmJmUucHVzaChhW2ZdKTtyZXR1cm4gZX0sbWFwOmZ1bmN0aW9uKGEsYixjKXt2YXIgZCxmPTAsZz1hLmxlbmd0aCxoPXIoYSksaT1bXTtpZihoKWZvcig7Zz5mO2YrKylkPWIoYVtmXSxmLGMpLG51bGwhPWQmJmkucHVzaChkKTtlbHNlIGZvcihmIGluIGEpZD1iKGFbZl0sZixjKSxudWxsIT1kJiZpLnB1c2goZCk7cmV0dXJuIGUuYXBwbHkoW10saSl9LGd1aWQ6MSxwcm94eTpmdW5jdGlvbihhLGIpe3ZhciBjLGUsZjtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIGImJihmPWFbYl0sYj1hLGE9ZiksbS5pc0Z1bmN0aW9uKGEpPyhjPWQuY2FsbChhcmd1bWVudHMsMiksZT1mdW5jdGlvbigpe3JldHVybiBhLmFwcGx5KGJ8fHRoaXMsYy5jb25jYXQoZC5jYWxsKGFyZ3VtZW50cykpKX0sZS5ndWlkPWEuZ3VpZD1hLmd1aWR8fG0uZ3VpZCsrLGUpOnZvaWQgMH0sbm93OmZ1bmN0aW9uKCl7cmV0dXJuK25ldyBEYXRlfSxzdXBwb3J0Omt9KSxtLmVhY2goIkJvb2xlYW4gTnVtYmVyIFN0cmluZyBGdW5jdGlvbiBBcnJheSBEYXRlIFJlZ0V4cCBPYmplY3QgRXJyb3IiLnNwbGl0KCIgIiksZnVuY3Rpb24oYSxiKXtoWyJbb2JqZWN0ICIrYisiXSJdPWIudG9Mb3dlckNhc2UoKX0pO2Z1bmN0aW9uIHIoYSl7dmFyIGI9Imxlbmd0aCJpbiBhJiZhLmxlbmd0aCxjPW0udHlwZShhKTtyZXR1cm4iZnVuY3Rpb24iPT09Y3x8bS5pc1dpbmRvdyhhKT8hMToxPT09YS5ub2RlVHlwZSYmYj8hMDoiYXJyYXkiPT09Y3x8MD09PWJ8fCJudW1iZXIiPT10eXBlb2YgYiYmYj4wJiZiLTEgaW4gYX12YXIgcz1mdW5jdGlvbihhKXt2YXIgYixjLGQsZSxmLGcsaCxpLGosayxsLG0sbixvLHAscSxyLHMsdCx1PSJzaXp6bGUiKzEqbmV3IERhdGUsdj1hLmRvY3VtZW50LHc9MCx4PTAseT1oYSgpLHo9aGEoKSxBPWhhKCksQj1mdW5jdGlvbihhLGIpe3JldHVybiBhPT09YiYmKGw9ITApLDB9LEM9MTw8MzEsRD17fS5oYXNPd25Qcm9wZXJ0eSxFPVtdLEY9RS5wb3AsRz1FLnB1c2gsSD1FLnB1c2gsST1FLnNsaWNlLEo9ZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9MCxkPWEubGVuZ3RoO2Q+YztjKyspaWYoYVtjXT09PWIpcmV0dXJuIGM7cmV0dXJuLTF9LEs9ImNoZWNrZWR8c2VsZWN0ZWR8YXN5bmN8YXV0b2ZvY3VzfGF1dG9wbGF5fGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxpc21hcHxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkIixMPSJbXFx4MjBcXHRcXHJcXG5cXGZdIixNPSIoPzpcXFxcLnxbXFx3LV18W15cXHgwMC1cXHhhMF0pKyIsTj1NLnJlcGxhY2UoInciLCJ3IyIpLE89IlxcWyIrTCsiKigiK00rIikoPzoiK0wrIiooWypeJHwhfl0/PSkiK0wrIiooPzonKCg/OlxcXFwufFteXFxcXCddKSopJ3xcIigoPzpcXFxcLnxbXlxcXFxcIl0pKilcInwoIitOKyIpKXwpIitMKyIqXFxdIixQPSI6KCIrTSsiKSg/OlxcKCgoJygoPzpcXFxcLnxbXlxcXFwnXSkqKSd8XCIoKD86XFxcXC58W15cXFxcXCJdKSopXCIpfCgoPzpcXFxcLnxbXlxcXFwoKVtcXF1dfCIrTysiKSopfC4qKVxcKXwpIixRPW5ldyBSZWdFeHAoTCsiKyIsImciKSxSPW5ldyBSZWdFeHAoIl4iK0wrIit8KCg/Ol58W15cXFxcXSkoPzpcXFxcLikqKSIrTCsiKyQiLCJnIiksUz1uZXcgUmVnRXhwKCJeIitMKyIqLCIrTCsiKiIpLFQ9bmV3IFJlZ0V4cCgiXiIrTCsiKihbPit+XXwiK0wrIikiK0wrIioiKSxVPW5ldyBSZWdFeHAoIj0iK0wrIiooW15cXF0nXCJdKj8pIitMKyIqXFxdIiwiZyIpLFY9bmV3IFJlZ0V4cChQKSxXPW5ldyBSZWdFeHAoIl4iK04rIiQiKSxYPXtJRDpuZXcgUmVnRXhwKCJeIygiK00rIikiKSxDTEFTUzpuZXcgUmVnRXhwKCJeXFwuKCIrTSsiKSIpLFRBRzpuZXcgUmVnRXhwKCJeKCIrTS5yZXBsYWNlKCJ3IiwidyoiKSsiKSIpLEFUVFI6bmV3IFJlZ0V4cCgiXiIrTyksUFNFVURPOm5ldyBSZWdFeHAoIl4iK1ApLENISUxEOm5ldyBSZWdFeHAoIl46KG9ubHl8Zmlyc3R8bGFzdHxudGh8bnRoLWxhc3QpLShjaGlsZHxvZi10eXBlKSg/OlxcKCIrTCsiKihldmVufG9kZHwoKFsrLV18KShcXGQqKW58KSIrTCsiKig/OihbKy1dfCkiK0wrIiooXFxkKyl8KSkiK0wrIipcXCl8KSIsImkiKSxib29sOm5ldyBSZWdFeHAoIl4oPzoiK0srIikkIiwiaSIpLG5lZWRzQ29udGV4dDpuZXcgUmVnRXhwKCJeIitMKyIqWz4rfl18OihldmVufG9kZHxlcXxndHxsdHxudGh8Zmlyc3R8bGFzdCkoPzpcXCgiK0wrIiooKD86LVxcZCk/XFxkKikiK0wrIipcXCl8KSg/PVteLV18JCkiLCJpIil9LFk9L14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSxaPS9eaFxkJC9pLCQ9L15bXntdK1x7XHMqXFtuYXRpdmUgXHcvLF89L14oPzojKFtcdy1dKyl8KFx3Kyl8XC4oW1x3LV0rKSkkLyxhYT0vWyt+XS8sYmE9Lyd8XFwvZyxjYT1uZXcgUmVnRXhwKCJcXFxcKFtcXGRhLWZdezEsNn0iK0wrIj98KCIrTCsiKXwuKSIsImlnIiksZGE9ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPSIweCIrYi02NTUzNjtyZXR1cm4gZCE9PWR8fGM/YjowPmQ/U3RyaW5nLmZyb21DaGFyQ29kZShkKzY1NTM2KTpTdHJpbmcuZnJvbUNoYXJDb2RlKGQ+PjEwfDU1Mjk2LDEwMjMmZHw1NjMyMCl9LGVhPWZ1bmN0aW9uKCl7bSgpfTt0cnl7SC5hcHBseShFPUkuY2FsbCh2LmNoaWxkTm9kZXMpLHYuY2hpbGROb2RlcyksRVt2LmNoaWxkTm9kZXMubGVuZ3RoXS5ub2RlVHlwZX1jYXRjaChmYSl7SD17YXBwbHk6RS5sZW5ndGg/ZnVuY3Rpb24oYSxiKXtHLmFwcGx5KGEsSS5jYWxsKGIpKX06ZnVuY3Rpb24oYSxiKXt2YXIgYz1hLmxlbmd0aCxkPTA7d2hpbGUoYVtjKytdPWJbZCsrXSk7YS5sZW5ndGg9Yy0xfX19ZnVuY3Rpb24gZ2EoYSxiLGQsZSl7dmFyIGYsaCxqLGssbCxvLHIscyx3LHg7aWYoKGI/Yi5vd25lckRvY3VtZW50fHxiOnYpIT09biYmbShiKSxiPWJ8fG4sZD1kfHxbXSxrPWIubm9kZVR5cGUsInN0cmluZyIhPXR5cGVvZiBhfHwhYXx8MSE9PWsmJjkhPT1rJiYxMSE9PWspcmV0dXJuIGQ7aWYoIWUmJnApe2lmKDExIT09ayYmKGY9Xy5leGVjKGEpKSlpZihqPWZbMV0pe2lmKDk9PT1rKXtpZihoPWIuZ2V0RWxlbWVudEJ5SWQoaiksIWh8fCFoLnBhcmVudE5vZGUpcmV0dXJuIGQ7aWYoaC5pZD09PWopcmV0dXJuIGQucHVzaChoKSxkfWVsc2UgaWYoYi5vd25lckRvY3VtZW50JiYoaD1iLm93bmVyRG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaikpJiZ0KGIsaCkmJmguaWQ9PT1qKXJldHVybiBkLnB1c2goaCksZH1lbHNle2lmKGZbMl0pcmV0dXJuIEguYXBwbHkoZCxiLmdldEVsZW1lbnRzQnlUYWdOYW1lKGEpKSxkO2lmKChqPWZbM10pJiZjLmdldEVsZW1lbnRzQnlDbGFzc05hbWUpcmV0dXJuIEguYXBwbHkoZCxiLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoaikpLGR9aWYoYy5xc2EmJighcXx8IXEudGVzdChhKSkpe2lmKHM9cj11LHc9Yix4PTEhPT1rJiZhLDE9PT1rJiYib2JqZWN0IiE9PWIubm9kZU5hbWUudG9Mb3dlckNhc2UoKSl7bz1nKGEpLChyPWIuZ2V0QXR0cmlidXRlKCJpZCIpKT9zPXIucmVwbGFjZShiYSwiXFwkJiIpOmIuc2V0QXR0cmlidXRlKCJpZCIscykscz0iW2lkPSciK3MrIiddICIsbD1vLmxlbmd0aDt3aGlsZShsLS0pb1tsXT1zK3JhKG9bbF0pO3c9YWEudGVzdChhKSYmcGEoYi5wYXJlbnROb2RlKXx8Yix4PW8uam9pbigiLCIpfWlmKHgpdHJ5e3JldHVybiBILmFwcGx5KGQsdy5xdWVyeVNlbGVjdG9yQWxsKHgpKSxkfWNhdGNoKHkpe31maW5hbGx5e3J8fGIucmVtb3ZlQXR0cmlidXRlKCJpZCIpfX19cmV0dXJuIGkoYS5yZXBsYWNlKFIsIiQxIiksYixkLGUpfWZ1bmN0aW9uIGhhKCl7dmFyIGE9W107ZnVuY3Rpb24gYihjLGUpe3JldHVybiBhLnB1c2goYysiICIpPmQuY2FjaGVMZW5ndGgmJmRlbGV0ZSBiW2Euc2hpZnQoKV0sYltjKyIgIl09ZX1yZXR1cm4gYn1mdW5jdGlvbiBpYShhKXtyZXR1cm4gYVt1XT0hMCxhfWZ1bmN0aW9uIGphKGEpe3ZhciBiPW4uY3JlYXRlRWxlbWVudCgiZGl2Iik7dHJ5e3JldHVybiEhYShiKX1jYXRjaChjKXtyZXR1cm4hMX1maW5hbGx5e2IucGFyZW50Tm9kZSYmYi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGIpLGI9bnVsbH19ZnVuY3Rpb24ga2EoYSxiKXt2YXIgYz1hLnNwbGl0KCJ8IiksZT1hLmxlbmd0aDt3aGlsZShlLS0pZC5hdHRySGFuZGxlW2NbZV1dPWJ9ZnVuY3Rpb24gbGEoYSxiKXt2YXIgYz1iJiZhLGQ9YyYmMT09PWEubm9kZVR5cGUmJjE9PT1iLm5vZGVUeXBlJiYofmIuc291cmNlSW5kZXh8fEMpLSh+YS5zb3VyY2VJbmRleHx8Qyk7aWYoZClyZXR1cm4gZDtpZihjKXdoaWxlKGM9Yy5uZXh0U2libGluZylpZihjPT09YilyZXR1cm4tMTtyZXR1cm4gYT8xOi0xfWZ1bmN0aW9uIG1hKGEpe3JldHVybiBmdW5jdGlvbihiKXt2YXIgYz1iLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7cmV0dXJuImlucHV0Ij09PWMmJmIudHlwZT09PWF9fWZ1bmN0aW9uIG5hKGEpe3JldHVybiBmdW5jdGlvbihiKXt2YXIgYz1iLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7cmV0dXJuKCJpbnB1dCI9PT1jfHwiYnV0dG9uIj09PWMpJiZiLnR5cGU9PT1hfX1mdW5jdGlvbiBvYShhKXtyZXR1cm4gaWEoZnVuY3Rpb24oYil7cmV0dXJuIGI9K2IsaWEoZnVuY3Rpb24oYyxkKXt2YXIgZSxmPWEoW10sYy5sZW5ndGgsYiksZz1mLmxlbmd0aDt3aGlsZShnLS0pY1tlPWZbZ11dJiYoY1tlXT0hKGRbZV09Y1tlXSkpfSl9KX1mdW5jdGlvbiBwYShhKXtyZXR1cm4gYSYmInVuZGVmaW5lZCIhPXR5cGVvZiBhLmdldEVsZW1lbnRzQnlUYWdOYW1lJiZhfWM9Z2Euc3VwcG9ydD17fSxmPWdhLmlzWE1MPWZ1bmN0aW9uKGEpe3ZhciBiPWEmJihhLm93bmVyRG9jdW1lbnR8fGEpLmRvY3VtZW50RWxlbWVudDtyZXR1cm4gYj8iSFRNTCIhPT1iLm5vZGVOYW1lOiExfSxtPWdhLnNldERvY3VtZW50PWZ1bmN0aW9uKGEpe3ZhciBiLGUsZz1hP2Eub3duZXJEb2N1bWVudHx8YTp2O3JldHVybiBnIT09biYmOT09PWcubm9kZVR5cGUmJmcuZG9jdW1lbnRFbGVtZW50PyhuPWcsbz1nLmRvY3VtZW50RWxlbWVudCxlPWcuZGVmYXVsdFZpZXcsZSYmZSE9PWUudG9wJiYoZS5hZGRFdmVudExpc3RlbmVyP2UuYWRkRXZlbnRMaXN0ZW5lcigidW5sb2FkIixlYSwhMSk6ZS5hdHRhY2hFdmVudCYmZS5hdHRhY2hFdmVudCgib251bmxvYWQiLGVhKSkscD0hZihnKSxjLmF0dHJpYnV0ZXM9amEoZnVuY3Rpb24oYSl7cmV0dXJuIGEuY2xhc3NOYW1lPSJpIiwhYS5nZXRBdHRyaWJ1dGUoImNsYXNzTmFtZSIpfSksYy5nZXRFbGVtZW50c0J5VGFnTmFtZT1qYShmdW5jdGlvbihhKXtyZXR1cm4gYS5hcHBlbmRDaGlsZChnLmNyZWF0ZUNvbW1lbnQoIiIpKSwhYS5nZXRFbGVtZW50c0J5VGFnTmFtZSgiKiIpLmxlbmd0aH0pLGMuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZT0kLnRlc3QoZy5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKSxjLmdldEJ5SWQ9amEoZnVuY3Rpb24oYSl7cmV0dXJuIG8uYXBwZW5kQ2hpbGQoYSkuaWQ9dSwhZy5nZXRFbGVtZW50c0J5TmFtZXx8IWcuZ2V0RWxlbWVudHNCeU5hbWUodSkubGVuZ3RofSksYy5nZXRCeUlkPyhkLmZpbmQuSUQ9ZnVuY3Rpb24oYSxiKXtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGIuZ2V0RWxlbWVudEJ5SWQmJnApe3ZhciBjPWIuZ2V0RWxlbWVudEJ5SWQoYSk7cmV0dXJuIGMmJmMucGFyZW50Tm9kZT9bY106W119fSxkLmZpbHRlci5JRD1mdW5jdGlvbihhKXt2YXIgYj1hLnJlcGxhY2UoY2EsZGEpO3JldHVybiBmdW5jdGlvbihhKXtyZXR1cm4gYS5nZXRBdHRyaWJ1dGUoImlkIik9PT1ifX0pOihkZWxldGUgZC5maW5kLklELGQuZmlsdGVyLklEPWZ1bmN0aW9uKGEpe3ZhciBiPWEucmVwbGFjZShjYSxkYSk7cmV0dXJuIGZ1bmN0aW9uKGEpe3ZhciBjPSJ1bmRlZmluZWQiIT10eXBlb2YgYS5nZXRBdHRyaWJ1dGVOb2RlJiZhLmdldEF0dHJpYnV0ZU5vZGUoImlkIik7cmV0dXJuIGMmJmMudmFsdWU9PT1ifX0pLGQuZmluZC5UQUc9Yy5nZXRFbGVtZW50c0J5VGFnTmFtZT9mdW5jdGlvbihhLGIpe3JldHVybiJ1bmRlZmluZWQiIT10eXBlb2YgYi5nZXRFbGVtZW50c0J5VGFnTmFtZT9iLmdldEVsZW1lbnRzQnlUYWdOYW1lKGEpOmMucXNhP2IucXVlcnlTZWxlY3RvckFsbChhKTp2b2lkIDB9OmZ1bmN0aW9uKGEsYil7dmFyIGMsZD1bXSxlPTAsZj1iLmdldEVsZW1lbnRzQnlUYWdOYW1lKGEpO2lmKCIqIj09PWEpe3doaWxlKGM9ZltlKytdKTE9PT1jLm5vZGVUeXBlJiZkLnB1c2goYyk7cmV0dXJuIGR9cmV0dXJuIGZ9LGQuZmluZC5DTEFTUz1jLmdldEVsZW1lbnRzQnlDbGFzc05hbWUmJmZ1bmN0aW9uKGEsYil7cmV0dXJuIHA/Yi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGEpOnZvaWQgMH0scj1bXSxxPVtdLChjLnFzYT0kLnRlc3QoZy5xdWVyeVNlbGVjdG9yQWxsKSkmJihqYShmdW5jdGlvbihhKXtvLmFwcGVuZENoaWxkKGEpLmlubmVySFRNTD0iPGEgaWQ9JyIrdSsiJz48L2E+PHNlbGVjdCBpZD0nIit1KyItXGZdJyBtc2FsbG93Y2FwdHVyZT0nJz48b3B0aW9uIHNlbGVjdGVkPScnPjwvb3B0aW9uPjwvc2VsZWN0PiIsYS5xdWVyeVNlbGVjdG9yQWxsKCJbbXNhbGxvd2NhcHR1cmVePScnXSIpLmxlbmd0aCYmcS5wdXNoKCJbKl4kXT0iK0wrIiooPzonJ3xcIlwiKSIpLGEucXVlcnlTZWxlY3RvckFsbCgiW3NlbGVjdGVkXSIpLmxlbmd0aHx8cS5wdXNoKCJcXFsiK0wrIiooPzp2YWx1ZXwiK0srIikiKSxhLnF1ZXJ5U2VsZWN0b3JBbGwoIltpZH49Iit1KyItXSIpLmxlbmd0aHx8cS5wdXNoKCJ+PSIpLGEucXVlcnlTZWxlY3RvckFsbCgiOmNoZWNrZWQiKS5sZW5ndGh8fHEucHVzaCgiOmNoZWNrZWQiKSxhLnF1ZXJ5U2VsZWN0b3JBbGwoImEjIit1KyIrKiIpLmxlbmd0aHx8cS5wdXNoKCIuIy4rWyt+XSIpfSksamEoZnVuY3Rpb24oYSl7dmFyIGI9Zy5jcmVhdGVFbGVtZW50KCJpbnB1dCIpO2Iuc2V0QXR0cmlidXRlKCJ0eXBlIiwiaGlkZGVuIiksYS5hcHBlbmRDaGlsZChiKS5zZXRBdHRyaWJ1dGUoIm5hbWUiLCJEIiksYS5xdWVyeVNlbGVjdG9yQWxsKCJbbmFtZT1kXSIpLmxlbmd0aCYmcS5wdXNoKCJuYW1lIitMKyIqWypeJHwhfl0/PSIpLGEucXVlcnlTZWxlY3RvckFsbCgiOmVuYWJsZWQiKS5sZW5ndGh8fHEucHVzaCgiOmVuYWJsZWQiLCI6ZGlzYWJsZWQiKSxhLnF1ZXJ5U2VsZWN0b3JBbGwoIiosOngiKSxxLnB1c2goIiwuKjoiKX0pKSwoYy5tYXRjaGVzU2VsZWN0b3I9JC50ZXN0KHM9by5tYXRjaGVzfHxvLndlYmtpdE1hdGNoZXNTZWxlY3Rvcnx8by5tb3pNYXRjaGVzU2VsZWN0b3J8fG8ub01hdGNoZXNTZWxlY3Rvcnx8by5tc01hdGNoZXNTZWxlY3RvcikpJiZqYShmdW5jdGlvbihhKXtjLmRpc2Nvbm5lY3RlZE1hdGNoPXMuY2FsbChhLCJkaXYiKSxzLmNhbGwoYSwiW3MhPScnXTp4Iiksci5wdXNoKCIhPSIsUCl9KSxxPXEubGVuZ3RoJiZuZXcgUmVnRXhwKHEuam9pbigifCIpKSxyPXIubGVuZ3RoJiZuZXcgUmVnRXhwKHIuam9pbigifCIpKSxiPSQudGVzdChvLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKSx0PWJ8fCQudGVzdChvLmNvbnRhaW5zKT9mdW5jdGlvbihhLGIpe3ZhciBjPTk9PT1hLm5vZGVUeXBlP2EuZG9jdW1lbnRFbGVtZW50OmEsZD1iJiZiLnBhcmVudE5vZGU7cmV0dXJuIGE9PT1kfHwhKCFkfHwxIT09ZC5ub2RlVHlwZXx8IShjLmNvbnRhaW5zP2MuY29udGFpbnMoZCk6YS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiYmMTYmYS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihkKSkpfTpmdW5jdGlvbihhLGIpe2lmKGIpd2hpbGUoYj1iLnBhcmVudE5vZGUpaWYoYj09PWEpcmV0dXJuITA7cmV0dXJuITF9LEI9Yj9mdW5jdGlvbihhLGIpe2lmKGE9PT1iKXJldHVybiBsPSEwLDA7dmFyIGQ9IWEuY29tcGFyZURvY3VtZW50UG9zaXRpb24tIWIuY29tcGFyZURvY3VtZW50UG9zaXRpb247cmV0dXJuIGQ/ZDooZD0oYS5vd25lckRvY3VtZW50fHxhKT09PShiLm93bmVyRG9jdW1lbnR8fGIpP2EuY29tcGFyZURvY3VtZW50UG9zaXRpb24oYik6MSwxJmR8fCFjLnNvcnREZXRhY2hlZCYmYi5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihhKT09PWQ/YT09PWd8fGEub3duZXJEb2N1bWVudD09PXYmJnQodixhKT8tMTpiPT09Z3x8Yi5vd25lckRvY3VtZW50PT09diYmdCh2LGIpPzE6az9KKGssYSktSihrLGIpOjA6NCZkPy0xOjEpfTpmdW5jdGlvbihhLGIpe2lmKGE9PT1iKXJldHVybiBsPSEwLDA7dmFyIGMsZD0wLGU9YS5wYXJlbnROb2RlLGY9Yi5wYXJlbnROb2RlLGg9W2FdLGk9W2JdO2lmKCFlfHwhZilyZXR1cm4gYT09PWc/LTE6Yj09PWc/MTplPy0xOmY/MTprP0ooayxhKS1KKGssYik6MDtpZihlPT09ZilyZXR1cm4gbGEoYSxiKTtjPWE7d2hpbGUoYz1jLnBhcmVudE5vZGUpaC51bnNoaWZ0KGMpO2M9Yjt3aGlsZShjPWMucGFyZW50Tm9kZSlpLnVuc2hpZnQoYyk7d2hpbGUoaFtkXT09PWlbZF0pZCsrO3JldHVybiBkP2xhKGhbZF0saVtkXSk6aFtkXT09PXY/LTE6aVtkXT09PXY/MTowfSxnKTpufSxnYS5tYXRjaGVzPWZ1bmN0aW9uKGEsYil7cmV0dXJuIGdhKGEsbnVsbCxudWxsLGIpfSxnYS5tYXRjaGVzU2VsZWN0b3I9ZnVuY3Rpb24oYSxiKXtpZigoYS5vd25lckRvY3VtZW50fHxhKSE9PW4mJm0oYSksYj1iLnJlcGxhY2UoVSwiPSckMSddIiksISghYy5tYXRjaGVzU2VsZWN0b3J8fCFwfHxyJiZyLnRlc3QoYil8fHEmJnEudGVzdChiKSkpdHJ5e3ZhciBkPXMuY2FsbChhLGIpO2lmKGR8fGMuZGlzY29ubmVjdGVkTWF0Y2h8fGEuZG9jdW1lbnQmJjExIT09YS5kb2N1bWVudC5ub2RlVHlwZSlyZXR1cm4gZH1jYXRjaChlKXt9cmV0dXJuIGdhKGIsbixudWxsLFthXSkubGVuZ3RoPjB9LGdhLmNvbnRhaW5zPWZ1bmN0aW9uKGEsYil7cmV0dXJuKGEub3duZXJEb2N1bWVudHx8YSkhPT1uJiZtKGEpLHQoYSxiKX0sZ2EuYXR0cj1mdW5jdGlvbihhLGIpeyhhLm93bmVyRG9jdW1lbnR8fGEpIT09biYmbShhKTt2YXIgZT1kLmF0dHJIYW5kbGVbYi50b0xvd2VyQ2FzZSgpXSxmPWUmJkQuY2FsbChkLmF0dHJIYW5kbGUsYi50b0xvd2VyQ2FzZSgpKT9lKGEsYiwhcCk6dm9pZCAwO3JldHVybiB2b2lkIDAhPT1mP2Y6Yy5hdHRyaWJ1dGVzfHwhcD9hLmdldEF0dHJpYnV0ZShiKTooZj1hLmdldEF0dHJpYnV0ZU5vZGUoYikpJiZmLnNwZWNpZmllZD9mLnZhbHVlOm51bGx9LGdhLmVycm9yPWZ1bmN0aW9uKGEpe3Rocm93IG5ldyBFcnJvcigiU3ludGF4IGVycm9yLCB1bnJlY29nbml6ZWQgZXhwcmVzc2lvbjogIithKX0sZ2EudW5pcXVlU29ydD1mdW5jdGlvbihhKXt2YXIgYixkPVtdLGU9MCxmPTA7aWYobD0hYy5kZXRlY3REdXBsaWNhdGVzLGs9IWMuc29ydFN0YWJsZSYmYS5zbGljZSgwKSxhLnNvcnQoQiksbCl7d2hpbGUoYj1hW2YrK10pYj09PWFbZl0mJihlPWQucHVzaChmKSk7d2hpbGUoZS0tKWEuc3BsaWNlKGRbZV0sMSl9cmV0dXJuIGs9bnVsbCxhfSxlPWdhLmdldFRleHQ9ZnVuY3Rpb24oYSl7dmFyIGIsYz0iIixkPTAsZj1hLm5vZGVUeXBlO2lmKGYpe2lmKDE9PT1mfHw5PT09Znx8MTE9PT1mKXtpZigic3RyaW5nIj09dHlwZW9mIGEudGV4dENvbnRlbnQpcmV0dXJuIGEudGV4dENvbnRlbnQ7Zm9yKGE9YS5maXJzdENoaWxkO2E7YT1hLm5leHRTaWJsaW5nKWMrPWUoYSl9ZWxzZSBpZigzPT09Znx8ND09PWYpcmV0dXJuIGEubm9kZVZhbHVlfWVsc2Ugd2hpbGUoYj1hW2QrK10pYys9ZShiKTtyZXR1cm4gY30sZD1nYS5zZWxlY3RvcnM9e2NhY2hlTGVuZ3RoOjUwLGNyZWF0ZVBzZXVkbzppYSxtYXRjaDpYLGF0dHJIYW5kbGU6e30sZmluZDp7fSxyZWxhdGl2ZTp7Ij4iOntkaXI6InBhcmVudE5vZGUiLGZpcnN0OiEwfSwiICI6e2RpcjoicGFyZW50Tm9kZSJ9LCIrIjp7ZGlyOiJwcmV2aW91c1NpYmxpbmciLGZpcnN0OiEwfSwifiI6e2RpcjoicHJldmlvdXNTaWJsaW5nIn19LHByZUZpbHRlcjp7QVRUUjpmdW5jdGlvbihhKXtyZXR1cm4gYVsxXT1hWzFdLnJlcGxhY2UoY2EsZGEpLGFbM109KGFbM118fGFbNF18fGFbNV18fCIiKS5yZXBsYWNlKGNhLGRhKSwifj0iPT09YVsyXSYmKGFbM109IiAiK2FbM10rIiAiKSxhLnNsaWNlKDAsNCl9LENISUxEOmZ1bmN0aW9uKGEpe3JldHVybiBhWzFdPWFbMV0udG9Mb3dlckNhc2UoKSwibnRoIj09PWFbMV0uc2xpY2UoMCwzKT8oYVszXXx8Z2EuZXJyb3IoYVswXSksYVs0XT0rKGFbNF0/YVs1XSsoYVs2XXx8MSk6MiooImV2ZW4iPT09YVszXXx8Im9kZCI9PT1hWzNdKSksYVs1XT0rKGFbN10rYVs4XXx8Im9kZCI9PT1hWzNdKSk6YVszXSYmZ2EuZXJyb3IoYVswXSksYX0sUFNFVURPOmZ1bmN0aW9uKGEpe3ZhciBiLGM9IWFbNl0mJmFbMl07cmV0dXJuIFguQ0hJTEQudGVzdChhWzBdKT9udWxsOihhWzNdP2FbMl09YVs0XXx8YVs1XXx8IiI6YyYmVi50ZXN0KGMpJiYoYj1nKGMsITApKSYmKGI9Yy5pbmRleE9mKCIpIixjLmxlbmd0aC1iKS1jLmxlbmd0aCkmJihhWzBdPWFbMF0uc2xpY2UoMCxiKSxhWzJdPWMuc2xpY2UoMCxiKSksYS5zbGljZSgwLDMpKX19LGZpbHRlcjp7VEFHOmZ1bmN0aW9uKGEpe3ZhciBiPWEucmVwbGFjZShjYSxkYSkudG9Mb3dlckNhc2UoKTtyZXR1cm4iKiI9PT1hP2Z1bmN0aW9uKCl7cmV0dXJuITB9OmZ1bmN0aW9uKGEpe3JldHVybiBhLm5vZGVOYW1lJiZhLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT1ifX0sQ0xBU1M6ZnVuY3Rpb24oYSl7dmFyIGI9eVthKyIgIl07cmV0dXJuIGJ8fChiPW5ldyBSZWdFeHAoIihefCIrTCsiKSIrYSsiKCIrTCsifCQpIikpJiZ5KGEsZnVuY3Rpb24oYSl7cmV0dXJuIGIudGVzdCgic3RyaW5nIj09dHlwZW9mIGEuY2xhc3NOYW1lJiZhLmNsYXNzTmFtZXx8InVuZGVmaW5lZCIhPXR5cGVvZiBhLmdldEF0dHJpYnV0ZSYmYS5nZXRBdHRyaWJ1dGUoImNsYXNzIil8fCIiKX0pfSxBVFRSOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gZnVuY3Rpb24oZCl7dmFyIGU9Z2EuYXR0cihkLGEpO3JldHVybiBudWxsPT1lPyIhPSI9PT1iOmI/KGUrPSIiLCI9Ij09PWI/ZT09PWM6IiE9Ij09PWI/ZSE9PWM6Il49Ij09PWI/YyYmMD09PWUuaW5kZXhPZihjKToiKj0iPT09Yj9jJiZlLmluZGV4T2YoYyk+LTE6IiQ9Ij09PWI/YyYmZS5zbGljZSgtYy5sZW5ndGgpPT09Yzoifj0iPT09Yj8oIiAiK2UucmVwbGFjZShRLCIgIikrIiAiKS5pbmRleE9mKGMpPi0xOiJ8PSI9PT1iP2U9PT1jfHxlLnNsaWNlKDAsYy5sZW5ndGgrMSk9PT1jKyItIjohMSk6ITB9fSxDSElMRDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBmPSJudGgiIT09YS5zbGljZSgwLDMpLGc9Imxhc3QiIT09YS5zbGljZSgtNCksaD0ib2YtdHlwZSI9PT1iO3JldHVybiAxPT09ZCYmMD09PWU/ZnVuY3Rpb24oYSl7cmV0dXJuISFhLnBhcmVudE5vZGV9OmZ1bmN0aW9uKGIsYyxpKXt2YXIgaixrLGwsbSxuLG8scD1mIT09Zz8ibmV4dFNpYmxpbmciOiJwcmV2aW91c1NpYmxpbmciLHE9Yi5wYXJlbnROb2RlLHI9aCYmYi5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpLHM9IWkmJiFoO2lmKHEpe2lmKGYpe3doaWxlKHApe2w9Yjt3aGlsZShsPWxbcF0paWYoaD9sLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT1yOjE9PT1sLm5vZGVUeXBlKXJldHVybiExO289cD0ib25seSI9PT1hJiYhbyYmIm5leHRTaWJsaW5nIn1yZXR1cm4hMH1pZihvPVtnP3EuZmlyc3RDaGlsZDpxLmxhc3RDaGlsZF0sZyYmcyl7az1xW3VdfHwocVt1XT17fSksaj1rW2FdfHxbXSxuPWpbMF09PT13JiZqWzFdLG09alswXT09PXcmJmpbMl0sbD1uJiZxLmNoaWxkTm9kZXNbbl07d2hpbGUobD0rK24mJmwmJmxbcF18fChtPW49MCl8fG8ucG9wKCkpaWYoMT09PWwubm9kZVR5cGUmJisrbSYmbD09PWIpe2tbYV09W3csbixtXTticmVha319ZWxzZSBpZihzJiYoaj0oYlt1XXx8KGJbdV09e30pKVthXSkmJmpbMF09PT13KW09alsxXTtlbHNlIHdoaWxlKGw9KytuJiZsJiZsW3BdfHwobT1uPTApfHxvLnBvcCgpKWlmKChoP2wubm9kZU5hbWUudG9Mb3dlckNhc2UoKT09PXI6MT09PWwubm9kZVR5cGUpJiYrK20mJihzJiYoKGxbdV18fChsW3VdPXt9KSlbYV09W3csbV0pLGw9PT1iKSlicmVhaztyZXR1cm4gbS09ZSxtPT09ZHx8bSVkPT09MCYmbS9kPj0wfX19LFBTRVVETzpmdW5jdGlvbihhLGIpe3ZhciBjLGU9ZC5wc2V1ZG9zW2FdfHxkLnNldEZpbHRlcnNbYS50b0xvd2VyQ2FzZSgpXXx8Z2EuZXJyb3IoInVuc3VwcG9ydGVkIHBzZXVkbzogIithKTtyZXR1cm4gZVt1XT9lKGIpOmUubGVuZ3RoPjE/KGM9W2EsYSwiIixiXSxkLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoYS50b0xvd2VyQ2FzZSgpKT9pYShmdW5jdGlvbihhLGMpe3ZhciBkLGY9ZShhLGIpLGc9Zi5sZW5ndGg7d2hpbGUoZy0tKWQ9SihhLGZbZ10pLGFbZF09IShjW2RdPWZbZ10pfSk6ZnVuY3Rpb24oYSl7cmV0dXJuIGUoYSwwLGMpfSk6ZX19LHBzZXVkb3M6e25vdDppYShmdW5jdGlvbihhKXt2YXIgYj1bXSxjPVtdLGQ9aChhLnJlcGxhY2UoUiwiJDEiKSk7cmV0dXJuIGRbdV0/aWEoZnVuY3Rpb24oYSxiLGMsZSl7dmFyIGYsZz1kKGEsbnVsbCxlLFtdKSxoPWEubGVuZ3RoO3doaWxlKGgtLSkoZj1nW2hdKSYmKGFbaF09IShiW2hdPWYpKX0pOmZ1bmN0aW9uKGEsZSxmKXtyZXR1cm4gYlswXT1hLGQoYixudWxsLGYsYyksYlswXT1udWxsLCFjLnBvcCgpfX0pLGhhczppYShmdW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rpb24oYil7cmV0dXJuIGdhKGEsYikubGVuZ3RoPjB9fSksY29udGFpbnM6aWEoZnVuY3Rpb24oYSl7cmV0dXJuIGE9YS5yZXBsYWNlKGNhLGRhKSxmdW5jdGlvbihiKXtyZXR1cm4oYi50ZXh0Q29udGVudHx8Yi5pbm5lclRleHR8fGUoYikpLmluZGV4T2YoYSk+LTF9fSksbGFuZzppYShmdW5jdGlvbihhKXtyZXR1cm4gVy50ZXN0KGF8fCIiKXx8Z2EuZXJyb3IoInVuc3VwcG9ydGVkIGxhbmc6ICIrYSksYT1hLnJlcGxhY2UoY2EsZGEpLnRvTG93ZXJDYXNlKCksZnVuY3Rpb24oYil7dmFyIGM7ZG8gaWYoYz1wP2IubGFuZzpiLmdldEF0dHJpYnV0ZSgieG1sOmxhbmciKXx8Yi5nZXRBdHRyaWJ1dGUoImxhbmciKSlyZXR1cm4gYz1jLnRvTG93ZXJDYXNlKCksYz09PWF8fDA9PT1jLmluZGV4T2YoYSsiLSIpO3doaWxlKChiPWIucGFyZW50Tm9kZSkmJjE9PT1iLm5vZGVUeXBlKTtyZXR1cm4hMX19KSx0YXJnZXQ6ZnVuY3Rpb24oYil7dmFyIGM9YS5sb2NhdGlvbiYmYS5sb2NhdGlvbi5oYXNoO3JldHVybiBjJiZjLnNsaWNlKDEpPT09Yi5pZH0scm9vdDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PW99LGZvY3VzOmZ1bmN0aW9uKGEpe3JldHVybiBhPT09bi5hY3RpdmVFbGVtZW50JiYoIW4uaGFzRm9jdXN8fG4uaGFzRm9jdXMoKSkmJiEhKGEudHlwZXx8YS5ocmVmfHx+YS50YWJJbmRleCl9LGVuYWJsZWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuZGlzYWJsZWQ9PT0hMX0sZGlzYWJsZWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuZGlzYWJsZWQ9PT0hMH0sY2hlY2tlZDpmdW5jdGlvbihhKXt2YXIgYj1hLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7cmV0dXJuImlucHV0Ij09PWImJiEhYS5jaGVja2VkfHwib3B0aW9uIj09PWImJiEhYS5zZWxlY3RlZH0sc2VsZWN0ZWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGEucGFyZW50Tm9kZSYmYS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXgsYS5zZWxlY3RlZD09PSEwfSxlbXB0eTpmdW5jdGlvbihhKXtmb3IoYT1hLmZpcnN0Q2hpbGQ7YTthPWEubmV4dFNpYmxpbmcpaWYoYS5ub2RlVHlwZTw2KXJldHVybiExO3JldHVybiEwfSxwYXJlbnQ6ZnVuY3Rpb24oYSl7cmV0dXJuIWQucHNldWRvcy5lbXB0eShhKX0saGVhZGVyOmZ1bmN0aW9uKGEpe3JldHVybiBaLnRlc3QoYS5ub2RlTmFtZSl9LGlucHV0OmZ1bmN0aW9uKGEpe3JldHVybiBZLnRlc3QoYS5ub2RlTmFtZSl9LGJ1dHRvbjpmdW5jdGlvbihhKXt2YXIgYj1hLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7cmV0dXJuImlucHV0Ij09PWImJiJidXR0b24iPT09YS50eXBlfHwiYnV0dG9uIj09PWJ9LHRleHQ6ZnVuY3Rpb24oYSl7dmFyIGI7cmV0dXJuImlucHV0Ij09PWEubm9kZU5hbWUudG9Mb3dlckNhc2UoKSYmInRleHQiPT09YS50eXBlJiYobnVsbD09KGI9YS5nZXRBdHRyaWJ1dGUoInR5cGUiKSl8fCJ0ZXh0Ij09PWIudG9Mb3dlckNhc2UoKSl9LGZpcnN0Om9hKGZ1bmN0aW9uKCl7cmV0dXJuWzBdfSksbGFzdDpvYShmdW5jdGlvbihhLGIpe3JldHVybltiLTFdfSksZXE6b2EoZnVuY3Rpb24oYSxiLGMpe3JldHVyblswPmM/YytiOmNdfSksZXZlbjpvYShmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz0wO2I+YztjKz0yKWEucHVzaChjKTtyZXR1cm4gYX0pLG9kZDpvYShmdW5jdGlvbihhLGIpe2Zvcih2YXIgYz0xO2I+YztjKz0yKWEucHVzaChjKTtyZXR1cm4gYX0pLGx0Om9hKGZ1bmN0aW9uKGEsYixjKXtmb3IodmFyIGQ9MD5jP2MrYjpjOy0tZD49MDspYS5wdXNoKGQpO3JldHVybiBhfSksZ3Q6b2EoZnVuY3Rpb24oYSxiLGMpe2Zvcih2YXIgZD0wPmM/YytiOmM7KytkPGI7KWEucHVzaChkKTtyZXR1cm4gYX0pfX0sZC5wc2V1ZG9zLm50aD1kLnBzZXVkb3MuZXE7Zm9yKGIgaW57cmFkaW86ITAsY2hlY2tib3g6ITAsZmlsZTohMCxwYXNzd29yZDohMCxpbWFnZTohMH0pZC5wc2V1ZG9zW2JdPW1hKGIpO2ZvcihiIGlue3N1Ym1pdDohMCxyZXNldDohMH0pZC5wc2V1ZG9zW2JdPW5hKGIpO2Z1bmN0aW9uIHFhKCl7fXFhLnByb3RvdHlwZT1kLmZpbHRlcnM9ZC5wc2V1ZG9zLGQuc2V0RmlsdGVycz1uZXcgcWEsZz1nYS50b2tlbml6ZT1mdW5jdGlvbihhLGIpe3ZhciBjLGUsZixnLGgsaSxqLGs9elthKyIgIl07aWYoaylyZXR1cm4gYj8wOmsuc2xpY2UoMCk7aD1hLGk9W10saj1kLnByZUZpbHRlcjt3aGlsZShoKXsoIWN8fChlPVMuZXhlYyhoKSkpJiYoZSYmKGg9aC5zbGljZShlWzBdLmxlbmd0aCl8fGgpLGkucHVzaChmPVtdKSksYz0hMSwoZT1ULmV4ZWMoaCkpJiYoYz1lLnNoaWZ0KCksZi5wdXNoKHt2YWx1ZTpjLHR5cGU6ZVswXS5yZXBsYWNlKFIsIiAiKX0pLGg9aC5zbGljZShjLmxlbmd0aCkpO2ZvcihnIGluIGQuZmlsdGVyKSEoZT1YW2ddLmV4ZWMoaCkpfHxqW2ddJiYhKGU9altnXShlKSl8fChjPWUuc2hpZnQoKSxmLnB1c2goe3ZhbHVlOmMsdHlwZTpnLG1hdGNoZXM6ZX0pLGg9aC5zbGljZShjLmxlbmd0aCkpO2lmKCFjKWJyZWFrfXJldHVybiBiP2gubGVuZ3RoOmg/Z2EuZXJyb3IoYSk6eihhLGkpLnNsaWNlKDApfTtmdW5jdGlvbiByYShhKXtmb3IodmFyIGI9MCxjPWEubGVuZ3RoLGQ9IiI7Yz5iO2IrKylkKz1hW2JdLnZhbHVlO3JldHVybiBkfWZ1bmN0aW9uIHNhKGEsYixjKXt2YXIgZD1iLmRpcixlPWMmJiJwYXJlbnROb2RlIj09PWQsZj14Kys7cmV0dXJuIGIuZmlyc3Q/ZnVuY3Rpb24oYixjLGYpe3doaWxlKGI9YltkXSlpZigxPT09Yi5ub2RlVHlwZXx8ZSlyZXR1cm4gYShiLGMsZil9OmZ1bmN0aW9uKGIsYyxnKXt2YXIgaCxpLGo9W3csZl07aWYoZyl7d2hpbGUoYj1iW2RdKWlmKCgxPT09Yi5ub2RlVHlwZXx8ZSkmJmEoYixjLGcpKXJldHVybiEwfWVsc2Ugd2hpbGUoYj1iW2RdKWlmKDE9PT1iLm5vZGVUeXBlfHxlKXtpZihpPWJbdV18fChiW3VdPXt9KSwoaD1pW2RdKSYmaFswXT09PXcmJmhbMV09PT1mKXJldHVybiBqWzJdPWhbMl07aWYoaVtkXT1qLGpbMl09YShiLGMsZykpcmV0dXJuITB9fX1mdW5jdGlvbiB0YShhKXtyZXR1cm4gYS5sZW5ndGg+MT9mdW5jdGlvbihiLGMsZCl7dmFyIGU9YS5sZW5ndGg7d2hpbGUoZS0tKWlmKCFhW2VdKGIsYyxkKSlyZXR1cm4hMTtyZXR1cm4hMH06YVswXX1mdW5jdGlvbiB1YShhLGIsYyl7Zm9yKHZhciBkPTAsZT1iLmxlbmd0aDtlPmQ7ZCsrKWdhKGEsYltkXSxjKTtyZXR1cm4gY31mdW5jdGlvbiB2YShhLGIsYyxkLGUpe2Zvcih2YXIgZixnPVtdLGg9MCxpPWEubGVuZ3RoLGo9bnVsbCE9YjtpPmg7aCsrKShmPWFbaF0pJiYoIWN8fGMoZixkLGUpKSYmKGcucHVzaChmKSxqJiZiLnB1c2goaCkpO3JldHVybiBnfWZ1bmN0aW9uIHdhKGEsYixjLGQsZSxmKXtyZXR1cm4gZCYmIWRbdV0mJihkPXdhKGQpKSxlJiYhZVt1XSYmKGU9d2EoZSxmKSksaWEoZnVuY3Rpb24oZixnLGgsaSl7dmFyIGosayxsLG09W10sbj1bXSxvPWcubGVuZ3RoLHA9Znx8dWEoYnx8IioiLGgubm9kZVR5cGU/W2hdOmgsW10pLHE9IWF8fCFmJiZiP3A6dmEocCxtLGEsaCxpKSxyPWM/ZXx8KGY/YTpvfHxkKT9bXTpnOnE7aWYoYyYmYyhxLHIsaCxpKSxkKXtqPXZhKHIsbiksZChqLFtdLGgsaSksaz1qLmxlbmd0aDt3aGlsZShrLS0pKGw9altrXSkmJihyW25ba11dPSEocVtuW2tdXT1sKSl9aWYoZil7aWYoZXx8YSl7aWYoZSl7aj1bXSxrPXIubGVuZ3RoO3doaWxlKGstLSkobD1yW2tdKSYmai5wdXNoKHFba109bCk7ZShudWxsLHI9W10saixpKX1rPXIubGVuZ3RoO3doaWxlKGstLSkobD1yW2tdKSYmKGo9ZT9KKGYsbCk6bVtrXSk+LTEmJihmW2pdPSEoZ1tqXT1sKSl9fWVsc2Ugcj12YShyPT09Zz9yLnNwbGljZShvLHIubGVuZ3RoKTpyKSxlP2UobnVsbCxnLHIsaSk6SC5hcHBseShnLHIpfSl9ZnVuY3Rpb24geGEoYSl7Zm9yKHZhciBiLGMsZSxmPWEubGVuZ3RoLGc9ZC5yZWxhdGl2ZVthWzBdLnR5cGVdLGg9Z3x8ZC5yZWxhdGl2ZVsiICJdLGk9Zz8xOjAsaz1zYShmdW5jdGlvbihhKXtyZXR1cm4gYT09PWJ9LGgsITApLGw9c2EoZnVuY3Rpb24oYSl7cmV0dXJuIEooYixhKT4tMX0saCwhMCksbT1bZnVuY3Rpb24oYSxjLGQpe3ZhciBlPSFnJiYoZHx8YyE9PWopfHwoKGI9Yykubm9kZVR5cGU/ayhhLGMsZCk6bChhLGMsZCkpO3JldHVybiBiPW51bGwsZX1dO2Y+aTtpKyspaWYoYz1kLnJlbGF0aXZlW2FbaV0udHlwZV0pbT1bc2EodGEobSksYyldO2Vsc2V7aWYoYz1kLmZpbHRlclthW2ldLnR5cGVdLmFwcGx5KG51bGwsYVtpXS5tYXRjaGVzKSxjW3VdKXtmb3IoZT0rK2k7Zj5lO2UrKylpZihkLnJlbGF0aXZlW2FbZV0udHlwZV0pYnJlYWs7cmV0dXJuIHdhKGk+MSYmdGEobSksaT4xJiZyYShhLnNsaWNlKDAsaS0xKS5jb25jYXQoe3ZhbHVlOiIgIj09PWFbaS0yXS50eXBlPyIqIjoiIn0pKS5yZXBsYWNlKFIsIiQxIiksYyxlPmkmJnhhKGEuc2xpY2UoaSxlKSksZj5lJiZ4YShhPWEuc2xpY2UoZSkpLGY+ZSYmcmEoYSkpfW0ucHVzaChjKX1yZXR1cm4gdGEobSl9ZnVuY3Rpb24geWEoYSxiKXt2YXIgYz1iLmxlbmd0aD4wLGU9YS5sZW5ndGg+MCxmPWZ1bmN0aW9uKGYsZyxoLGksayl7dmFyIGwsbSxvLHA9MCxxPSIwIixyPWYmJltdLHM9W10sdD1qLHU9Znx8ZSYmZC5maW5kLlRBRygiKiIsayksdj13Kz1udWxsPT10PzE6TWF0aC5yYW5kb20oKXx8LjEseD11Lmxlbmd0aDtmb3IoayYmKGo9ZyE9PW4mJmcpO3EhPT14JiZudWxsIT0obD11W3FdKTtxKyspe2lmKGUmJmwpe209MDt3aGlsZShvPWFbbSsrXSlpZihvKGwsZyxoKSl7aS5wdXNoKGwpO2JyZWFrfWsmJih3PXYpfWMmJigobD0hbyYmbCkmJnAtLSxmJiZyLnB1c2gobCkpfWlmKHArPXEsYyYmcSE9PXApe209MDt3aGlsZShvPWJbbSsrXSlvKHIscyxnLGgpO2lmKGYpe2lmKHA+MCl3aGlsZShxLS0pcltxXXx8c1txXXx8KHNbcV09Ri5jYWxsKGkpKTtzPXZhKHMpfUguYXBwbHkoaSxzKSxrJiYhZiYmcy5sZW5ndGg+MCYmcCtiLmxlbmd0aD4xJiZnYS51bmlxdWVTb3J0KGkpfXJldHVybiBrJiYodz12LGo9dCkscn07cmV0dXJuIGM/aWEoZik6Zn1yZXR1cm4gaD1nYS5jb21waWxlPWZ1bmN0aW9uKGEsYil7dmFyIGMsZD1bXSxlPVtdLGY9QVthKyIgIl07aWYoIWYpe2J8fChiPWcoYSkpLGM9Yi5sZW5ndGg7d2hpbGUoYy0tKWY9eGEoYltjXSksZlt1XT9kLnB1c2goZik6ZS5wdXNoKGYpO2Y9QShhLHlhKGUsZCkpLGYuc2VsZWN0b3I9YX1yZXR1cm4gZn0saT1nYS5zZWxlY3Q9ZnVuY3Rpb24oYSxiLGUsZil7dmFyIGksaixrLGwsbSxuPSJmdW5jdGlvbiI9PXR5cGVvZiBhJiZhLG89IWYmJmcoYT1uLnNlbGVjdG9yfHxhKTtpZihlPWV8fFtdLDE9PT1vLmxlbmd0aCl7aWYoaj1vWzBdPW9bMF0uc2xpY2UoMCksai5sZW5ndGg+MiYmIklEIj09PShrPWpbMF0pLnR5cGUmJmMuZ2V0QnlJZCYmOT09PWIubm9kZVR5cGUmJnAmJmQucmVsYXRpdmVbalsxXS50eXBlXSl7aWYoYj0oZC5maW5kLklEKGsubWF0Y2hlc1swXS5yZXBsYWNlKGNhLGRhKSxiKXx8W10pWzBdLCFiKXJldHVybiBlO24mJihiPWIucGFyZW50Tm9kZSksYT1hLnNsaWNlKGouc2hpZnQoKS52YWx1ZS5sZW5ndGgpfWk9WC5uZWVkc0NvbnRleHQudGVzdChhKT8wOmoubGVuZ3RoO3doaWxlKGktLSl7aWYoaz1qW2ldLGQucmVsYXRpdmVbbD1rLnR5cGVdKWJyZWFrO2lmKChtPWQuZmluZFtsXSkmJihmPW0oay5tYXRjaGVzWzBdLnJlcGxhY2UoY2EsZGEpLGFhLnRlc3QoalswXS50eXBlKSYmcGEoYi5wYXJlbnROb2RlKXx8YikpKXtpZihqLnNwbGljZShpLDEpLGE9Zi5sZW5ndGgmJnJhKGopLCFhKXJldHVybiBILmFwcGx5KGUsZiksZTticmVha319fXJldHVybihufHxoKGEsbykpKGYsYiwhcCxlLGFhLnRlc3QoYSkmJnBhKGIucGFyZW50Tm9kZSl8fGIpLGV9LGMuc29ydFN0YWJsZT11LnNwbGl0KCIiKS5zb3J0KEIpLmpvaW4oIiIpPT09dSxjLmRldGVjdER1cGxpY2F0ZXM9ISFsLG0oKSxjLnNvcnREZXRhY2hlZD1qYShmdW5jdGlvbihhKXtyZXR1cm4gMSZhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKG4uY3JlYXRlRWxlbWVudCgiZGl2IikpfSksamEoZnVuY3Rpb24oYSl7cmV0dXJuIGEuaW5uZXJIVE1MPSI8YSBocmVmPScjJz48L2E+IiwiIyI9PT1hLmZpcnN0Q2hpbGQuZ2V0QXR0cmlidXRlKCJocmVmIil9KXx8a2EoInR5cGV8aHJlZnxoZWlnaHR8d2lkdGgiLGZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYz92b2lkIDA6YS5nZXRBdHRyaWJ1dGUoYiwidHlwZSI9PT1iLnRvTG93ZXJDYXNlKCk/MToyKX0pLGMuYXR0cmlidXRlcyYmamEoZnVuY3Rpb24oYSl7cmV0dXJuIGEuaW5uZXJIVE1MPSI8aW5wdXQvPiIsYS5maXJzdENoaWxkLnNldEF0dHJpYnV0ZSgidmFsdWUiLCIiKSwiIj09PWEuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoInZhbHVlIil9KXx8a2EoInZhbHVlIixmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGN8fCJpbnB1dCIhPT1hLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk/dm9pZCAwOmEuZGVmYXVsdFZhbHVlfSksamEoZnVuY3Rpb24oYSl7cmV0dXJuIG51bGw9PWEuZ2V0QXR0cmlidXRlKCJkaXNhYmxlZCIpfSl8fGthKEssZnVuY3Rpb24oYSxiLGMpe3ZhciBkO3JldHVybiBjP3ZvaWQgMDphW2JdPT09ITA/Yi50b0xvd2VyQ2FzZSgpOihkPWEuZ2V0QXR0cmlidXRlTm9kZShiKSkmJmQuc3BlY2lmaWVkP2QudmFsdWU6bnVsbH0pLGdhfShhKTttLmZpbmQ9cyxtLmV4cHI9cy5zZWxlY3RvcnMsbS5leHByWyI6Il09bS5leHByLnBzZXVkb3MsbS51bmlxdWU9cy51bmlxdWVTb3J0LG0udGV4dD1zLmdldFRleHQsbS5pc1hNTERvYz1zLmlzWE1MLG0uY29udGFpbnM9cy5jb250YWluczt2YXIgdD1tLmV4cHIubWF0Y2gubmVlZHNDb250ZXh0LHU9L148KFx3KylccypcLz8+KD86PFwvXDE+fCkkLyx2PS9eLlteOiNcW1wuLF0qJC87ZnVuY3Rpb24gdyhhLGIsYyl7aWYobS5pc0Z1bmN0aW9uKGIpKXJldHVybiBtLmdyZXAoYSxmdW5jdGlvbihhLGQpe3JldHVybiEhYi5jYWxsKGEsZCxhKSE9PWN9KTtpZihiLm5vZGVUeXBlKXJldHVybiBtLmdyZXAoYSxmdW5jdGlvbihhKXtyZXR1cm4gYT09PWIhPT1jfSk7aWYoInN0cmluZyI9PXR5cGVvZiBiKXtpZih2LnRlc3QoYikpcmV0dXJuIG0uZmlsdGVyKGIsYSxjKTtiPW0uZmlsdGVyKGIsYSl9cmV0dXJuIG0uZ3JlcChhLGZ1bmN0aW9uKGEpe3JldHVybiBtLmluQXJyYXkoYSxiKT49MCE9PWN9KX1tLmZpbHRlcj1mdW5jdGlvbihhLGIsYyl7dmFyIGQ9YlswXTtyZXR1cm4gYyYmKGE9Ijpub3QoIithKyIpIiksMT09PWIubGVuZ3RoJiYxPT09ZC5ub2RlVHlwZT9tLmZpbmQubWF0Y2hlc1NlbGVjdG9yKGQsYSk/W2RdOltdOm0uZmluZC5tYXRjaGVzKGEsbS5ncmVwKGIsZnVuY3Rpb24oYSl7cmV0dXJuIDE9PT1hLm5vZGVUeXBlfSkpfSxtLmZuLmV4dGVuZCh7ZmluZDpmdW5jdGlvbihhKXt2YXIgYixjPVtdLGQ9dGhpcyxlPWQubGVuZ3RoO2lmKCJzdHJpbmciIT10eXBlb2YgYSlyZXR1cm4gdGhpcy5wdXNoU3RhY2sobShhKS5maWx0ZXIoZnVuY3Rpb24oKXtmb3IoYj0wO2U+YjtiKyspaWYobS5jb250YWlucyhkW2JdLHRoaXMpKXJldHVybiEwfSkpO2ZvcihiPTA7ZT5iO2IrKyltLmZpbmQoYSxkW2JdLGMpO3JldHVybiBjPXRoaXMucHVzaFN0YWNrKGU+MT9tLnVuaXF1ZShjKTpjKSxjLnNlbGVjdG9yPXRoaXMuc2VsZWN0b3I/dGhpcy5zZWxlY3RvcisiICIrYTphLGN9LGZpbHRlcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5wdXNoU3RhY2sodyh0aGlzLGF8fFtdLCExKSl9LG5vdDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5wdXNoU3RhY2sodyh0aGlzLGF8fFtdLCEwKSl9LGlzOmZ1bmN0aW9uKGEpe3JldHVybiEhdyh0aGlzLCJzdHJpbmciPT10eXBlb2YgYSYmdC50ZXN0KGEpP20oYSk6YXx8W10sITEpLmxlbmd0aH19KTt2YXIgeCx5PWEuZG9jdW1lbnQsej0vXig/OlxzKig8W1x3XFddKz4pW14+XSp8IyhbXHctXSopKSQvLEE9bS5mbi5pbml0PWZ1bmN0aW9uKGEsYil7dmFyIGMsZDtpZighYSlyZXR1cm4gdGhpcztpZigic3RyaW5nIj09dHlwZW9mIGEpe2lmKGM9IjwiPT09YS5jaGFyQXQoMCkmJiI+Ij09PWEuY2hhckF0KGEubGVuZ3RoLTEpJiZhLmxlbmd0aD49Mz9bbnVsbCxhLG51bGxdOnouZXhlYyhhKSwhY3x8IWNbMV0mJmIpcmV0dXJuIWJ8fGIuanF1ZXJ5PyhifHx4KS5maW5kKGEpOnRoaXMuY29uc3RydWN0b3IoYikuZmluZChhKTtpZihjWzFdKXtpZihiPWIgaW5zdGFuY2VvZiBtP2JbMF06YixtLm1lcmdlKHRoaXMsbS5wYXJzZUhUTUwoY1sxXSxiJiZiLm5vZGVUeXBlP2Iub3duZXJEb2N1bWVudHx8Yjp5LCEwKSksdS50ZXN0KGNbMV0pJiZtLmlzUGxhaW5PYmplY3QoYikpZm9yKGMgaW4gYiltLmlzRnVuY3Rpb24odGhpc1tjXSk/dGhpc1tjXShiW2NdKTp0aGlzLmF0dHIoYyxiW2NdKTtyZXR1cm4gdGhpc31pZihkPXkuZ2V0RWxlbWVudEJ5SWQoY1syXSksZCYmZC5wYXJlbnROb2RlKXtpZihkLmlkIT09Y1syXSlyZXR1cm4geC5maW5kKGEpO3RoaXMubGVuZ3RoPTEsdGhpc1swXT1kfXJldHVybiB0aGlzLmNvbnRleHQ9eSx0aGlzLnNlbGVjdG9yPWEsdGhpc31yZXR1cm4gYS5ub2RlVHlwZT8odGhpcy5jb250ZXh0PXRoaXNbMF09YSx0aGlzLmxlbmd0aD0xLHRoaXMpOm0uaXNGdW5jdGlvbihhKT8idW5kZWZpbmVkIiE9dHlwZW9mIHgucmVhZHk/eC5yZWFkeShhKTphKG0pOih2b2lkIDAhPT1hLnNlbGVjdG9yJiYodGhpcy5zZWxlY3Rvcj1hLnNlbGVjdG9yLHRoaXMuY29udGV4dD1hLmNvbnRleHQpLG0ubWFrZUFycmF5KGEsdGhpcykpfTtBLnByb3RvdHlwZT1tLmZuLHg9bSh5KTt2YXIgQj0vXig/OnBhcmVudHN8cHJldig/OlVudGlsfEFsbCkpLyxDPXtjaGlsZHJlbjohMCxjb250ZW50czohMCxuZXh0OiEwLHByZXY6ITB9O20uZXh0ZW5kKHtkaXI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBkPVtdLGU9YVtiXTt3aGlsZShlJiY5IT09ZS5ub2RlVHlwZSYmKHZvaWQgMD09PWN8fDEhPT1lLm5vZGVUeXBlfHwhbShlKS5pcyhjKSkpMT09PWUubm9kZVR5cGUmJmQucHVzaChlKSxlPWVbYl07cmV0dXJuIGR9LHNpYmxpbmc6ZnVuY3Rpb24oYSxiKXtmb3IodmFyIGM9W107YTthPWEubmV4dFNpYmxpbmcpMT09PWEubm9kZVR5cGUmJmEhPT1iJiZjLnB1c2goYSk7cmV0dXJuIGN9fSksbS5mbi5leHRlbmQoe2hhczpmdW5jdGlvbihhKXt2YXIgYixjPW0oYSx0aGlzKSxkPWMubGVuZ3RoO3JldHVybiB0aGlzLmZpbHRlcihmdW5jdGlvbigpe2ZvcihiPTA7ZD5iO2IrKylpZihtLmNvbnRhaW5zKHRoaXMsY1tiXSkpcmV0dXJuITB9KX0sY2xvc2VzdDpmdW5jdGlvbihhLGIpe2Zvcih2YXIgYyxkPTAsZT10aGlzLmxlbmd0aCxmPVtdLGc9dC50ZXN0KGEpfHwic3RyaW5nIiE9dHlwZW9mIGE/bShhLGJ8fHRoaXMuY29udGV4dCk6MDtlPmQ7ZCsrKWZvcihjPXRoaXNbZF07YyYmYyE9PWI7Yz1jLnBhcmVudE5vZGUpaWYoYy5ub2RlVHlwZTwxMSYmKGc/Zy5pbmRleChjKT4tMToxPT09Yy5ub2RlVHlwZSYmbS5maW5kLm1hdGNoZXNTZWxlY3RvcihjLGEpKSl7Zi5wdXNoKGMpO2JyZWFrfXJldHVybiB0aGlzLnB1c2hTdGFjayhmLmxlbmd0aD4xP20udW5pcXVlKGYpOmYpfSxpbmRleDpmdW5jdGlvbihhKXtyZXR1cm4gYT8ic3RyaW5nIj09dHlwZW9mIGE/bS5pbkFycmF5KHRoaXNbMF0sbShhKSk6bS5pbkFycmF5KGEuanF1ZXJ5P2FbMF06YSx0aGlzKTp0aGlzWzBdJiZ0aGlzWzBdLnBhcmVudE5vZGU/dGhpcy5maXJzdCgpLnByZXZBbGwoKS5sZW5ndGg6LTF9LGFkZDpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnB1c2hTdGFjayhtLnVuaXF1ZShtLm1lcmdlKHRoaXMuZ2V0KCksbShhLGIpKSkpfSxhZGRCYWNrOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmFkZChudWxsPT1hP3RoaXMucHJldk9iamVjdDp0aGlzLnByZXZPYmplY3QuZmlsdGVyKGEpKX19KTtmdW5jdGlvbiBEKGEsYil7ZG8gYT1hW2JdO3doaWxlKGEmJjEhPT1hLm5vZGVUeXBlKTtyZXR1cm4gYX1tLmVhY2goe3BhcmVudDpmdW5jdGlvbihhKXt2YXIgYj1hLnBhcmVudE5vZGU7cmV0dXJuIGImJjExIT09Yi5ub2RlVHlwZT9iOm51bGx9LHBhcmVudHM6ZnVuY3Rpb24oYSl7cmV0dXJuIG0uZGlyKGEsInBhcmVudE5vZGUiKX0scGFyZW50c1VudGlsOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbS5kaXIoYSwicGFyZW50Tm9kZSIsYyl9LG5leHQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEQoYSwibmV4dFNpYmxpbmciKX0scHJldjpmdW5jdGlvbihhKXtyZXR1cm4gRChhLCJwcmV2aW91c1NpYmxpbmciKX0sbmV4dEFsbDpmdW5jdGlvbihhKXtyZXR1cm4gbS5kaXIoYSwibmV4dFNpYmxpbmciKX0scHJldkFsbDpmdW5jdGlvbihhKXtyZXR1cm4gbS5kaXIoYSwicHJldmlvdXNTaWJsaW5nIil9LG5leHRVbnRpbDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG0uZGlyKGEsIm5leHRTaWJsaW5nIixjKX0scHJldlVudGlsOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbS5kaXIoYSwicHJldmlvdXNTaWJsaW5nIixjKX0sc2libGluZ3M6ZnVuY3Rpb24oYSl7cmV0dXJuIG0uc2libGluZygoYS5wYXJlbnROb2RlfHx7fSkuZmlyc3RDaGlsZCxhKX0sY2hpbGRyZW46ZnVuY3Rpb24oYSl7cmV0dXJuIG0uc2libGluZyhhLmZpcnN0Q2hpbGQpfSxjb250ZW50czpmdW5jdGlvbihhKXtyZXR1cm4gbS5ub2RlTmFtZShhLCJpZnJhbWUiKT9hLmNvbnRlbnREb2N1bWVudHx8YS5jb250ZW50V2luZG93LmRvY3VtZW50Om0ubWVyZ2UoW10sYS5jaGlsZE5vZGVzKX19LGZ1bmN0aW9uKGEsYil7bS5mblthXT1mdW5jdGlvbihjLGQpe3ZhciBlPW0ubWFwKHRoaXMsYixjKTtyZXR1cm4iVW50aWwiIT09YS5zbGljZSgtNSkmJihkPWMpLGQmJiJzdHJpbmciPT10eXBlb2YgZCYmKGU9bS5maWx0ZXIoZCxlKSksdGhpcy5sZW5ndGg+MSYmKENbYV18fChlPW0udW5pcXVlKGUpKSxCLnRlc3QoYSkmJihlPWUucmV2ZXJzZSgpKSksdGhpcy5wdXNoU3RhY2soZSl9fSk7dmFyIEU9L1xTKy9nLEY9e307ZnVuY3Rpb24gRyhhKXt2YXIgYj1GW2FdPXt9O3JldHVybiBtLmVhY2goYS5tYXRjaChFKXx8W10sZnVuY3Rpb24oYSxjKXtiW2NdPSEwfSksYn1tLkNhbGxiYWNrcz1mdW5jdGlvbihhKXthPSJzdHJpbmciPT10eXBlb2YgYT9GW2FdfHxHKGEpOm0uZXh0ZW5kKHt9LGEpO3ZhciBiLGMsZCxlLGYsZyxoPVtdLGk9IWEub25jZSYmW10saj1mdW5jdGlvbihsKXtmb3IoYz1hLm1lbW9yeSYmbCxkPSEwLGY9Z3x8MCxnPTAsZT1oLmxlbmd0aCxiPSEwO2gmJmU+ZjtmKyspaWYoaFtmXS5hcHBseShsWzBdLGxbMV0pPT09ITEmJmEuc3RvcE9uRmFsc2Upe2M9ITE7YnJlYWt9Yj0hMSxoJiYoaT9pLmxlbmd0aCYmaihpLnNoaWZ0KCkpOmM/aD1bXTprLmRpc2FibGUoKSl9LGs9e2FkZDpmdW5jdGlvbigpe2lmKGgpe3ZhciBkPWgubGVuZ3RoOyFmdW5jdGlvbiBmKGIpe20uZWFjaChiLGZ1bmN0aW9uKGIsYyl7dmFyIGQ9bS50eXBlKGMpOyJmdW5jdGlvbiI9PT1kP2EudW5pcXVlJiZrLmhhcyhjKXx8aC5wdXNoKGMpOmMmJmMubGVuZ3RoJiYic3RyaW5nIiE9PWQmJmYoYyl9KX0oYXJndW1lbnRzKSxiP2U9aC5sZW5ndGg6YyYmKGc9ZCxqKGMpKX1yZXR1cm4gdGhpc30scmVtb3ZlOmZ1bmN0aW9uKCl7cmV0dXJuIGgmJm0uZWFjaChhcmd1bWVudHMsZnVuY3Rpb24oYSxjKXt2YXIgZDt3aGlsZSgoZD1tLmluQXJyYXkoYyxoLGQpKT4tMSloLnNwbGljZShkLDEpLGImJihlPj1kJiZlLS0sZj49ZCYmZi0tKX0pLHRoaXN9LGhhczpmdW5jdGlvbihhKXtyZXR1cm4gYT9tLmluQXJyYXkoYSxoKT4tMTohKCFofHwhaC5sZW5ndGgpfSxlbXB0eTpmdW5jdGlvbigpe3JldHVybiBoPVtdLGU9MCx0aGlzfSxkaXNhYmxlOmZ1bmN0aW9uKCl7cmV0dXJuIGg9aT1jPXZvaWQgMCx0aGlzfSxkaXNhYmxlZDpmdW5jdGlvbigpe3JldHVybiFofSxsb2NrOmZ1bmN0aW9uKCl7cmV0dXJuIGk9dm9pZCAwLGN8fGsuZGlzYWJsZSgpLHRoaXN9LGxvY2tlZDpmdW5jdGlvbigpe3JldHVybiFpfSxmaXJlV2l0aDpmdW5jdGlvbihhLGMpe3JldHVybiFofHxkJiYhaXx8KGM9Y3x8W10sYz1bYSxjLnNsaWNlP2Muc2xpY2UoKTpjXSxiP2kucHVzaChjKTpqKGMpKSx0aGlzfSxmaXJlOmZ1bmN0aW9uKCl7cmV0dXJuIGsuZmlyZVdpdGgodGhpcyxhcmd1bWVudHMpLHRoaXN9LGZpcmVkOmZ1bmN0aW9uKCl7cmV0dXJuISFkfX07cmV0dXJuIGt9LG0uZXh0ZW5kKHtEZWZlcnJlZDpmdW5jdGlvbihhKXt2YXIgYj1bWyJyZXNvbHZlIiwiZG9uZSIsbS5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IiksInJlc29sdmVkIl0sWyJyZWplY3QiLCJmYWlsIixtLkNhbGxiYWNrcygib25jZSBtZW1vcnkiKSwicmVqZWN0ZWQiXSxbIm5vdGlmeSIsInByb2dyZXNzIixtLkNhbGxiYWNrcygibWVtb3J5IildXSxjPSJwZW5kaW5nIixkPXtzdGF0ZTpmdW5jdGlvbigpe3JldHVybiBjfSxhbHdheXM6ZnVuY3Rpb24oKXtyZXR1cm4gZS5kb25lKGFyZ3VtZW50cykuZmFpbChhcmd1bWVudHMpLHRoaXN9LHRoZW46ZnVuY3Rpb24oKXt2YXIgYT1hcmd1bWVudHM7cmV0dXJuIG0uRGVmZXJyZWQoZnVuY3Rpb24oYyl7bS5lYWNoKGIsZnVuY3Rpb24oYixmKXt2YXIgZz1tLmlzRnVuY3Rpb24oYVtiXSkmJmFbYl07ZVtmWzFdXShmdW5jdGlvbigpe3ZhciBhPWcmJmcuYXBwbHkodGhpcyxhcmd1bWVudHMpO2EmJm0uaXNGdW5jdGlvbihhLnByb21pc2UpP2EucHJvbWlzZSgpLmRvbmUoYy5yZXNvbHZlKS5mYWlsKGMucmVqZWN0KS5wcm9ncmVzcyhjLm5vdGlmeSk6Y1tmWzBdKyJXaXRoIl0odGhpcz09PWQ/Yy5wcm9taXNlKCk6dGhpcyxnP1thXTphcmd1bWVudHMpfSl9KSxhPW51bGx9KS5wcm9taXNlKCl9LHByb21pc2U6ZnVuY3Rpb24oYSl7cmV0dXJuIG51bGwhPWE/bS5leHRlbmQoYSxkKTpkfX0sZT17fTtyZXR1cm4gZC5waXBlPWQudGhlbixtLmVhY2goYixmdW5jdGlvbihhLGYpe3ZhciBnPWZbMl0saD1mWzNdO2RbZlsxXV09Zy5hZGQsaCYmZy5hZGQoZnVuY3Rpb24oKXtjPWh9LGJbMV5hXVsyXS5kaXNhYmxlLGJbMl1bMl0ubG9jayksZVtmWzBdXT1mdW5jdGlvbigpe3JldHVybiBlW2ZbMF0rIldpdGgiXSh0aGlzPT09ZT9kOnRoaXMsYXJndW1lbnRzKSx0aGlzfSxlW2ZbMF0rIldpdGgiXT1nLmZpcmVXaXRofSksZC5wcm9taXNlKGUpLGEmJmEuY2FsbChlLGUpLGV9LHdoZW46ZnVuY3Rpb24oYSl7dmFyIGI9MCxjPWQuY2FsbChhcmd1bWVudHMpLGU9Yy5sZW5ndGgsZj0xIT09ZXx8YSYmbS5pc0Z1bmN0aW9uKGEucHJvbWlzZSk/ZTowLGc9MT09PWY/YTptLkRlZmVycmVkKCksaD1mdW5jdGlvbihhLGIsYyl7cmV0dXJuIGZ1bmN0aW9uKGUpe2JbYV09dGhpcyxjW2FdPWFyZ3VtZW50cy5sZW5ndGg+MT9kLmNhbGwoYXJndW1lbnRzKTplLGM9PT1pP2cubm90aWZ5V2l0aChiLGMpOi0tZnx8Zy5yZXNvbHZlV2l0aChiLGMpfX0saSxqLGs7aWYoZT4xKWZvcihpPW5ldyBBcnJheShlKSxqPW5ldyBBcnJheShlKSxrPW5ldyBBcnJheShlKTtlPmI7YisrKWNbYl0mJm0uaXNGdW5jdGlvbihjW2JdLnByb21pc2UpP2NbYl0ucHJvbWlzZSgpLmRvbmUoaChiLGssYykpLmZhaWwoZy5yZWplY3QpLnByb2dyZXNzKGgoYixqLGkpKTotLWY7cmV0dXJuIGZ8fGcucmVzb2x2ZVdpdGgoayxjKSxnLnByb21pc2UoKX19KTt2YXIgSDttLmZuLnJlYWR5PWZ1bmN0aW9uKGEpe3JldHVybiBtLnJlYWR5LnByb21pc2UoKS5kb25lKGEpLHRoaXN9LG0uZXh0ZW5kKHtpc1JlYWR5OiExLHJlYWR5V2FpdDoxLGhvbGRSZWFkeTpmdW5jdGlvbihhKXthP20ucmVhZHlXYWl0Kys6bS5yZWFkeSghMCl9LHJlYWR5OmZ1bmN0aW9uKGEpe2lmKGE9PT0hMD8hLS1tLnJlYWR5V2FpdDohbS5pc1JlYWR5KXtpZigheS5ib2R5KXJldHVybiBzZXRUaW1lb3V0KG0ucmVhZHkpO20uaXNSZWFkeT0hMCxhIT09ITAmJi0tbS5yZWFkeVdhaXQ+MHx8KEgucmVzb2x2ZVdpdGgoeSxbbV0pLG0uZm4udHJpZ2dlckhhbmRsZXImJihtKHkpLnRyaWdnZXJIYW5kbGVyKCJyZWFkeSIpLG0oeSkub2ZmKCJyZWFkeSIpKSl9fX0pO2Z1bmN0aW9uIEkoKXt5LmFkZEV2ZW50TGlzdGVuZXI/KHkucmVtb3ZlRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsSiwhMSksYS5yZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIixKLCExKSk6KHkuZGV0YWNoRXZlbnQoIm9ucmVhZHlzdGF0ZWNoYW5nZSIsSiksYS5kZXRhY2hFdmVudCgib25sb2FkIixKKSl9ZnVuY3Rpb24gSigpeyh5LmFkZEV2ZW50TGlzdGVuZXJ8fCJsb2FkIj09PWV2ZW50LnR5cGV8fCJjb21wbGV0ZSI9PT15LnJlYWR5U3RhdGUpJiYoSSgpLG0ucmVhZHkoKSl9bS5yZWFkeS5wcm9taXNlPWZ1bmN0aW9uKGIpe2lmKCFIKWlmKEg9bS5EZWZlcnJlZCgpLCJjb21wbGV0ZSI9PT15LnJlYWR5U3RhdGUpc2V0VGltZW91dChtLnJlYWR5KTtlbHNlIGlmKHkuYWRkRXZlbnRMaXN0ZW5lcil5LmFkZEV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLEosITEpLGEuYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsSiwhMSk7ZWxzZXt5LmF0dGFjaEV2ZW50KCJvbnJlYWR5c3RhdGVjaGFuZ2UiLEopLGEuYXR0YWNoRXZlbnQoIm9ubG9hZCIsSik7dmFyIGM9ITE7dHJ5e2M9bnVsbD09YS5mcmFtZUVsZW1lbnQmJnkuZG9jdW1lbnRFbGVtZW50fWNhdGNoKGQpe31jJiZjLmRvU2Nyb2xsJiYhZnVuY3Rpb24gZSgpe2lmKCFtLmlzUmVhZHkpe3RyeXtjLmRvU2Nyb2xsKCJsZWZ0Iil9Y2F0Y2goYSl7cmV0dXJuIHNldFRpbWVvdXQoZSw1MCl9SSgpLG0ucmVhZHkoKX19KCl9cmV0dXJuIEgucHJvbWlzZShiKX07dmFyIEs9InVuZGVmaW5lZCIsTDtmb3IoTCBpbiBtKGspKWJyZWFrO2sub3duTGFzdD0iMCIhPT1MLGsuaW5saW5lQmxvY2tOZWVkc0xheW91dD0hMSxtKGZ1bmN0aW9uKCl7dmFyIGEsYixjLGQ7Yz15LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJib2R5IilbMF0sYyYmYy5zdHlsZSYmKGI9eS5jcmVhdGVFbGVtZW50KCJkaXYiKSxkPXkuY3JlYXRlRWxlbWVudCgiZGl2IiksZC5zdHlsZS5jc3NUZXh0PSJwb3NpdGlvbjphYnNvbHV0ZTtib3JkZXI6MDt3aWR0aDowO2hlaWdodDowO3RvcDowO2xlZnQ6LTk5OTlweCIsYy5hcHBlbmRDaGlsZChkKS5hcHBlbmRDaGlsZChiKSx0eXBlb2YgYi5zdHlsZS56b29tIT09SyYmKGIuc3R5bGUuY3NzVGV4dD0iZGlzcGxheTppbmxpbmU7bWFyZ2luOjA7Ym9yZGVyOjA7cGFkZGluZzoxcHg7d2lkdGg6MXB4O3pvb206MSIsay5pbmxpbmVCbG9ja05lZWRzTGF5b3V0PWE9Mz09PWIub2Zmc2V0V2lkdGgsYSYmKGMuc3R5bGUuem9vbT0xKSksYy5yZW1vdmVDaGlsZChkKSl9KSxmdW5jdGlvbigpe3ZhciBhPXkuY3JlYXRlRWxlbWVudCgiZGl2Iik7aWYobnVsbD09ay5kZWxldGVFeHBhbmRvKXtrLmRlbGV0ZUV4cGFuZG89ITA7dHJ5e2RlbGV0ZSBhLnRlc3R9Y2F0Y2goYil7ay5kZWxldGVFeHBhbmRvPSExfX1hPW51bGx9KCksbS5hY2NlcHREYXRhPWZ1bmN0aW9uKGEpe3ZhciBiPW0ubm9EYXRhWyhhLm5vZGVOYW1lKyIgIikudG9Mb3dlckNhc2UoKV0sYz0rYS5ub2RlVHlwZXx8MTtyZXR1cm4gMSE9PWMmJjkhPT1jPyExOiFifHxiIT09ITAmJmEuZ2V0QXR0cmlidXRlKCJjbGFzc2lkIik9PT1ifTt2YXIgTT0vXig/Olx7W1x3XFddKlx9fFxbW1x3XFddKlxdKSQvLE49LyhbQS1aXSkvZztmdW5jdGlvbiBPKGEsYixjKXtpZih2b2lkIDA9PT1jJiYxPT09YS5ub2RlVHlwZSl7dmFyIGQ9ImRhdGEtIitiLnJlcGxhY2UoTiwiLSQxIikudG9Mb3dlckNhc2UoKTtpZihjPWEuZ2V0QXR0cmlidXRlKGQpLCJzdHJpbmciPT10eXBlb2YgYyl7dHJ5e2M9InRydWUiPT09Yz8hMDoiZmFsc2UiPT09Yz8hMToibnVsbCI9PT1jP251bGw6K2MrIiI9PT1jPytjOk0udGVzdChjKT9tLnBhcnNlSlNPTihjKTpjfWNhdGNoKGUpe31tLmRhdGEoYSxiLGMpfWVsc2UgYz12b2lkIDB9cmV0dXJuIGN9ZnVuY3Rpb24gUChhKXt2YXIgYjtmb3IoYiBpbiBhKWlmKCgiZGF0YSIhPT1ifHwhbS5pc0VtcHR5T2JqZWN0KGFbYl0pKSYmInRvSlNPTiIhPT1iKXJldHVybiExOwoKcmV0dXJuITB9ZnVuY3Rpb24gUShhLGIsZCxlKXtpZihtLmFjY2VwdERhdGEoYSkpe3ZhciBmLGcsaD1tLmV4cGFuZG8saT1hLm5vZGVUeXBlLGo9aT9tLmNhY2hlOmEsaz1pP2FbaF06YVtoXSYmaDtpZihrJiZqW2tdJiYoZXx8altrXS5kYXRhKXx8dm9pZCAwIT09ZHx8InN0cmluZyIhPXR5cGVvZiBiKXJldHVybiBrfHwoaz1pP2FbaF09Yy5wb3AoKXx8bS5ndWlkKys6aCksaltrXXx8KGpba109aT97fTp7dG9KU09OOm0ubm9vcH0pLCgib2JqZWN0Ij09dHlwZW9mIGJ8fCJmdW5jdGlvbiI9PXR5cGVvZiBiKSYmKGU/altrXT1tLmV4dGVuZChqW2tdLGIpOmpba10uZGF0YT1tLmV4dGVuZChqW2tdLmRhdGEsYikpLGc9altrXSxlfHwoZy5kYXRhfHwoZy5kYXRhPXt9KSxnPWcuZGF0YSksdm9pZCAwIT09ZCYmKGdbbS5jYW1lbENhc2UoYildPWQpLCJzdHJpbmciPT10eXBlb2YgYj8oZj1nW2JdLG51bGw9PWYmJihmPWdbbS5jYW1lbENhc2UoYildKSk6Zj1nLGZ9fWZ1bmN0aW9uIFIoYSxiLGMpe2lmKG0uYWNjZXB0RGF0YShhKSl7dmFyIGQsZSxmPWEubm9kZVR5cGUsZz1mP20uY2FjaGU6YSxoPWY/YVttLmV4cGFuZG9dOm0uZXhwYW5kbztpZihnW2hdKXtpZihiJiYoZD1jP2dbaF06Z1toXS5kYXRhKSl7bS5pc0FycmF5KGIpP2I9Yi5jb25jYXQobS5tYXAoYixtLmNhbWVsQ2FzZSkpOmIgaW4gZD9iPVtiXTooYj1tLmNhbWVsQ2FzZShiKSxiPWIgaW4gZD9bYl06Yi5zcGxpdCgiICIpKSxlPWIubGVuZ3RoO3doaWxlKGUtLSlkZWxldGUgZFtiW2VdXTtpZihjPyFQKGQpOiFtLmlzRW1wdHlPYmplY3QoZCkpcmV0dXJufShjfHwoZGVsZXRlIGdbaF0uZGF0YSxQKGdbaF0pKSkmJihmP20uY2xlYW5EYXRhKFthXSwhMCk6ay5kZWxldGVFeHBhbmRvfHxnIT1nLndpbmRvdz9kZWxldGUgZ1toXTpnW2hdPW51bGwpfX19bS5leHRlbmQoe2NhY2hlOnt9LG5vRGF0YTp7ImFwcGxldCAiOiEwLCJlbWJlZCAiOiEwLCJvYmplY3QgIjoiY2xzaWQ6RDI3Q0RCNkUtQUU2RC0xMWNmLTk2QjgtNDQ0NTUzNTQwMDAwIn0saGFzRGF0YTpmdW5jdGlvbihhKXtyZXR1cm4gYT1hLm5vZGVUeXBlP20uY2FjaGVbYVttLmV4cGFuZG9dXTphW20uZXhwYW5kb10sISFhJiYhUChhKX0sZGF0YTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIFEoYSxiLGMpfSxyZW1vdmVEYXRhOmZ1bmN0aW9uKGEsYil7cmV0dXJuIFIoYSxiKX0sX2RhdGE6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBRKGEsYixjLCEwKX0sX3JlbW92ZURhdGE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gUihhLGIsITApfX0pLG0uZm4uZXh0ZW5kKHtkYXRhOmZ1bmN0aW9uKGEsYil7dmFyIGMsZCxlLGY9dGhpc1swXSxnPWYmJmYuYXR0cmlidXRlcztpZih2b2lkIDA9PT1hKXtpZih0aGlzLmxlbmd0aCYmKGU9bS5kYXRhKGYpLDE9PT1mLm5vZGVUeXBlJiYhbS5fZGF0YShmLCJwYXJzZWRBdHRycyIpKSl7Yz1nLmxlbmd0aDt3aGlsZShjLS0pZ1tjXSYmKGQ9Z1tjXS5uYW1lLDA9PT1kLmluZGV4T2YoImRhdGEtIikmJihkPW0uY2FtZWxDYXNlKGQuc2xpY2UoNSkpLE8oZixkLGVbZF0pKSk7bS5fZGF0YShmLCJwYXJzZWRBdHRycyIsITApfXJldHVybiBlfXJldHVybiJvYmplY3QiPT10eXBlb2YgYT90aGlzLmVhY2goZnVuY3Rpb24oKXttLmRhdGEodGhpcyxhKX0pOmFyZ3VtZW50cy5sZW5ndGg+MT90aGlzLmVhY2goZnVuY3Rpb24oKXttLmRhdGEodGhpcyxhLGIpfSk6Zj9PKGYsYSxtLmRhdGEoZixhKSk6dm9pZCAwfSxyZW1vdmVEYXRhOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXttLnJlbW92ZURhdGEodGhpcyxhKX0pfX0pLG0uZXh0ZW5kKHtxdWV1ZTpmdW5jdGlvbihhLGIsYyl7dmFyIGQ7cmV0dXJuIGE/KGI9KGJ8fCJmeCIpKyJxdWV1ZSIsZD1tLl9kYXRhKGEsYiksYyYmKCFkfHxtLmlzQXJyYXkoYyk/ZD1tLl9kYXRhKGEsYixtLm1ha2VBcnJheShjKSk6ZC5wdXNoKGMpKSxkfHxbXSk6dm9pZCAwfSxkZXF1ZXVlOmZ1bmN0aW9uKGEsYil7Yj1ifHwiZngiO3ZhciBjPW0ucXVldWUoYSxiKSxkPWMubGVuZ3RoLGU9Yy5zaGlmdCgpLGY9bS5fcXVldWVIb29rcyhhLGIpLGc9ZnVuY3Rpb24oKXttLmRlcXVldWUoYSxiKX07ImlucHJvZ3Jlc3MiPT09ZSYmKGU9Yy5zaGlmdCgpLGQtLSksZSYmKCJmeCI9PT1iJiZjLnVuc2hpZnQoImlucHJvZ3Jlc3MiKSxkZWxldGUgZi5zdG9wLGUuY2FsbChhLGcsZikpLCFkJiZmJiZmLmVtcHR5LmZpcmUoKX0sX3F1ZXVlSG9va3M6ZnVuY3Rpb24oYSxiKXt2YXIgYz1iKyJxdWV1ZUhvb2tzIjtyZXR1cm4gbS5fZGF0YShhLGMpfHxtLl9kYXRhKGEsYyx7ZW1wdHk6bS5DYWxsYmFja3MoIm9uY2UgbWVtb3J5IikuYWRkKGZ1bmN0aW9uKCl7bS5fcmVtb3ZlRGF0YShhLGIrInF1ZXVlIiksbS5fcmVtb3ZlRGF0YShhLGMpfSl9KX19KSxtLmZuLmV4dGVuZCh7cXVldWU6ZnVuY3Rpb24oYSxiKXt2YXIgYz0yO3JldHVybiJzdHJpbmciIT10eXBlb2YgYSYmKGI9YSxhPSJmeCIsYy0tKSxhcmd1bWVudHMubGVuZ3RoPGM/bS5xdWV1ZSh0aGlzWzBdLGEpOnZvaWQgMD09PWI/dGhpczp0aGlzLmVhY2goZnVuY3Rpb24oKXt2YXIgYz1tLnF1ZXVlKHRoaXMsYSxiKTttLl9xdWV1ZUhvb2tzKHRoaXMsYSksImZ4Ij09PWEmJiJpbnByb2dyZXNzIiE9PWNbMF0mJm0uZGVxdWV1ZSh0aGlzLGEpfSl9LGRlcXVldWU6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpe20uZGVxdWV1ZSh0aGlzLGEpfSl9LGNsZWFyUXVldWU6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMucXVldWUoYXx8ImZ4IixbXSl9LHByb21pc2U6ZnVuY3Rpb24oYSxiKXt2YXIgYyxkPTEsZT1tLkRlZmVycmVkKCksZj10aGlzLGc9dGhpcy5sZW5ndGgsaD1mdW5jdGlvbigpey0tZHx8ZS5yZXNvbHZlV2l0aChmLFtmXSl9OyJzdHJpbmciIT10eXBlb2YgYSYmKGI9YSxhPXZvaWQgMCksYT1hfHwiZngiO3doaWxlKGctLSljPW0uX2RhdGEoZltnXSxhKyJxdWV1ZUhvb2tzIiksYyYmYy5lbXB0eSYmKGQrKyxjLmVtcHR5LmFkZChoKSk7cmV0dXJuIGgoKSxlLnByb21pc2UoYil9fSk7dmFyIFM9L1srLV0/KD86XGQqXC58KVxkKyg/OltlRV1bKy1dP1xkK3wpLy5zb3VyY2UsVD1bIlRvcCIsIlJpZ2h0IiwiQm90dG9tIiwiTGVmdCJdLFU9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT1ifHxhLCJub25lIj09PW0uY3NzKGEsImRpc3BsYXkiKXx8IW0uY29udGFpbnMoYS5vd25lckRvY3VtZW50LGEpfSxWPW0uYWNjZXNzPWZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciBoPTAsaT1hLmxlbmd0aCxqPW51bGw9PWM7aWYoIm9iamVjdCI9PT1tLnR5cGUoYykpe2U9ITA7Zm9yKGggaW4gYyltLmFjY2VzcyhhLGIsaCxjW2hdLCEwLGYsZyl9ZWxzZSBpZih2b2lkIDAhPT1kJiYoZT0hMCxtLmlzRnVuY3Rpb24oZCl8fChnPSEwKSxqJiYoZz8oYi5jYWxsKGEsZCksYj1udWxsKTooaj1iLGI9ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBqLmNhbGwobShhKSxjKX0pKSxiKSlmb3IoO2k+aDtoKyspYihhW2hdLGMsZz9kOmQuY2FsbChhW2hdLGgsYihhW2hdLGMpKSk7cmV0dXJuIGU/YTpqP2IuY2FsbChhKTppP2IoYVswXSxjKTpmfSxXPS9eKD86Y2hlY2tib3h8cmFkaW8pJC9pOyFmdW5jdGlvbigpe3ZhciBhPXkuY3JlYXRlRWxlbWVudCgiaW5wdXQiKSxiPXkuY3JlYXRlRWxlbWVudCgiZGl2IiksYz15LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtpZihiLmlubmVySFRNTD0iICA8bGluay8+PHRhYmxlPjwvdGFibGU+PGEgaHJlZj0nL2EnPmE8L2E+PGlucHV0IHR5cGU9J2NoZWNrYm94Jy8+IixrLmxlYWRpbmdXaGl0ZXNwYWNlPTM9PT1iLmZpcnN0Q2hpbGQubm9kZVR5cGUsay50Ym9keT0hYi5nZXRFbGVtZW50c0J5VGFnTmFtZSgidGJvZHkiKS5sZW5ndGgsay5odG1sU2VyaWFsaXplPSEhYi5nZXRFbGVtZW50c0J5VGFnTmFtZSgibGluayIpLmxlbmd0aCxrLmh0bWw1Q2xvbmU9Ijw6bmF2PjwvOm5hdj4iIT09eS5jcmVhdGVFbGVtZW50KCJuYXYiKS5jbG9uZU5vZGUoITApLm91dGVySFRNTCxhLnR5cGU9ImNoZWNrYm94IixhLmNoZWNrZWQ9ITAsYy5hcHBlbmRDaGlsZChhKSxrLmFwcGVuZENoZWNrZWQ9YS5jaGVja2VkLGIuaW5uZXJIVE1MPSI8dGV4dGFyZWE+eDwvdGV4dGFyZWE+IixrLm5vQ2xvbmVDaGVja2VkPSEhYi5jbG9uZU5vZGUoITApLmxhc3RDaGlsZC5kZWZhdWx0VmFsdWUsYy5hcHBlbmRDaGlsZChiKSxiLmlubmVySFRNTD0iPGlucHV0IHR5cGU9J3JhZGlvJyBjaGVja2VkPSdjaGVja2VkJyBuYW1lPSd0Jy8+IixrLmNoZWNrQ2xvbmU9Yi5jbG9uZU5vZGUoITApLmNsb25lTm9kZSghMCkubGFzdENoaWxkLmNoZWNrZWQsay5ub0Nsb25lRXZlbnQ9ITAsYi5hdHRhY2hFdmVudCYmKGIuYXR0YWNoRXZlbnQoIm9uY2xpY2siLGZ1bmN0aW9uKCl7ay5ub0Nsb25lRXZlbnQ9ITF9KSxiLmNsb25lTm9kZSghMCkuY2xpY2soKSksbnVsbD09ay5kZWxldGVFeHBhbmRvKXtrLmRlbGV0ZUV4cGFuZG89ITA7dHJ5e2RlbGV0ZSBiLnRlc3R9Y2F0Y2goZCl7ay5kZWxldGVFeHBhbmRvPSExfX19KCksZnVuY3Rpb24oKXt2YXIgYixjLGQ9eS5jcmVhdGVFbGVtZW50KCJkaXYiKTtmb3IoYiBpbntzdWJtaXQ6ITAsY2hhbmdlOiEwLGZvY3VzaW46ITB9KWM9Im9uIitiLChrW2IrIkJ1YmJsZXMiXT1jIGluIGEpfHwoZC5zZXRBdHRyaWJ1dGUoYywidCIpLGtbYisiQnViYmxlcyJdPWQuYXR0cmlidXRlc1tjXS5leHBhbmRvPT09ITEpO2Q9bnVsbH0oKTt2YXIgWD0vXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYSkkL2ksWT0vXmtleS8sWj0vXig/Om1vdXNlfHBvaW50ZXJ8Y29udGV4dG1lbnUpfGNsaWNrLywkPS9eKD86Zm9jdXNpbmZvY3VzfGZvY3Vzb3V0Ymx1cikkLyxfPS9eKFteLl0qKSg/OlwuKC4rKXwpJC87ZnVuY3Rpb24gYWEoKXtyZXR1cm4hMH1mdW5jdGlvbiBiYSgpe3JldHVybiExfWZ1bmN0aW9uIGNhKCl7dHJ5e3JldHVybiB5LmFjdGl2ZUVsZW1lbnR9Y2F0Y2goYSl7fX1tLmV2ZW50PXtnbG9iYWw6e30sYWRkOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIGYsZyxoLGksaixrLGwsbixvLHAscSxyPW0uX2RhdGEoYSk7aWYocil7Yy5oYW5kbGVyJiYoaT1jLGM9aS5oYW5kbGVyLGU9aS5zZWxlY3RvciksYy5ndWlkfHwoYy5ndWlkPW0uZ3VpZCsrKSwoZz1yLmV2ZW50cyl8fChnPXIuZXZlbnRzPXt9KSwoaz1yLmhhbmRsZSl8fChrPXIuaGFuZGxlPWZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgbT09PUt8fGEmJm0uZXZlbnQudHJpZ2dlcmVkPT09YS50eXBlP3ZvaWQgMDptLmV2ZW50LmRpc3BhdGNoLmFwcGx5KGsuZWxlbSxhcmd1bWVudHMpfSxrLmVsZW09YSksYj0oYnx8IiIpLm1hdGNoKEUpfHxbIiJdLGg9Yi5sZW5ndGg7d2hpbGUoaC0tKWY9Xy5leGVjKGJbaF0pfHxbXSxvPXE9ZlsxXSxwPShmWzJdfHwiIikuc3BsaXQoIi4iKS5zb3J0KCksbyYmKGo9bS5ldmVudC5zcGVjaWFsW29dfHx7fSxvPShlP2ouZGVsZWdhdGVUeXBlOmouYmluZFR5cGUpfHxvLGo9bS5ldmVudC5zcGVjaWFsW29dfHx7fSxsPW0uZXh0ZW5kKHt0eXBlOm8sb3JpZ1R5cGU6cSxkYXRhOmQsaGFuZGxlcjpjLGd1aWQ6Yy5ndWlkLHNlbGVjdG9yOmUsbmVlZHNDb250ZXh0OmUmJm0uZXhwci5tYXRjaC5uZWVkc0NvbnRleHQudGVzdChlKSxuYW1lc3BhY2U6cC5qb2luKCIuIil9LGkpLChuPWdbb10pfHwobj1nW29dPVtdLG4uZGVsZWdhdGVDb3VudD0wLGouc2V0dXAmJmouc2V0dXAuY2FsbChhLGQscCxrKSE9PSExfHwoYS5hZGRFdmVudExpc3RlbmVyP2EuYWRkRXZlbnRMaXN0ZW5lcihvLGssITEpOmEuYXR0YWNoRXZlbnQmJmEuYXR0YWNoRXZlbnQoIm9uIitvLGspKSksai5hZGQmJihqLmFkZC5jYWxsKGEsbCksbC5oYW5kbGVyLmd1aWR8fChsLmhhbmRsZXIuZ3VpZD1jLmd1aWQpKSxlP24uc3BsaWNlKG4uZGVsZWdhdGVDb3VudCsrLDAsbCk6bi5wdXNoKGwpLG0uZXZlbnQuZ2xvYmFsW29dPSEwKTthPW51bGx9fSxyZW1vdmU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgZixnLGgsaSxqLGssbCxuLG8scCxxLHI9bS5oYXNEYXRhKGEpJiZtLl9kYXRhKGEpO2lmKHImJihrPXIuZXZlbnRzKSl7Yj0oYnx8IiIpLm1hdGNoKEUpfHxbIiJdLGo9Yi5sZW5ndGg7d2hpbGUoai0tKWlmKGg9Xy5leGVjKGJbal0pfHxbXSxvPXE9aFsxXSxwPShoWzJdfHwiIikuc3BsaXQoIi4iKS5zb3J0KCksbyl7bD1tLmV2ZW50LnNwZWNpYWxbb118fHt9LG89KGQ/bC5kZWxlZ2F0ZVR5cGU6bC5iaW5kVHlwZSl8fG8sbj1rW29dfHxbXSxoPWhbMl0mJm5ldyBSZWdFeHAoIihefFxcLikiK3Auam9pbigiXFwuKD86LipcXC58KSIpKyIoXFwufCQpIiksaT1mPW4ubGVuZ3RoO3doaWxlKGYtLSlnPW5bZl0sIWUmJnEhPT1nLm9yaWdUeXBlfHxjJiZjLmd1aWQhPT1nLmd1aWR8fGgmJiFoLnRlc3QoZy5uYW1lc3BhY2UpfHxkJiZkIT09Zy5zZWxlY3RvciYmKCIqKiIhPT1kfHwhZy5zZWxlY3Rvcil8fChuLnNwbGljZShmLDEpLGcuc2VsZWN0b3ImJm4uZGVsZWdhdGVDb3VudC0tLGwucmVtb3ZlJiZsLnJlbW92ZS5jYWxsKGEsZykpO2kmJiFuLmxlbmd0aCYmKGwudGVhcmRvd24mJmwudGVhcmRvd24uY2FsbChhLHAsci5oYW5kbGUpIT09ITF8fG0ucmVtb3ZlRXZlbnQoYSxvLHIuaGFuZGxlKSxkZWxldGUga1tvXSl9ZWxzZSBmb3IobyBpbiBrKW0uZXZlbnQucmVtb3ZlKGEsbytiW2pdLGMsZCwhMCk7bS5pc0VtcHR5T2JqZWN0KGspJiYoZGVsZXRlIHIuaGFuZGxlLG0uX3JlbW92ZURhdGEoYSwiZXZlbnRzIikpfX0sdHJpZ2dlcjpmdW5jdGlvbihiLGMsZCxlKXt2YXIgZixnLGgsaSxrLGwsbixvPVtkfHx5XSxwPWouY2FsbChiLCJ0eXBlIik/Yi50eXBlOmIscT1qLmNhbGwoYiwibmFtZXNwYWNlIik/Yi5uYW1lc3BhY2Uuc3BsaXQoIi4iKTpbXTtpZihoPWw9ZD1kfHx5LDMhPT1kLm5vZGVUeXBlJiY4IT09ZC5ub2RlVHlwZSYmISQudGVzdChwK20uZXZlbnQudHJpZ2dlcmVkKSYmKHAuaW5kZXhPZigiLiIpPj0wJiYocT1wLnNwbGl0KCIuIikscD1xLnNoaWZ0KCkscS5zb3J0KCkpLGc9cC5pbmRleE9mKCI6Iik8MCYmIm9uIitwLGI9YlttLmV4cGFuZG9dP2I6bmV3IG0uRXZlbnQocCwib2JqZWN0Ij09dHlwZW9mIGImJmIpLGIuaXNUcmlnZ2VyPWU/MjozLGIubmFtZXNwYWNlPXEuam9pbigiLiIpLGIubmFtZXNwYWNlX3JlPWIubmFtZXNwYWNlP25ldyBSZWdFeHAoIihefFxcLikiK3Euam9pbigiXFwuKD86LipcXC58KSIpKyIoXFwufCQpIik6bnVsbCxiLnJlc3VsdD12b2lkIDAsYi50YXJnZXR8fChiLnRhcmdldD1kKSxjPW51bGw9PWM/W2JdOm0ubWFrZUFycmF5KGMsW2JdKSxrPW0uZXZlbnQuc3BlY2lhbFtwXXx8e30sZXx8IWsudHJpZ2dlcnx8ay50cmlnZ2VyLmFwcGx5KGQsYykhPT0hMSkpe2lmKCFlJiYhay5ub0J1YmJsZSYmIW0uaXNXaW5kb3coZCkpe2ZvcihpPWsuZGVsZWdhdGVUeXBlfHxwLCQudGVzdChpK3ApfHwoaD1oLnBhcmVudE5vZGUpO2g7aD1oLnBhcmVudE5vZGUpby5wdXNoKGgpLGw9aDtsPT09KGQub3duZXJEb2N1bWVudHx8eSkmJm8ucHVzaChsLmRlZmF1bHRWaWV3fHxsLnBhcmVudFdpbmRvd3x8YSl9bj0wO3doaWxlKChoPW9bbisrXSkmJiFiLmlzUHJvcGFnYXRpb25TdG9wcGVkKCkpYi50eXBlPW4+MT9pOmsuYmluZFR5cGV8fHAsZj0obS5fZGF0YShoLCJldmVudHMiKXx8e30pW2IudHlwZV0mJm0uX2RhdGEoaCwiaGFuZGxlIiksZiYmZi5hcHBseShoLGMpLGY9ZyYmaFtnXSxmJiZmLmFwcGx5JiZtLmFjY2VwdERhdGEoaCkmJihiLnJlc3VsdD1mLmFwcGx5KGgsYyksYi5yZXN1bHQ9PT0hMSYmYi5wcmV2ZW50RGVmYXVsdCgpKTtpZihiLnR5cGU9cCwhZSYmIWIuaXNEZWZhdWx0UHJldmVudGVkKCkmJighay5fZGVmYXVsdHx8ay5fZGVmYXVsdC5hcHBseShvLnBvcCgpLGMpPT09ITEpJiZtLmFjY2VwdERhdGEoZCkmJmcmJmRbcF0mJiFtLmlzV2luZG93KGQpKXtsPWRbZ10sbCYmKGRbZ109bnVsbCksbS5ldmVudC50cmlnZ2VyZWQ9cDt0cnl7ZFtwXSgpfWNhdGNoKHIpe31tLmV2ZW50LnRyaWdnZXJlZD12b2lkIDAsbCYmKGRbZ109bCl9cmV0dXJuIGIucmVzdWx0fX0sZGlzcGF0Y2g6ZnVuY3Rpb24oYSl7YT1tLmV2ZW50LmZpeChhKTt2YXIgYixjLGUsZixnLGg9W10saT1kLmNhbGwoYXJndW1lbnRzKSxqPShtLl9kYXRhKHRoaXMsImV2ZW50cyIpfHx7fSlbYS50eXBlXXx8W10saz1tLmV2ZW50LnNwZWNpYWxbYS50eXBlXXx8e307aWYoaVswXT1hLGEuZGVsZWdhdGVUYXJnZXQ9dGhpcywhay5wcmVEaXNwYXRjaHx8ay5wcmVEaXNwYXRjaC5jYWxsKHRoaXMsYSkhPT0hMSl7aD1tLmV2ZW50LmhhbmRsZXJzLmNhbGwodGhpcyxhLGopLGI9MDt3aGlsZSgoZj1oW2IrK10pJiYhYS5pc1Byb3BhZ2F0aW9uU3RvcHBlZCgpKXthLmN1cnJlbnRUYXJnZXQ9Zi5lbGVtLGc9MDt3aGlsZSgoZT1mLmhhbmRsZXJzW2crK10pJiYhYS5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpKSghYS5uYW1lc3BhY2VfcmV8fGEubmFtZXNwYWNlX3JlLnRlc3QoZS5uYW1lc3BhY2UpKSYmKGEuaGFuZGxlT2JqPWUsYS5kYXRhPWUuZGF0YSxjPSgobS5ldmVudC5zcGVjaWFsW2Uub3JpZ1R5cGVdfHx7fSkuaGFuZGxlfHxlLmhhbmRsZXIpLmFwcGx5KGYuZWxlbSxpKSx2b2lkIDAhPT1jJiYoYS5yZXN1bHQ9Yyk9PT0hMSYmKGEucHJldmVudERlZmF1bHQoKSxhLnN0b3BQcm9wYWdhdGlvbigpKSl9cmV0dXJuIGsucG9zdERpc3BhdGNoJiZrLnBvc3REaXNwYXRjaC5jYWxsKHRoaXMsYSksYS5yZXN1bHR9fSxoYW5kbGVyczpmdW5jdGlvbihhLGIpe3ZhciBjLGQsZSxmLGc9W10saD1iLmRlbGVnYXRlQ291bnQsaT1hLnRhcmdldDtpZihoJiZpLm5vZGVUeXBlJiYoIWEuYnV0dG9ufHwiY2xpY2siIT09YS50eXBlKSlmb3IoO2khPXRoaXM7aT1pLnBhcmVudE5vZGV8fHRoaXMpaWYoMT09PWkubm9kZVR5cGUmJihpLmRpc2FibGVkIT09ITB8fCJjbGljayIhPT1hLnR5cGUpKXtmb3IoZT1bXSxmPTA7aD5mO2YrKylkPWJbZl0sYz1kLnNlbGVjdG9yKyIgIix2b2lkIDA9PT1lW2NdJiYoZVtjXT1kLm5lZWRzQ29udGV4dD9tKGMsdGhpcykuaW5kZXgoaSk+PTA6bS5maW5kKGMsdGhpcyxudWxsLFtpXSkubGVuZ3RoKSxlW2NdJiZlLnB1c2goZCk7ZS5sZW5ndGgmJmcucHVzaCh7ZWxlbTppLGhhbmRsZXJzOmV9KX1yZXR1cm4gaDxiLmxlbmd0aCYmZy5wdXNoKHtlbGVtOnRoaXMsaGFuZGxlcnM6Yi5zbGljZShoKX0pLGd9LGZpeDpmdW5jdGlvbihhKXtpZihhW20uZXhwYW5kb10pcmV0dXJuIGE7dmFyIGIsYyxkLGU9YS50eXBlLGY9YSxnPXRoaXMuZml4SG9va3NbZV07Z3x8KHRoaXMuZml4SG9va3NbZV09Zz1aLnRlc3QoZSk/dGhpcy5tb3VzZUhvb2tzOlkudGVzdChlKT90aGlzLmtleUhvb2tzOnt9KSxkPWcucHJvcHM/dGhpcy5wcm9wcy5jb25jYXQoZy5wcm9wcyk6dGhpcy5wcm9wcyxhPW5ldyBtLkV2ZW50KGYpLGI9ZC5sZW5ndGg7d2hpbGUoYi0tKWM9ZFtiXSxhW2NdPWZbY107cmV0dXJuIGEudGFyZ2V0fHwoYS50YXJnZXQ9Zi5zcmNFbGVtZW50fHx5KSwzPT09YS50YXJnZXQubm9kZVR5cGUmJihhLnRhcmdldD1hLnRhcmdldC5wYXJlbnROb2RlKSxhLm1ldGFLZXk9ISFhLm1ldGFLZXksZy5maWx0ZXI/Zy5maWx0ZXIoYSxmKTphfSxwcm9wczoiYWx0S2V5IGJ1YmJsZXMgY2FuY2VsYWJsZSBjdHJsS2V5IGN1cnJlbnRUYXJnZXQgZXZlbnRQaGFzZSBtZXRhS2V5IHJlbGF0ZWRUYXJnZXQgc2hpZnRLZXkgdGFyZ2V0IHRpbWVTdGFtcCB2aWV3IHdoaWNoIi5zcGxpdCgiICIpLGZpeEhvb2tzOnt9LGtleUhvb2tzOntwcm9wczoiY2hhciBjaGFyQ29kZSBrZXkga2V5Q29kZSIuc3BsaXQoIiAiKSxmaWx0ZXI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbnVsbD09YS53aGljaCYmKGEud2hpY2g9bnVsbCE9Yi5jaGFyQ29kZT9iLmNoYXJDb2RlOmIua2V5Q29kZSksYX19LG1vdXNlSG9va3M6e3Byb3BzOiJidXR0b24gYnV0dG9ucyBjbGllbnRYIGNsaWVudFkgZnJvbUVsZW1lbnQgb2Zmc2V0WCBvZmZzZXRZIHBhZ2VYIHBhZ2VZIHNjcmVlblggc2NyZWVuWSB0b0VsZW1lbnQiLnNwbGl0KCIgIiksZmlsdGVyOmZ1bmN0aW9uKGEsYil7dmFyIGMsZCxlLGY9Yi5idXR0b24sZz1iLmZyb21FbGVtZW50O3JldHVybiBudWxsPT1hLnBhZ2VYJiZudWxsIT1iLmNsaWVudFgmJihkPWEudGFyZ2V0Lm93bmVyRG9jdW1lbnR8fHksZT1kLmRvY3VtZW50RWxlbWVudCxjPWQuYm9keSxhLnBhZ2VYPWIuY2xpZW50WCsoZSYmZS5zY3JvbGxMZWZ0fHxjJiZjLnNjcm9sbExlZnR8fDApLShlJiZlLmNsaWVudExlZnR8fGMmJmMuY2xpZW50TGVmdHx8MCksYS5wYWdlWT1iLmNsaWVudFkrKGUmJmUuc2Nyb2xsVG9wfHxjJiZjLnNjcm9sbFRvcHx8MCktKGUmJmUuY2xpZW50VG9wfHxjJiZjLmNsaWVudFRvcHx8MCkpLCFhLnJlbGF0ZWRUYXJnZXQmJmcmJihhLnJlbGF0ZWRUYXJnZXQ9Zz09PWEudGFyZ2V0P2IudG9FbGVtZW50OmcpLGEud2hpY2h8fHZvaWQgMD09PWZ8fChhLndoaWNoPTEmZj8xOjImZj8zOjQmZj8yOjApLGF9fSxzcGVjaWFsOntsb2FkOntub0J1YmJsZTohMH0sZm9jdXM6e3RyaWdnZXI6ZnVuY3Rpb24oKXtpZih0aGlzIT09Y2EoKSYmdGhpcy5mb2N1cyl0cnl7cmV0dXJuIHRoaXMuZm9jdXMoKSwhMX1jYXRjaChhKXt9fSxkZWxlZ2F0ZVR5cGU6ImZvY3VzaW4ifSxibHVyOnt0cmlnZ2VyOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXM9PT1jYSgpJiZ0aGlzLmJsdXI/KHRoaXMuYmx1cigpLCExKTp2b2lkIDB9LGRlbGVnYXRlVHlwZToiZm9jdXNvdXQifSxjbGljazp7dHJpZ2dlcjpmdW5jdGlvbigpe3JldHVybiBtLm5vZGVOYW1lKHRoaXMsImlucHV0IikmJiJjaGVja2JveCI9PT10aGlzLnR5cGUmJnRoaXMuY2xpY2s/KHRoaXMuY2xpY2soKSwhMSk6dm9pZCAwfSxfZGVmYXVsdDpmdW5jdGlvbihhKXtyZXR1cm4gbS5ub2RlTmFtZShhLnRhcmdldCwiYSIpfX0sYmVmb3JldW5sb2FkOntwb3N0RGlzcGF0Y2g6ZnVuY3Rpb24oYSl7dm9pZCAwIT09YS5yZXN1bHQmJmEub3JpZ2luYWxFdmVudCYmKGEub3JpZ2luYWxFdmVudC5yZXR1cm5WYWx1ZT1hLnJlc3VsdCl9fX0sc2ltdWxhdGU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bS5leHRlbmQobmV3IG0uRXZlbnQsYyx7dHlwZTphLGlzU2ltdWxhdGVkOiEwLG9yaWdpbmFsRXZlbnQ6e319KTtkP20uZXZlbnQudHJpZ2dlcihlLG51bGwsYik6bS5ldmVudC5kaXNwYXRjaC5jYWxsKGIsZSksZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSYmYy5wcmV2ZW50RGVmYXVsdCgpfX0sbS5yZW1vdmVFdmVudD15LnJlbW92ZUV2ZW50TGlzdGVuZXI/ZnVuY3Rpb24oYSxiLGMpe2EucmVtb3ZlRXZlbnRMaXN0ZW5lciYmYS5yZW1vdmVFdmVudExpc3RlbmVyKGIsYywhMSl9OmZ1bmN0aW9uKGEsYixjKXt2YXIgZD0ib24iK2I7YS5kZXRhY2hFdmVudCYmKHR5cGVvZiBhW2RdPT09SyYmKGFbZF09bnVsbCksYS5kZXRhY2hFdmVudChkLGMpKX0sbS5FdmVudD1mdW5jdGlvbihhLGIpe3JldHVybiB0aGlzIGluc3RhbmNlb2YgbS5FdmVudD8oYSYmYS50eXBlPyh0aGlzLm9yaWdpbmFsRXZlbnQ9YSx0aGlzLnR5cGU9YS50eXBlLHRoaXMuaXNEZWZhdWx0UHJldmVudGVkPWEuZGVmYXVsdFByZXZlbnRlZHx8dm9pZCAwPT09YS5kZWZhdWx0UHJldmVudGVkJiZhLnJldHVyblZhbHVlPT09ITE/YWE6YmEpOnRoaXMudHlwZT1hLGImJm0uZXh0ZW5kKHRoaXMsYiksdGhpcy50aW1lU3RhbXA9YSYmYS50aW1lU3RhbXB8fG0ubm93KCksdm9pZCh0aGlzW20uZXhwYW5kb109ITApKTpuZXcgbS5FdmVudChhLGIpfSxtLkV2ZW50LnByb3RvdHlwZT17aXNEZWZhdWx0UHJldmVudGVkOmJhLGlzUHJvcGFnYXRpb25TdG9wcGVkOmJhLGlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOmJhLHByZXZlbnREZWZhdWx0OmZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5vcmlnaW5hbEV2ZW50O3RoaXMuaXNEZWZhdWx0UHJldmVudGVkPWFhLGEmJihhLnByZXZlbnREZWZhdWx0P2EucHJldmVudERlZmF1bHQoKTphLnJldHVyblZhbHVlPSExKX0sc3RvcFByb3BhZ2F0aW9uOmZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5vcmlnaW5hbEV2ZW50O3RoaXMuaXNQcm9wYWdhdGlvblN0b3BwZWQ9YWEsYSYmKGEuc3RvcFByb3BhZ2F0aW9uJiZhLnN0b3BQcm9wYWdhdGlvbigpLGEuY2FuY2VsQnViYmxlPSEwKX0sc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uOmZ1bmN0aW9uKCl7dmFyIGE9dGhpcy5vcmlnaW5hbEV2ZW50O3RoaXMuaXNJbW1lZGlhdGVQcm9wYWdhdGlvblN0b3BwZWQ9YWEsYSYmYS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24mJmEuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCksdGhpcy5zdG9wUHJvcGFnYXRpb24oKX19LG0uZWFjaCh7bW91c2VlbnRlcjoibW91c2VvdmVyIixtb3VzZWxlYXZlOiJtb3VzZW91dCIscG9pbnRlcmVudGVyOiJwb2ludGVyb3ZlciIscG9pbnRlcmxlYXZlOiJwb2ludGVyb3V0In0sZnVuY3Rpb24oYSxiKXttLmV2ZW50LnNwZWNpYWxbYV09e2RlbGVnYXRlVHlwZTpiLGJpbmRUeXBlOmIsaGFuZGxlOmZ1bmN0aW9uKGEpe3ZhciBjLGQ9dGhpcyxlPWEucmVsYXRlZFRhcmdldCxmPWEuaGFuZGxlT2JqO3JldHVybighZXx8ZSE9PWQmJiFtLmNvbnRhaW5zKGQsZSkpJiYoYS50eXBlPWYub3JpZ1R5cGUsYz1mLmhhbmRsZXIuYXBwbHkodGhpcyxhcmd1bWVudHMpLGEudHlwZT1iKSxjfX19KSxrLnN1Ym1pdEJ1YmJsZXN8fChtLmV2ZW50LnNwZWNpYWwuc3VibWl0PXtzZXR1cDpmdW5jdGlvbigpe3JldHVybiBtLm5vZGVOYW1lKHRoaXMsImZvcm0iKT8hMTp2b2lkIG0uZXZlbnQuYWRkKHRoaXMsImNsaWNrLl9zdWJtaXQga2V5cHJlc3MuX3N1Ym1pdCIsZnVuY3Rpb24oYSl7dmFyIGI9YS50YXJnZXQsYz1tLm5vZGVOYW1lKGIsImlucHV0Iil8fG0ubm9kZU5hbWUoYiwiYnV0dG9uIik/Yi5mb3JtOnZvaWQgMDtjJiYhbS5fZGF0YShjLCJzdWJtaXRCdWJibGVzIikmJihtLmV2ZW50LmFkZChjLCJzdWJtaXQuX3N1Ym1pdCIsZnVuY3Rpb24oYSl7YS5fc3VibWl0X2J1YmJsZT0hMH0pLG0uX2RhdGEoYywic3VibWl0QnViYmxlcyIsITApKX0pfSxwb3N0RGlzcGF0Y2g6ZnVuY3Rpb24oYSl7YS5fc3VibWl0X2J1YmJsZSYmKGRlbGV0ZSBhLl9zdWJtaXRfYnViYmxlLHRoaXMucGFyZW50Tm9kZSYmIWEuaXNUcmlnZ2VyJiZtLmV2ZW50LnNpbXVsYXRlKCJzdWJtaXQiLHRoaXMucGFyZW50Tm9kZSxhLCEwKSl9LHRlYXJkb3duOmZ1bmN0aW9uKCl7cmV0dXJuIG0ubm9kZU5hbWUodGhpcywiZm9ybSIpPyExOnZvaWQgbS5ldmVudC5yZW1vdmUodGhpcywiLl9zdWJtaXQiKX19KSxrLmNoYW5nZUJ1YmJsZXN8fChtLmV2ZW50LnNwZWNpYWwuY2hhbmdlPXtzZXR1cDpmdW5jdGlvbigpe3JldHVybiBYLnRlc3QodGhpcy5ub2RlTmFtZSk/KCgiY2hlY2tib3giPT09dGhpcy50eXBlfHwicmFkaW8iPT09dGhpcy50eXBlKSYmKG0uZXZlbnQuYWRkKHRoaXMsInByb3BlcnR5Y2hhbmdlLl9jaGFuZ2UiLGZ1bmN0aW9uKGEpeyJjaGVja2VkIj09PWEub3JpZ2luYWxFdmVudC5wcm9wZXJ0eU5hbWUmJih0aGlzLl9qdXN0X2NoYW5nZWQ9ITApfSksbS5ldmVudC5hZGQodGhpcywiY2xpY2suX2NoYW5nZSIsZnVuY3Rpb24oYSl7dGhpcy5fanVzdF9jaGFuZ2VkJiYhYS5pc1RyaWdnZXImJih0aGlzLl9qdXN0X2NoYW5nZWQ9ITEpLG0uZXZlbnQuc2ltdWxhdGUoImNoYW5nZSIsdGhpcyxhLCEwKX0pKSwhMSk6dm9pZCBtLmV2ZW50LmFkZCh0aGlzLCJiZWZvcmVhY3RpdmF0ZS5fY2hhbmdlIixmdW5jdGlvbihhKXt2YXIgYj1hLnRhcmdldDtYLnRlc3QoYi5ub2RlTmFtZSkmJiFtLl9kYXRhKGIsImNoYW5nZUJ1YmJsZXMiKSYmKG0uZXZlbnQuYWRkKGIsImNoYW5nZS5fY2hhbmdlIixmdW5jdGlvbihhKXshdGhpcy5wYXJlbnROb2RlfHxhLmlzU2ltdWxhdGVkfHxhLmlzVHJpZ2dlcnx8bS5ldmVudC5zaW11bGF0ZSgiY2hhbmdlIix0aGlzLnBhcmVudE5vZGUsYSwhMCl9KSxtLl9kYXRhKGIsImNoYW5nZUJ1YmJsZXMiLCEwKSl9KX0saGFuZGxlOmZ1bmN0aW9uKGEpe3ZhciBiPWEudGFyZ2V0O3JldHVybiB0aGlzIT09Ynx8YS5pc1NpbXVsYXRlZHx8YS5pc1RyaWdnZXJ8fCJyYWRpbyIhPT1iLnR5cGUmJiJjaGVja2JveCIhPT1iLnR5cGU/YS5oYW5kbGVPYmouaGFuZGxlci5hcHBseSh0aGlzLGFyZ3VtZW50cyk6dm9pZCAwfSx0ZWFyZG93bjpmdW5jdGlvbigpe3JldHVybiBtLmV2ZW50LnJlbW92ZSh0aGlzLCIuX2NoYW5nZSIpLCFYLnRlc3QodGhpcy5ub2RlTmFtZSl9fSksay5mb2N1c2luQnViYmxlc3x8bS5lYWNoKHtmb2N1czoiZm9jdXNpbiIsYmx1cjoiZm9jdXNvdXQifSxmdW5jdGlvbihhLGIpe3ZhciBjPWZ1bmN0aW9uKGEpe20uZXZlbnQuc2ltdWxhdGUoYixhLnRhcmdldCxtLmV2ZW50LmZpeChhKSwhMCl9O20uZXZlbnQuc3BlY2lhbFtiXT17c2V0dXA6ZnVuY3Rpb24oKXt2YXIgZD10aGlzLm93bmVyRG9jdW1lbnR8fHRoaXMsZT1tLl9kYXRhKGQsYik7ZXx8ZC5hZGRFdmVudExpc3RlbmVyKGEsYywhMCksbS5fZGF0YShkLGIsKGV8fDApKzEpfSx0ZWFyZG93bjpmdW5jdGlvbigpe3ZhciBkPXRoaXMub3duZXJEb2N1bWVudHx8dGhpcyxlPW0uX2RhdGEoZCxiKS0xO2U/bS5fZGF0YShkLGIsZSk6KGQucmVtb3ZlRXZlbnRMaXN0ZW5lcihhLGMsITApLG0uX3JlbW92ZURhdGEoZCxiKSl9fX0pLG0uZm4uZXh0ZW5kKHtvbjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBmLGc7aWYoIm9iamVjdCI9PXR5cGVvZiBhKXsic3RyaW5nIiE9dHlwZW9mIGImJihjPWN8fGIsYj12b2lkIDApO2ZvcihmIGluIGEpdGhpcy5vbihmLGIsYyxhW2ZdLGUpO3JldHVybiB0aGlzfWlmKG51bGw9PWMmJm51bGw9PWQ/KGQ9YixjPWI9dm9pZCAwKTpudWxsPT1kJiYoInN0cmluZyI9PXR5cGVvZiBiPyhkPWMsYz12b2lkIDApOihkPWMsYz1iLGI9dm9pZCAwKSksZD09PSExKWQ9YmE7ZWxzZSBpZighZClyZXR1cm4gdGhpcztyZXR1cm4gMT09PWUmJihnPWQsZD1mdW5jdGlvbihhKXtyZXR1cm4gbSgpLm9mZihhKSxnLmFwcGx5KHRoaXMsYXJndW1lbnRzKX0sZC5ndWlkPWcuZ3VpZHx8KGcuZ3VpZD1tLmd1aWQrKykpLHRoaXMuZWFjaChmdW5jdGlvbigpe20uZXZlbnQuYWRkKHRoaXMsYSxkLGMsYil9KX0sb25lOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiB0aGlzLm9uKGEsYixjLGQsMSl9LG9mZjpmdW5jdGlvbihhLGIsYyl7dmFyIGQsZTtpZihhJiZhLnByZXZlbnREZWZhdWx0JiZhLmhhbmRsZU9iailyZXR1cm4gZD1hLmhhbmRsZU9iaixtKGEuZGVsZWdhdGVUYXJnZXQpLm9mZihkLm5hbWVzcGFjZT9kLm9yaWdUeXBlKyIuIitkLm5hbWVzcGFjZTpkLm9yaWdUeXBlLGQuc2VsZWN0b3IsZC5oYW5kbGVyKSx0aGlzO2lmKCJvYmplY3QiPT10eXBlb2YgYSl7Zm9yKGUgaW4gYSl0aGlzLm9mZihlLGIsYVtlXSk7cmV0dXJuIHRoaXN9cmV0dXJuKGI9PT0hMXx8ImZ1bmN0aW9uIj09dHlwZW9mIGIpJiYoYz1iLGI9dm9pZCAwKSxjPT09ITEmJihjPWJhKSx0aGlzLmVhY2goZnVuY3Rpb24oKXttLmV2ZW50LnJlbW92ZSh0aGlzLGEsYyxiKX0pfSx0cmlnZ2VyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpe20uZXZlbnQudHJpZ2dlcihhLGIsdGhpcyl9KX0sdHJpZ2dlckhhbmRsZXI6ZnVuY3Rpb24oYSxiKXt2YXIgYz10aGlzWzBdO3JldHVybiBjP20uZXZlbnQudHJpZ2dlcihhLGIsYywhMCk6dm9pZCAwfX0pO2Z1bmN0aW9uIGRhKGEpe3ZhciBiPWVhLnNwbGl0KCJ8IiksYz1hLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtpZihjLmNyZWF0ZUVsZW1lbnQpd2hpbGUoYi5sZW5ndGgpYy5jcmVhdGVFbGVtZW50KGIucG9wKCkpO3JldHVybiBjfXZhciBlYT0iYWJicnxhcnRpY2xlfGFzaWRlfGF1ZGlvfGJkaXxjYW52YXN8ZGF0YXxkYXRhbGlzdHxkZXRhaWxzfGZpZ2NhcHRpb258ZmlndXJlfGZvb3RlcnxoZWFkZXJ8aGdyb3VwfG1hcmt8bWV0ZXJ8bmF2fG91dHB1dHxwcm9ncmVzc3xzZWN0aW9ufHN1bW1hcnl8dGltZXx2aWRlbyIsZmE9LyBqUXVlcnlcZCs9Iig/Om51bGx8XGQrKSIvZyxnYT1uZXcgUmVnRXhwKCI8KD86IitlYSsiKVtcXHMvPl0iLCJpIiksaGE9L15ccysvLGlhPS88KD8hYXJlYXxicnxjb2x8ZW1iZWR8aHJ8aW1nfGlucHV0fGxpbmt8bWV0YXxwYXJhbSkoKFtcdzpdKylbXj5dKilcLz4vZ2ksamE9LzwoW1x3Ol0rKS8sa2E9Lzx0Ym9keS9pLGxhPS88fCYjP1x3KzsvLG1hPS88KD86c2NyaXB0fHN0eWxlfGxpbmspL2ksbmE9L2NoZWNrZWRccyooPzpbXj1dfD1ccyouY2hlY2tlZC4pL2ksb2E9L14kfFwvKD86amF2YXxlY21hKXNjcmlwdC9pLHBhPS9edHJ1ZVwvKC4qKS8scWE9L15ccyo8ISg/OlxbQ0RBVEFcW3wtLSl8KD86XF1cXXwtLSk+XHMqJC9nLHJhPXtvcHRpb246WzEsIjxzZWxlY3QgbXVsdGlwbGU9J211bHRpcGxlJz4iLCI8L3NlbGVjdD4iXSxsZWdlbmQ6WzEsIjxmaWVsZHNldD4iLCI8L2ZpZWxkc2V0PiJdLGFyZWE6WzEsIjxtYXA+IiwiPC9tYXA+Il0scGFyYW06WzEsIjxvYmplY3Q+IiwiPC9vYmplY3Q+Il0sdGhlYWQ6WzEsIjx0YWJsZT4iLCI8L3RhYmxlPiJdLHRyOlsyLCI8dGFibGU+PHRib2R5PiIsIjwvdGJvZHk+PC90YWJsZT4iXSxjb2w6WzIsIjx0YWJsZT48dGJvZHk+PC90Ym9keT48Y29sZ3JvdXA+IiwiPC9jb2xncm91cD48L3RhYmxlPiJdLHRkOlszLCI8dGFibGU+PHRib2R5Pjx0cj4iLCI8L3RyPjwvdGJvZHk+PC90YWJsZT4iXSxfZGVmYXVsdDprLmh0bWxTZXJpYWxpemU/WzAsIiIsIiJdOlsxLCJYPGRpdj4iLCI8L2Rpdj4iXX0sc2E9ZGEoeSksdGE9c2EuYXBwZW5kQ2hpbGQoeS5jcmVhdGVFbGVtZW50KCJkaXYiKSk7cmEub3B0Z3JvdXA9cmEub3B0aW9uLHJhLnRib2R5PXJhLnRmb290PXJhLmNvbGdyb3VwPXJhLmNhcHRpb249cmEudGhlYWQscmEudGg9cmEudGQ7ZnVuY3Rpb24gdWEoYSxiKXt2YXIgYyxkLGU9MCxmPXR5cGVvZiBhLmdldEVsZW1lbnRzQnlUYWdOYW1lIT09Sz9hLmdldEVsZW1lbnRzQnlUYWdOYW1lKGJ8fCIqIik6dHlwZW9mIGEucXVlcnlTZWxlY3RvckFsbCE9PUs/YS5xdWVyeVNlbGVjdG9yQWxsKGJ8fCIqIik6dm9pZCAwO2lmKCFmKWZvcihmPVtdLGM9YS5jaGlsZE5vZGVzfHxhO251bGwhPShkPWNbZV0pO2UrKykhYnx8bS5ub2RlTmFtZShkLGIpP2YucHVzaChkKTptLm1lcmdlKGYsdWEoZCxiKSk7cmV0dXJuIHZvaWQgMD09PWJ8fGImJm0ubm9kZU5hbWUoYSxiKT9tLm1lcmdlKFthXSxmKTpmfWZ1bmN0aW9uIHZhKGEpe1cudGVzdChhLnR5cGUpJiYoYS5kZWZhdWx0Q2hlY2tlZD1hLmNoZWNrZWQpfWZ1bmN0aW9uIHdhKGEsYil7cmV0dXJuIG0ubm9kZU5hbWUoYSwidGFibGUiKSYmbS5ub2RlTmFtZSgxMSE9PWIubm9kZVR5cGU/YjpiLmZpcnN0Q2hpbGQsInRyIik/YS5nZXRFbGVtZW50c0J5VGFnTmFtZSgidGJvZHkiKVswXXx8YS5hcHBlbmRDaGlsZChhLm93bmVyRG9jdW1lbnQuY3JlYXRlRWxlbWVudCgidGJvZHkiKSk6YX1mdW5jdGlvbiB4YShhKXtyZXR1cm4gYS50eXBlPShudWxsIT09bS5maW5kLmF0dHIoYSwidHlwZSIpKSsiLyIrYS50eXBlLGF9ZnVuY3Rpb24geWEoYSl7dmFyIGI9cGEuZXhlYyhhLnR5cGUpO3JldHVybiBiP2EudHlwZT1iWzFdOmEucmVtb3ZlQXR0cmlidXRlKCJ0eXBlIiksYX1mdW5jdGlvbiB6YShhLGIpe2Zvcih2YXIgYyxkPTA7bnVsbCE9KGM9YVtkXSk7ZCsrKW0uX2RhdGEoYywiZ2xvYmFsRXZhbCIsIWJ8fG0uX2RhdGEoYltkXSwiZ2xvYmFsRXZhbCIpKX1mdW5jdGlvbiBBYShhLGIpe2lmKDE9PT1iLm5vZGVUeXBlJiZtLmhhc0RhdGEoYSkpe3ZhciBjLGQsZSxmPW0uX2RhdGEoYSksZz1tLl9kYXRhKGIsZiksaD1mLmV2ZW50cztpZihoKXtkZWxldGUgZy5oYW5kbGUsZy5ldmVudHM9e307Zm9yKGMgaW4gaClmb3IoZD0wLGU9aFtjXS5sZW5ndGg7ZT5kO2QrKyltLmV2ZW50LmFkZChiLGMsaFtjXVtkXSl9Zy5kYXRhJiYoZy5kYXRhPW0uZXh0ZW5kKHt9LGcuZGF0YSkpfX1mdW5jdGlvbiBCYShhLGIpe3ZhciBjLGQsZTtpZigxPT09Yi5ub2RlVHlwZSl7aWYoYz1iLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksIWsubm9DbG9uZUV2ZW50JiZiW20uZXhwYW5kb10pe2U9bS5fZGF0YShiKTtmb3IoZCBpbiBlLmV2ZW50cyltLnJlbW92ZUV2ZW50KGIsZCxlLmhhbmRsZSk7Yi5yZW1vdmVBdHRyaWJ1dGUobS5leHBhbmRvKX0ic2NyaXB0Ij09PWMmJmIudGV4dCE9PWEudGV4dD8oeGEoYikudGV4dD1hLnRleHQseWEoYikpOiJvYmplY3QiPT09Yz8oYi5wYXJlbnROb2RlJiYoYi5vdXRlckhUTUw9YS5vdXRlckhUTUwpLGsuaHRtbDVDbG9uZSYmYS5pbm5lckhUTUwmJiFtLnRyaW0oYi5pbm5lckhUTUwpJiYoYi5pbm5lckhUTUw9YS5pbm5lckhUTUwpKToiaW5wdXQiPT09YyYmVy50ZXN0KGEudHlwZSk/KGIuZGVmYXVsdENoZWNrZWQ9Yi5jaGVja2VkPWEuY2hlY2tlZCxiLnZhbHVlIT09YS52YWx1ZSYmKGIudmFsdWU9YS52YWx1ZSkpOiJvcHRpb24iPT09Yz9iLmRlZmF1bHRTZWxlY3RlZD1iLnNlbGVjdGVkPWEuZGVmYXVsdFNlbGVjdGVkOigiaW5wdXQiPT09Y3x8InRleHRhcmVhIj09PWMpJiYoYi5kZWZhdWx0VmFsdWU9YS5kZWZhdWx0VmFsdWUpfX1tLmV4dGVuZCh7Y2xvbmU6ZnVuY3Rpb24oYSxiLGMpe3ZhciBkLGUsZixnLGgsaT1tLmNvbnRhaW5zKGEub3duZXJEb2N1bWVudCxhKTtpZihrLmh0bWw1Q2xvbmV8fG0uaXNYTUxEb2MoYSl8fCFnYS50ZXN0KCI8IithLm5vZGVOYW1lKyI+Iik/Zj1hLmNsb25lTm9kZSghMCk6KHRhLmlubmVySFRNTD1hLm91dGVySFRNTCx0YS5yZW1vdmVDaGlsZChmPXRhLmZpcnN0Q2hpbGQpKSwhKGsubm9DbG9uZUV2ZW50JiZrLm5vQ2xvbmVDaGVja2VkfHwxIT09YS5ub2RlVHlwZSYmMTEhPT1hLm5vZGVUeXBlfHxtLmlzWE1MRG9jKGEpKSlmb3IoZD11YShmKSxoPXVhKGEpLGc9MDtudWxsIT0oZT1oW2ddKTsrK2cpZFtnXSYmQmEoZSxkW2ddKTtpZihiKWlmKGMpZm9yKGg9aHx8dWEoYSksZD1kfHx1YShmKSxnPTA7bnVsbCE9KGU9aFtnXSk7ZysrKUFhKGUsZFtnXSk7ZWxzZSBBYShhLGYpO3JldHVybiBkPXVhKGYsInNjcmlwdCIpLGQubGVuZ3RoPjAmJnphKGQsIWkmJnVhKGEsInNjcmlwdCIpKSxkPWg9ZT1udWxsLGZ9LGJ1aWxkRnJhZ21lbnQ6ZnVuY3Rpb24oYSxiLGMsZCl7Zm9yKHZhciBlLGYsZyxoLGksaixsLG49YS5sZW5ndGgsbz1kYShiKSxwPVtdLHE9MDtuPnE7cSsrKWlmKGY9YVtxXSxmfHwwPT09ZilpZigib2JqZWN0Ij09PW0udHlwZShmKSltLm1lcmdlKHAsZi5ub2RlVHlwZT9bZl06Zik7ZWxzZSBpZihsYS50ZXN0KGYpKXtoPWh8fG8uYXBwZW5kQ2hpbGQoYi5jcmVhdGVFbGVtZW50KCJkaXYiKSksaT0oamEuZXhlYyhmKXx8WyIiLCIiXSlbMV0udG9Mb3dlckNhc2UoKSxsPXJhW2ldfHxyYS5fZGVmYXVsdCxoLmlubmVySFRNTD1sWzFdK2YucmVwbGFjZShpYSwiPCQxPjwvJDI+IikrbFsyXSxlPWxbMF07d2hpbGUoZS0tKWg9aC5sYXN0Q2hpbGQ7aWYoIWsubGVhZGluZ1doaXRlc3BhY2UmJmhhLnRlc3QoZikmJnAucHVzaChiLmNyZWF0ZVRleHROb2RlKGhhLmV4ZWMoZilbMF0pKSwhay50Ym9keSl7Zj0idGFibGUiIT09aXx8a2EudGVzdChmKT8iPHRhYmxlPiIhPT1sWzFdfHxrYS50ZXN0KGYpPzA6aDpoLmZpcnN0Q2hpbGQsZT1mJiZmLmNoaWxkTm9kZXMubGVuZ3RoO3doaWxlKGUtLSltLm5vZGVOYW1lKGo9Zi5jaGlsZE5vZGVzW2VdLCJ0Ym9keSIpJiYhai5jaGlsZE5vZGVzLmxlbmd0aCYmZi5yZW1vdmVDaGlsZChqKX1tLm1lcmdlKHAsaC5jaGlsZE5vZGVzKSxoLnRleHRDb250ZW50PSIiO3doaWxlKGguZmlyc3RDaGlsZCloLnJlbW92ZUNoaWxkKGguZmlyc3RDaGlsZCk7aD1vLmxhc3RDaGlsZH1lbHNlIHAucHVzaChiLmNyZWF0ZVRleHROb2RlKGYpKTtoJiZvLnJlbW92ZUNoaWxkKGgpLGsuYXBwZW5kQ2hlY2tlZHx8bS5ncmVwKHVhKHAsImlucHV0IiksdmEpLHE9MDt3aGlsZShmPXBbcSsrXSlpZigoIWR8fC0xPT09bS5pbkFycmF5KGYsZCkpJiYoZz1tLmNvbnRhaW5zKGYub3duZXJEb2N1bWVudCxmKSxoPXVhKG8uYXBwZW5kQ2hpbGQoZiksInNjcmlwdCIpLGcmJnphKGgpLGMpKXtlPTA7d2hpbGUoZj1oW2UrK10pb2EudGVzdChmLnR5cGV8fCIiKSYmYy5wdXNoKGYpfXJldHVybiBoPW51bGwsb30sY2xlYW5EYXRhOmZ1bmN0aW9uKGEsYil7Zm9yKHZhciBkLGUsZixnLGg9MCxpPW0uZXhwYW5kbyxqPW0uY2FjaGUsbD1rLmRlbGV0ZUV4cGFuZG8sbj1tLmV2ZW50LnNwZWNpYWw7bnVsbCE9KGQ9YVtoXSk7aCsrKWlmKChifHxtLmFjY2VwdERhdGEoZCkpJiYoZj1kW2ldLGc9ZiYmaltmXSkpe2lmKGcuZXZlbnRzKWZvcihlIGluIGcuZXZlbnRzKW5bZV0/bS5ldmVudC5yZW1vdmUoZCxlKTptLnJlbW92ZUV2ZW50KGQsZSxnLmhhbmRsZSk7altmXSYmKGRlbGV0ZSBqW2ZdLGw/ZGVsZXRlIGRbaV06dHlwZW9mIGQucmVtb3ZlQXR0cmlidXRlIT09Sz9kLnJlbW92ZUF0dHJpYnV0ZShpKTpkW2ldPW51bGwsYy5wdXNoKGYpKX19fSksbS5mbi5leHRlbmQoe3RleHQ6ZnVuY3Rpb24oYSl7cmV0dXJuIFYodGhpcyxmdW5jdGlvbihhKXtyZXR1cm4gdm9pZCAwPT09YT9tLnRleHQodGhpcyk6dGhpcy5lbXB0eSgpLmFwcGVuZCgodGhpc1swXSYmdGhpc1swXS5vd25lckRvY3VtZW50fHx5KS5jcmVhdGVUZXh0Tm9kZShhKSl9LG51bGwsYSxhcmd1bWVudHMubGVuZ3RoKX0sYXBwZW5kOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZG9tTWFuaXAoYXJndW1lbnRzLGZ1bmN0aW9uKGEpe2lmKDE9PT10aGlzLm5vZGVUeXBlfHwxMT09PXRoaXMubm9kZVR5cGV8fDk9PT10aGlzLm5vZGVUeXBlKXt2YXIgYj13YSh0aGlzLGEpO2IuYXBwZW5kQ2hpbGQoYSl9fSl9LHByZXBlbmQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsZnVuY3Rpb24oYSl7aWYoMT09PXRoaXMubm9kZVR5cGV8fDExPT09dGhpcy5ub2RlVHlwZXx8OT09PXRoaXMubm9kZVR5cGUpe3ZhciBiPXdhKHRoaXMsYSk7Yi5pbnNlcnRCZWZvcmUoYSxiLmZpcnN0Q2hpbGQpfX0pfSxiZWZvcmU6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsZnVuY3Rpb24oYSl7dGhpcy5wYXJlbnROb2RlJiZ0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsdGhpcyl9KX0sYWZ0ZXI6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsZnVuY3Rpb24oYSl7dGhpcy5wYXJlbnROb2RlJiZ0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsdGhpcy5uZXh0U2libGluZyl9KX0scmVtb3ZlOmZ1bmN0aW9uKGEsYil7Zm9yKHZhciBjLGQ9YT9tLmZpbHRlcihhLHRoaXMpOnRoaXMsZT0wO251bGwhPShjPWRbZV0pO2UrKylifHwxIT09Yy5ub2RlVHlwZXx8bS5jbGVhbkRhdGEodWEoYykpLGMucGFyZW50Tm9kZSYmKGImJm0uY29udGFpbnMoYy5vd25lckRvY3VtZW50LGMpJiZ6YSh1YShjLCJzY3JpcHQiKSksYy5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGMpKTtyZXR1cm4gdGhpc30sZW1wdHk6ZnVuY3Rpb24oKXtmb3IodmFyIGEsYj0wO251bGwhPShhPXRoaXNbYl0pO2IrKyl7MT09PWEubm9kZVR5cGUmJm0uY2xlYW5EYXRhKHVhKGEsITEpKTt3aGlsZShhLmZpcnN0Q2hpbGQpYS5yZW1vdmVDaGlsZChhLmZpcnN0Q2hpbGQpO2Eub3B0aW9ucyYmbS5ub2RlTmFtZShhLCJzZWxlY3QiKSYmKGEub3B0aW9ucy5sZW5ndGg9MCl9cmV0dXJuIHRoaXN9LGNsb25lOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9bnVsbD09YT8hMTphLGI9bnVsbD09Yj9hOmIsdGhpcy5tYXAoZnVuY3Rpb24oKXtyZXR1cm4gbS5jbG9uZSh0aGlzLGEsYil9KX0saHRtbDpmdW5jdGlvbihhKXtyZXR1cm4gVih0aGlzLGZ1bmN0aW9uKGEpe3ZhciBiPXRoaXNbMF18fHt9LGM9MCxkPXRoaXMubGVuZ3RoO2lmKHZvaWQgMD09PWEpcmV0dXJuIDE9PT1iLm5vZGVUeXBlP2IuaW5uZXJIVE1MLnJlcGxhY2UoZmEsIiIpOnZvaWQgMDtpZighKCJzdHJpbmciIT10eXBlb2YgYXx8bWEudGVzdChhKXx8IWsuaHRtbFNlcmlhbGl6ZSYmZ2EudGVzdChhKXx8IWsubGVhZGluZ1doaXRlc3BhY2UmJmhhLnRlc3QoYSl8fHJhWyhqYS5leGVjKGEpfHxbIiIsIiJdKVsxXS50b0xvd2VyQ2FzZSgpXSkpe2E9YS5yZXBsYWNlKGlhLCI8JDE+PC8kMj4iKTt0cnl7Zm9yKDtkPmM7YysrKWI9dGhpc1tjXXx8e30sMT09PWIubm9kZVR5cGUmJihtLmNsZWFuRGF0YSh1YShiLCExKSksYi5pbm5lckhUTUw9YSk7Yj0wfWNhdGNoKGUpe319YiYmdGhpcy5lbXB0eSgpLmFwcGVuZChhKX0sbnVsbCxhLGFyZ3VtZW50cy5sZW5ndGgpfSxyZXBsYWNlV2l0aDpmdW5jdGlvbigpe3ZhciBhPWFyZ3VtZW50c1swXTtyZXR1cm4gdGhpcy5kb21NYW5pcChhcmd1bWVudHMsZnVuY3Rpb24oYil7YT10aGlzLnBhcmVudE5vZGUsbS5jbGVhbkRhdGEodWEodGhpcykpLGEmJmEucmVwbGFjZUNoaWxkKGIsdGhpcyl9KSxhJiYoYS5sZW5ndGh8fGEubm9kZVR5cGUpP3RoaXM6dGhpcy5yZW1vdmUoKX0sZGV0YWNoOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnJlbW92ZShhLCEwKX0sZG9tTWFuaXA6ZnVuY3Rpb24oYSxiKXthPWUuYXBwbHkoW10sYSk7dmFyIGMsZCxmLGcsaCxpLGo9MCxsPXRoaXMubGVuZ3RoLG49dGhpcyxvPWwtMSxwPWFbMF0scT1tLmlzRnVuY3Rpb24ocCk7aWYocXx8bD4xJiYic3RyaW5nIj09dHlwZW9mIHAmJiFrLmNoZWNrQ2xvbmUmJm5hLnRlc3QocCkpcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihjKXt2YXIgZD1uLmVxKGMpO3EmJihhWzBdPXAuY2FsbCh0aGlzLGMsZC5odG1sKCkpKSxkLmRvbU1hbmlwKGEsYil9KTtpZihsJiYoaT1tLmJ1aWxkRnJhZ21lbnQoYSx0aGlzWzBdLm93bmVyRG9jdW1lbnQsITEsdGhpcyksYz1pLmZpcnN0Q2hpbGQsMT09PWkuY2hpbGROb2Rlcy5sZW5ndGgmJihpPWMpLGMpKXtmb3IoZz1tLm1hcCh1YShpLCJzY3JpcHQiKSx4YSksZj1nLmxlbmd0aDtsPmo7aisrKWQ9aSxqIT09byYmKGQ9bS5jbG9uZShkLCEwLCEwKSxmJiZtLm1lcmdlKGcsdWEoZCwic2NyaXB0IikpKSxiLmNhbGwodGhpc1tqXSxkLGopO2lmKGYpZm9yKGg9Z1tnLmxlbmd0aC0xXS5vd25lckRvY3VtZW50LG0ubWFwKGcseWEpLGo9MDtmPmo7aisrKWQ9Z1tqXSxvYS50ZXN0KGQudHlwZXx8IiIpJiYhbS5fZGF0YShkLCJnbG9iYWxFdmFsIikmJm0uY29udGFpbnMoaCxkKSYmKGQuc3JjP20uX2V2YWxVcmwmJm0uX2V2YWxVcmwoZC5zcmMpOm0uZ2xvYmFsRXZhbCgoZC50ZXh0fHxkLnRleHRDb250ZW50fHxkLmlubmVySFRNTHx8IiIpLnJlcGxhY2UocWEsIiIpKSk7aT1jPW51bGx9cmV0dXJuIHRoaXN9fSksbS5lYWNoKHthcHBlbmRUbzoiYXBwZW5kIixwcmVwZW5kVG86InByZXBlbmQiLGluc2VydEJlZm9yZToiYmVmb3JlIixpbnNlcnRBZnRlcjoiYWZ0ZXIiLHJlcGxhY2VBbGw6InJlcGxhY2VXaXRoIn0sZnVuY3Rpb24oYSxiKXttLmZuW2FdPWZ1bmN0aW9uKGEpe2Zvcih2YXIgYyxkPTAsZT1bXSxnPW0oYSksaD1nLmxlbmd0aC0xO2g+PWQ7ZCsrKWM9ZD09PWg/dGhpczp0aGlzLmNsb25lKCEwKSxtKGdbZF0pW2JdKGMpLGYuYXBwbHkoZSxjLmdldCgpKTtyZXR1cm4gdGhpcy5wdXNoU3RhY2soZSl9fSk7dmFyIENhLERhPXt9O2Z1bmN0aW9uIEVhKGIsYyl7dmFyIGQsZT1tKGMuY3JlYXRlRWxlbWVudChiKSkuYXBwZW5kVG8oYy5ib2R5KSxmPWEuZ2V0RGVmYXVsdENvbXB1dGVkU3R5bGUmJihkPWEuZ2V0RGVmYXVsdENvbXB1dGVkU3R5bGUoZVswXSkpP2QuZGlzcGxheTptLmNzcyhlWzBdLCJkaXNwbGF5Iik7cmV0dXJuIGUuZGV0YWNoKCksZn1mdW5jdGlvbiBGYShhKXt2YXIgYj15LGM9RGFbYV07cmV0dXJuIGN8fChjPUVhKGEsYiksIm5vbmUiIT09YyYmY3x8KENhPShDYXx8bSgiPGlmcmFtZSBmcmFtZWJvcmRlcj0nMCcgd2lkdGg9JzAnIGhlaWdodD0nMCcvPiIpKS5hcHBlbmRUbyhiLmRvY3VtZW50RWxlbWVudCksYj0oQ2FbMF0uY29udGVudFdpbmRvd3x8Q2FbMF0uY29udGVudERvY3VtZW50KS5kb2N1bWVudCxiLndyaXRlKCksYi5jbG9zZSgpLGM9RWEoYSxiKSxDYS5kZXRhY2goKSksRGFbYV09YyksY30hZnVuY3Rpb24oKXt2YXIgYTtrLnNocmlua1dyYXBCbG9ja3M9ZnVuY3Rpb24oKXtpZihudWxsIT1hKXJldHVybiBhO2E9ITE7dmFyIGIsYyxkO3JldHVybiBjPXkuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImJvZHkiKVswXSxjJiZjLnN0eWxlPyhiPXkuY3JlYXRlRWxlbWVudCgiZGl2IiksZD15LmNyZWF0ZUVsZW1lbnQoImRpdiIpLGQuc3R5bGUuY3NzVGV4dD0icG9zaXRpb246YWJzb2x1dGU7Ym9yZGVyOjA7d2lkdGg6MDtoZWlnaHQ6MDt0b3A6MDtsZWZ0Oi05OTk5cHgiLGMuYXBwZW5kQ2hpbGQoZCkuYXBwZW5kQ2hpbGQoYiksdHlwZW9mIGIuc3R5bGUuem9vbSE9PUsmJihiLnN0eWxlLmNzc1RleHQ9Ii13ZWJraXQtYm94LXNpemluZzpjb250ZW50LWJveDstbW96LWJveC1zaXppbmc6Y29udGVudC1ib3g7Ym94LXNpemluZzpjb250ZW50LWJveDtkaXNwbGF5OmJsb2NrO21hcmdpbjowO2JvcmRlcjowO3BhZGRpbmc6MXB4O3dpZHRoOjFweDt6b29tOjEiLGIuYXBwZW5kQ2hpbGQoeS5jcmVhdGVFbGVtZW50KCJkaXYiKSkuc3R5bGUud2lkdGg9IjVweCIsYT0zIT09Yi5vZmZzZXRXaWR0aCksYy5yZW1vdmVDaGlsZChkKSxhKTp2b2lkIDB9fSgpO3ZhciBHYT0vXm1hcmdpbi8sSGE9bmV3IFJlZ0V4cCgiXigiK1MrIikoPyFweClbYS16JV0rJCIsImkiKSxJYSxKYSxLYT0vXih0b3B8cmlnaHR8Ym90dG9tfGxlZnQpJC87YS5nZXRDb21wdXRlZFN0eWxlPyhJYT1mdW5jdGlvbihiKXtyZXR1cm4gYi5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3Lm9wZW5lcj9iLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShiLG51bGwpOmEuZ2V0Q29tcHV0ZWRTdHlsZShiLG51bGwpfSxKYT1mdW5jdGlvbihhLGIsYyl7dmFyIGQsZSxmLGcsaD1hLnN0eWxlO3JldHVybiBjPWN8fElhKGEpLGc9Yz9jLmdldFByb3BlcnR5VmFsdWUoYil8fGNbYl06dm9pZCAwLGMmJigiIiE9PWd8fG0uY29udGFpbnMoYS5vd25lckRvY3VtZW50LGEpfHwoZz1tLnN0eWxlKGEsYikpLEhhLnRlc3QoZykmJkdhLnRlc3QoYikmJihkPWgud2lkdGgsZT1oLm1pbldpZHRoLGY9aC5tYXhXaWR0aCxoLm1pbldpZHRoPWgubWF4V2lkdGg9aC53aWR0aD1nLGc9Yy53aWR0aCxoLndpZHRoPWQsaC5taW5XaWR0aD1lLGgubWF4V2lkdGg9ZikpLHZvaWQgMD09PWc/ZzpnKyIifSk6eS5kb2N1bWVudEVsZW1lbnQuY3VycmVudFN0eWxlJiYoSWE9ZnVuY3Rpb24oYSl7cmV0dXJuIGEuY3VycmVudFN0eWxlfSxKYT1mdW5jdGlvbihhLGIsYyl7dmFyIGQsZSxmLGcsaD1hLnN0eWxlO3JldHVybiBjPWN8fElhKGEpLGc9Yz9jW2JdOnZvaWQgMCxudWxsPT1nJiZoJiZoW2JdJiYoZz1oW2JdKSxIYS50ZXN0KGcpJiYhS2EudGVzdChiKSYmKGQ9aC5sZWZ0LGU9YS5ydW50aW1lU3R5bGUsZj1lJiZlLmxlZnQsZiYmKGUubGVmdD1hLmN1cnJlbnRTdHlsZS5sZWZ0KSxoLmxlZnQ9ImZvbnRTaXplIj09PWI/IjFlbSI6ZyxnPWgucGl4ZWxMZWZ0KyJweCIsaC5sZWZ0PWQsZiYmKGUubGVmdD1mKSksdm9pZCAwPT09Zz9nOmcrIiJ8fCJhdXRvIn0pO2Z1bmN0aW9uIExhKGEsYil7cmV0dXJue2dldDpmdW5jdGlvbigpe3ZhciBjPWEoKTtpZihudWxsIT1jKXJldHVybiBjP3ZvaWQgZGVsZXRlIHRoaXMuZ2V0Oih0aGlzLmdldD1iKS5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fX0hZnVuY3Rpb24oKXt2YXIgYixjLGQsZSxmLGcsaDtpZihiPXkuY3JlYXRlRWxlbWVudCgiZGl2IiksYi5pbm5lckhUTUw9IiAgPGxpbmsvPjx0YWJsZT48L3RhYmxlPjxhIGhyZWY9Jy9hJz5hPC9hPjxpbnB1dCB0eXBlPSdjaGVja2JveCcvPiIsZD1iLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJhIilbMF0sYz1kJiZkLnN0eWxlKXtjLmNzc1RleHQ9ImZsb2F0OmxlZnQ7b3BhY2l0eTouNSIsay5vcGFjaXR5PSIwLjUiPT09Yy5vcGFjaXR5LGsuY3NzRmxvYXQ9ISFjLmNzc0Zsb2F0LGIuc3R5bGUuYmFja2dyb3VuZENsaXA9ImNvbnRlbnQtYm94IixiLmNsb25lTm9kZSghMCkuc3R5bGUuYmFja2dyb3VuZENsaXA9IiIsay5jbGVhckNsb25lU3R5bGU9ImNvbnRlbnQtYm94Ij09PWIuc3R5bGUuYmFja2dyb3VuZENsaXAsay5ib3hTaXppbmc9IiI9PT1jLmJveFNpemluZ3x8IiI9PT1jLk1vekJveFNpemluZ3x8IiI9PT1jLldlYmtpdEJveFNpemluZyxtLmV4dGVuZChrLHtyZWxpYWJsZUhpZGRlbk9mZnNldHM6ZnVuY3Rpb24oKXtyZXR1cm4gbnVsbD09ZyYmaSgpLGd9LGJveFNpemluZ1JlbGlhYmxlOmZ1bmN0aW9uKCl7cmV0dXJuIG51bGw9PWYmJmkoKSxmfSxwaXhlbFBvc2l0aW9uOmZ1bmN0aW9uKCl7cmV0dXJuIG51bGw9PWUmJmkoKSxlfSxyZWxpYWJsZU1hcmdpblJpZ2h0OmZ1bmN0aW9uKCl7cmV0dXJuIG51bGw9PWgmJmkoKSxofX0pO2Z1bmN0aW9uIGkoKXt2YXIgYixjLGQsaTtjPXkuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImJvZHkiKVswXSxjJiZjLnN0eWxlJiYoYj15LmNyZWF0ZUVsZW1lbnQoImRpdiIpLGQ9eS5jcmVhdGVFbGVtZW50KCJkaXYiKSxkLnN0eWxlLmNzc1RleHQ9InBvc2l0aW9uOmFic29sdXRlO2JvcmRlcjowO3dpZHRoOjA7aGVpZ2h0OjA7dG9wOjA7bGVmdDotOTk5OXB4IixjLmFwcGVuZENoaWxkKGQpLmFwcGVuZENoaWxkKGIpLGIuc3R5bGUuY3NzVGV4dD0iLXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O2Rpc3BsYXk6YmxvY2s7bWFyZ2luLXRvcDoxJTt0b3A6MSU7Ym9yZGVyOjFweDtwYWRkaW5nOjFweDt3aWR0aDo0cHg7cG9zaXRpb246YWJzb2x1dGUiLGU9Zj0hMSxoPSEwLGEuZ2V0Q29tcHV0ZWRTdHlsZSYmKGU9IjElIiE9PShhLmdldENvbXB1dGVkU3R5bGUoYixudWxsKXx8e30pLnRvcCxmPSI0cHgiPT09KGEuZ2V0Q29tcHV0ZWRTdHlsZShiLG51bGwpfHx7d2lkdGg6IjRweCJ9KS53aWR0aCxpPWIuYXBwZW5kQ2hpbGQoeS5jcmVhdGVFbGVtZW50KCJkaXYiKSksaS5zdHlsZS5jc3NUZXh0PWIuc3R5bGUuY3NzVGV4dD0iLXdlYmtpdC1ib3gtc2l6aW5nOmNvbnRlbnQtYm94Oy1tb3otYm94LXNpemluZzpjb250ZW50LWJveDtib3gtc2l6aW5nOmNvbnRlbnQtYm94O2Rpc3BsYXk6YmxvY2s7bWFyZ2luOjA7Ym9yZGVyOjA7cGFkZGluZzowIixpLnN0eWxlLm1hcmdpblJpZ2h0PWkuc3R5bGUud2lkdGg9IjAiLGIuc3R5bGUud2lkdGg9IjFweCIsaD0hcGFyc2VGbG9hdCgoYS5nZXRDb21wdXRlZFN0eWxlKGksbnVsbCl8fHt9KS5tYXJnaW5SaWdodCksYi5yZW1vdmVDaGlsZChpKSksYi5pbm5lckhUTUw9Ijx0YWJsZT48dHI+PHRkPjwvdGQ+PHRkPnQ8L3RkPjwvdHI+PC90YWJsZT4iLGk9Yi5nZXRFbGVtZW50c0J5VGFnTmFtZSgidGQiKSxpWzBdLnN0eWxlLmNzc1RleHQ9Im1hcmdpbjowO2JvcmRlcjowO3BhZGRpbmc6MDtkaXNwbGF5Om5vbmUiLGc9MD09PWlbMF0ub2Zmc2V0SGVpZ2h0LGcmJihpWzBdLnN0eWxlLmRpc3BsYXk9IiIsaVsxXS5zdHlsZS5kaXNwbGF5PSJub25lIixnPTA9PT1pWzBdLm9mZnNldEhlaWdodCksYy5yZW1vdmVDaGlsZChkKSl9fX0oKSxtLnN3YXA9ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGUsZixnPXt9O2ZvcihmIGluIGIpZ1tmXT1hLnN0eWxlW2ZdLGEuc3R5bGVbZl09YltmXTtlPWMuYXBwbHkoYSxkfHxbXSk7Zm9yKGYgaW4gYilhLnN0eWxlW2ZdPWdbZl07cmV0dXJuIGV9O3ZhciBNYT0vYWxwaGFcKFteKV0qXCkvaSxOYT0vb3BhY2l0eVxzKj1ccyooW14pXSopLyxPYT0vXihub25lfHRhYmxlKD8hLWNbZWFdKS4rKS8sUGE9bmV3IFJlZ0V4cCgiXigiK1MrIikoLiopJCIsImkiKSxRYT1uZXcgUmVnRXhwKCJeKFsrLV0pPSgiK1MrIikiLCJpIiksUmE9e3Bvc2l0aW9uOiJhYnNvbHV0ZSIsdmlzaWJpbGl0eToiaGlkZGVuIixkaXNwbGF5OiJibG9jayJ9LFNhPXtsZXR0ZXJTcGFjaW5nOiIwIixmb250V2VpZ2h0OiI0MDAifSxUYT1bIldlYmtpdCIsIk8iLCJNb3oiLCJtcyJdO2Z1bmN0aW9uIFVhKGEsYil7aWYoYiBpbiBhKXJldHVybiBiO3ZhciBjPWIuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkrYi5zbGljZSgxKSxkPWIsZT1UYS5sZW5ndGg7d2hpbGUoZS0tKWlmKGI9VGFbZV0rYyxiIGluIGEpcmV0dXJuIGI7cmV0dXJuIGR9ZnVuY3Rpb24gVmEoYSxiKXtmb3IodmFyIGMsZCxlLGY9W10sZz0wLGg9YS5sZW5ndGg7aD5nO2crKylkPWFbZ10sZC5zdHlsZSYmKGZbZ109bS5fZGF0YShkLCJvbGRkaXNwbGF5IiksYz1kLnN0eWxlLmRpc3BsYXksYj8oZltnXXx8Im5vbmUiIT09Y3x8KGQuc3R5bGUuZGlzcGxheT0iIiksIiI9PT1kLnN0eWxlLmRpc3BsYXkmJlUoZCkmJihmW2ddPW0uX2RhdGEoZCwib2xkZGlzcGxheSIsRmEoZC5ub2RlTmFtZSkpKSk6KGU9VShkKSwoYyYmIm5vbmUiIT09Y3x8IWUpJiZtLl9kYXRhKGQsIm9sZGRpc3BsYXkiLGU/YzptLmNzcyhkLCJkaXNwbGF5IikpKSk7Zm9yKGc9MDtoPmc7ZysrKWQ9YVtnXSxkLnN0eWxlJiYoYiYmIm5vbmUiIT09ZC5zdHlsZS5kaXNwbGF5JiYiIiE9PWQuc3R5bGUuZGlzcGxheXx8KGQuc3R5bGUuZGlzcGxheT1iP2ZbZ118fCIiOiJub25lIikpO3JldHVybiBhfWZ1bmN0aW9uIFdhKGEsYixjKXt2YXIgZD1QYS5leGVjKGIpO3JldHVybiBkP01hdGgubWF4KDAsZFsxXS0oY3x8MCkpKyhkWzJdfHwicHgiKTpifWZ1bmN0aW9uIFhhKGEsYixjLGQsZSl7Zm9yKHZhciBmPWM9PT0oZD8iYm9yZGVyIjoiY29udGVudCIpPzQ6IndpZHRoIj09PWI/MTowLGc9MDs0PmY7Zis9MikibWFyZ2luIj09PWMmJihnKz1tLmNzcyhhLGMrVFtmXSwhMCxlKSksZD8oImNvbnRlbnQiPT09YyYmKGctPW0uY3NzKGEsInBhZGRpbmciK1RbZl0sITAsZSkpLCJtYXJnaW4iIT09YyYmKGctPW0uY3NzKGEsImJvcmRlciIrVFtmXSsiV2lkdGgiLCEwLGUpKSk6KGcrPW0uY3NzKGEsInBhZGRpbmciK1RbZl0sITAsZSksInBhZGRpbmciIT09YyYmKGcrPW0uY3NzKGEsImJvcmRlciIrVFtmXSsiV2lkdGgiLCEwLGUpKSk7cmV0dXJuIGd9ZnVuY3Rpb24gWWEoYSxiLGMpe3ZhciBkPSEwLGU9IndpZHRoIj09PWI/YS5vZmZzZXRXaWR0aDphLm9mZnNldEhlaWdodCxmPUlhKGEpLGc9ay5ib3hTaXppbmcmJiJib3JkZXItYm94Ij09PW0uY3NzKGEsImJveFNpemluZyIsITEsZik7aWYoMD49ZXx8bnVsbD09ZSl7aWYoZT1KYShhLGIsZiksKDA+ZXx8bnVsbD09ZSkmJihlPWEuc3R5bGVbYl0pLEhhLnRlc3QoZSkpcmV0dXJuIGU7ZD1nJiYoay5ib3hTaXppbmdSZWxpYWJsZSgpfHxlPT09YS5zdHlsZVtiXSksZT1wYXJzZUZsb2F0KGUpfHwwfXJldHVybiBlK1hhKGEsYixjfHwoZz8iYm9yZGVyIjoiY29udGVudCIpLGQsZikrInB4In1tLmV4dGVuZCh7Y3NzSG9va3M6e29wYWNpdHk6e2dldDpmdW5jdGlvbihhLGIpe2lmKGIpe3ZhciBjPUphKGEsIm9wYWNpdHkiKTtyZXR1cm4iIj09PWM/IjEiOmN9fX19LGNzc051bWJlcjp7Y29sdW1uQ291bnQ6ITAsZmlsbE9wYWNpdHk6ITAsZmxleEdyb3c6ITAsZmxleFNocmluazohMCxmb250V2VpZ2h0OiEwLGxpbmVIZWlnaHQ6ITAsb3BhY2l0eTohMCxvcmRlcjohMCxvcnBoYW5zOiEwLHdpZG93czohMCx6SW5kZXg6ITAsem9vbTohMH0sY3NzUHJvcHM6eyJmbG9hdCI6ay5jc3NGbG9hdD8iY3NzRmxvYXQiOiJzdHlsZUZsb2F0In0sc3R5bGU6ZnVuY3Rpb24oYSxiLGMsZCl7aWYoYSYmMyE9PWEubm9kZVR5cGUmJjghPT1hLm5vZGVUeXBlJiZhLnN0eWxlKXt2YXIgZSxmLGcsaD1tLmNhbWVsQ2FzZShiKSxpPWEuc3R5bGU7aWYoYj1tLmNzc1Byb3BzW2hdfHwobS5jc3NQcm9wc1toXT1VYShpLGgpKSxnPW0uY3NzSG9va3NbYl18fG0uY3NzSG9va3NbaF0sdm9pZCAwPT09YylyZXR1cm4gZyYmImdldCJpbiBnJiZ2b2lkIDAhPT0oZT1nLmdldChhLCExLGQpKT9lOmlbYl07aWYoZj10eXBlb2YgYywic3RyaW5nIj09PWYmJihlPVFhLmV4ZWMoYykpJiYoYz0oZVsxXSsxKSplWzJdK3BhcnNlRmxvYXQobS5jc3MoYSxiKSksZj0ibnVtYmVyIiksbnVsbCE9YyYmYz09PWMmJigibnVtYmVyIiE9PWZ8fG0uY3NzTnVtYmVyW2hdfHwoYys9InB4Iiksay5jbGVhckNsb25lU3R5bGV8fCIiIT09Y3x8MCE9PWIuaW5kZXhPZigiYmFja2dyb3VuZCIpfHwoaVtiXT0iaW5oZXJpdCIpLCEoZyYmInNldCJpbiBnJiZ2b2lkIDA9PT0oYz1nLnNldChhLGMsZCkpKSkpdHJ5e2lbYl09Y31jYXRjaChqKXt9fX0sY3NzOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBlLGYsZyxoPW0uY2FtZWxDYXNlKGIpO3JldHVybiBiPW0uY3NzUHJvcHNbaF18fChtLmNzc1Byb3BzW2hdPVVhKGEuc3R5bGUsaCkpLGc9bS5jc3NIb29rc1tiXXx8bS5jc3NIb29rc1toXSxnJiYiZ2V0ImluIGcmJihmPWcuZ2V0KGEsITAsYykpLHZvaWQgMD09PWYmJihmPUphKGEsYixkKSksIm5vcm1hbCI9PT1mJiZiIGluIFNhJiYoZj1TYVtiXSksIiI9PT1jfHxjPyhlPXBhcnNlRmxvYXQoZiksYz09PSEwfHxtLmlzTnVtZXJpYyhlKT9lfHwwOmYpOmZ9fSksbS5lYWNoKFsiaGVpZ2h0Iiwid2lkdGgiXSxmdW5jdGlvbihhLGIpe20uY3NzSG9va3NbYl09e2dldDpmdW5jdGlvbihhLGMsZCl7cmV0dXJuIGM/T2EudGVzdChtLmNzcyhhLCJkaXNwbGF5IikpJiYwPT09YS5vZmZzZXRXaWR0aD9tLnN3YXAoYSxSYSxmdW5jdGlvbigpe3JldHVybiBZYShhLGIsZCl9KTpZYShhLGIsZCk6dm9pZCAwfSxzZXQ6ZnVuY3Rpb24oYSxjLGQpe3ZhciBlPWQmJklhKGEpO3JldHVybiBXYShhLGMsZD9YYShhLGIsZCxrLmJveFNpemluZyYmImJvcmRlci1ib3giPT09bS5jc3MoYSwiYm94U2l6aW5nIiwhMSxlKSxlKTowKX19fSksay5vcGFjaXR5fHwobS5jc3NIb29rcy5vcGFjaXR5PXtnZXQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gTmEudGVzdCgoYiYmYS5jdXJyZW50U3R5bGU/YS5jdXJyZW50U3R5bGUuZmlsdGVyOmEuc3R5bGUuZmlsdGVyKXx8IiIpPy4wMSpwYXJzZUZsb2F0KFJlZ0V4cC4kMSkrIiI6Yj8iMSI6IiJ9LHNldDpmdW5jdGlvbihhLGIpe3ZhciBjPWEuc3R5bGUsZD1hLmN1cnJlbnRTdHlsZSxlPW0uaXNOdW1lcmljKGIpPyJhbHBoYShvcGFjaXR5PSIrMTAwKmIrIikiOiIiLGY9ZCYmZC5maWx0ZXJ8fGMuZmlsdGVyfHwiIjtjLnpvb209MSwoYj49MXx8IiI9PT1iKSYmIiI9PT1tLnRyaW0oZi5yZXBsYWNlKE1hLCIiKSkmJmMucmVtb3ZlQXR0cmlidXRlJiYoYy5yZW1vdmVBdHRyaWJ1dGUoImZpbHRlciIpLCIiPT09Ynx8ZCYmIWQuZmlsdGVyKXx8KGMuZmlsdGVyPU1hLnRlc3QoZik/Zi5yZXBsYWNlKE1hLGUpOmYrIiAiK2UpfX0pLG0uY3NzSG9va3MubWFyZ2luUmlnaHQ9TGEoay5yZWxpYWJsZU1hcmdpblJpZ2h0LGZ1bmN0aW9uKGEsYil7cmV0dXJuIGI/bS5zd2FwKGEse2Rpc3BsYXk6ImlubGluZS1ibG9jayJ9LEphLFthLCJtYXJnaW5SaWdodCJdKTp2b2lkIDB9KSxtLmVhY2goe21hcmdpbjoiIixwYWRkaW5nOiIiLGJvcmRlcjoiV2lkdGgifSxmdW5jdGlvbihhLGIpe20uY3NzSG9va3NbYStiXT17ZXhwYW5kOmZ1bmN0aW9uKGMpe2Zvcih2YXIgZD0wLGU9e30sZj0ic3RyaW5nIj09dHlwZW9mIGM/Yy5zcGxpdCgiICIpOltjXTs0PmQ7ZCsrKWVbYStUW2RdK2JdPWZbZF18fGZbZC0yXXx8ZlswXTtyZXR1cm4gZX19LEdhLnRlc3QoYSl8fChtLmNzc0hvb2tzW2ErYl0uc2V0PVdhKX0pLG0uZm4uZXh0ZW5kKHtjc3M6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gVih0aGlzLGZ1bmN0aW9uKGEsYixjKXt2YXIgZCxlLGY9e30sZz0wO2lmKG0uaXNBcnJheShiKSl7Zm9yKGQ9SWEoYSksZT1iLmxlbmd0aDtlPmc7ZysrKWZbYltnXV09bS5jc3MoYSxiW2ddLCExLGQpO3JldHVybiBmfXJldHVybiB2b2lkIDAhPT1jP20uc3R5bGUoYSxiLGMpOm0uY3NzKGEsYil9LGEsYixhcmd1bWVudHMubGVuZ3RoPjEpfSxzaG93OmZ1bmN0aW9uKCl7cmV0dXJuIFZhKHRoaXMsITApfSxoaWRlOmZ1bmN0aW9uKCl7cmV0dXJuIFZhKHRoaXMpfSx0b2dnbGU6ZnVuY3Rpb24oYSl7cmV0dXJuImJvb2xlYW4iPT10eXBlb2YgYT9hP3RoaXMuc2hvdygpOnRoaXMuaGlkZSgpOnRoaXMuZWFjaChmdW5jdGlvbigpe1UodGhpcyk/bSh0aGlzKS5zaG93KCk6bSh0aGlzKS5oaWRlKCl9KX19KTtmdW5jdGlvbiBaYShhLGIsYyxkLGUpewpyZXR1cm4gbmV3IFphLnByb3RvdHlwZS5pbml0KGEsYixjLGQsZSl9bS5Ud2Vlbj1aYSxaYS5wcm90b3R5cGU9e2NvbnN0cnVjdG9yOlphLGluaXQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3RoaXMuZWxlbT1hLHRoaXMucHJvcD1jLHRoaXMuZWFzaW5nPWV8fCJzd2luZyIsdGhpcy5vcHRpb25zPWIsdGhpcy5zdGFydD10aGlzLm5vdz10aGlzLmN1cigpLHRoaXMuZW5kPWQsdGhpcy51bml0PWZ8fChtLmNzc051bWJlcltjXT8iIjoicHgiKX0sY3VyOmZ1bmN0aW9uKCl7dmFyIGE9WmEucHJvcEhvb2tzW3RoaXMucHJvcF07cmV0dXJuIGEmJmEuZ2V0P2EuZ2V0KHRoaXMpOlphLnByb3BIb29rcy5fZGVmYXVsdC5nZXQodGhpcyl9LHJ1bjpmdW5jdGlvbihhKXt2YXIgYixjPVphLnByb3BIb29rc1t0aGlzLnByb3BdO3JldHVybiB0aGlzLm9wdGlvbnMuZHVyYXRpb24/dGhpcy5wb3M9Yj1tLmVhc2luZ1t0aGlzLmVhc2luZ10oYSx0aGlzLm9wdGlvbnMuZHVyYXRpb24qYSwwLDEsdGhpcy5vcHRpb25zLmR1cmF0aW9uKTp0aGlzLnBvcz1iPWEsdGhpcy5ub3c9KHRoaXMuZW5kLXRoaXMuc3RhcnQpKmIrdGhpcy5zdGFydCx0aGlzLm9wdGlvbnMuc3RlcCYmdGhpcy5vcHRpb25zLnN0ZXAuY2FsbCh0aGlzLmVsZW0sdGhpcy5ub3csdGhpcyksYyYmYy5zZXQ/Yy5zZXQodGhpcyk6WmEucHJvcEhvb2tzLl9kZWZhdWx0LnNldCh0aGlzKSx0aGlzfX0sWmEucHJvdG90eXBlLmluaXQucHJvdG90eXBlPVphLnByb3RvdHlwZSxaYS5wcm9wSG9va3M9e19kZWZhdWx0OntnZXQ6ZnVuY3Rpb24oYSl7dmFyIGI7cmV0dXJuIG51bGw9PWEuZWxlbVthLnByb3BdfHxhLmVsZW0uc3R5bGUmJm51bGwhPWEuZWxlbS5zdHlsZVthLnByb3BdPyhiPW0uY3NzKGEuZWxlbSxhLnByb3AsIiIpLGImJiJhdXRvIiE9PWI/YjowKTphLmVsZW1bYS5wcm9wXX0sc2V0OmZ1bmN0aW9uKGEpe20uZnguc3RlcFthLnByb3BdP20uZnguc3RlcFthLnByb3BdKGEpOmEuZWxlbS5zdHlsZSYmKG51bGwhPWEuZWxlbS5zdHlsZVttLmNzc1Byb3BzW2EucHJvcF1dfHxtLmNzc0hvb2tzW2EucHJvcF0pP20uc3R5bGUoYS5lbGVtLGEucHJvcCxhLm5vdythLnVuaXQpOmEuZWxlbVthLnByb3BdPWEubm93fX19LFphLnByb3BIb29rcy5zY3JvbGxUb3A9WmEucHJvcEhvb2tzLnNjcm9sbExlZnQ9e3NldDpmdW5jdGlvbihhKXthLmVsZW0ubm9kZVR5cGUmJmEuZWxlbS5wYXJlbnROb2RlJiYoYS5lbGVtW2EucHJvcF09YS5ub3cpfX0sbS5lYXNpbmc9e2xpbmVhcjpmdW5jdGlvbihhKXtyZXR1cm4gYX0sc3dpbmc6ZnVuY3Rpb24oYSl7cmV0dXJuLjUtTWF0aC5jb3MoYSpNYXRoLlBJKS8yfX0sbS5meD1aYS5wcm90b3R5cGUuaW5pdCxtLmZ4LnN0ZXA9e307dmFyICRhLF9hLGFiPS9eKD86dG9nZ2xlfHNob3d8aGlkZSkkLyxiYj1uZXcgUmVnRXhwKCJeKD86KFsrLV0pPXwpKCIrUysiKShbYS16JV0qKSQiLCJpIiksY2I9L3F1ZXVlSG9va3MkLyxkYj1baWJdLGViPXsiKiI6W2Z1bmN0aW9uKGEsYil7dmFyIGM9dGhpcy5jcmVhdGVUd2VlbihhLGIpLGQ9Yy5jdXIoKSxlPWJiLmV4ZWMoYiksZj1lJiZlWzNdfHwobS5jc3NOdW1iZXJbYV0/IiI6InB4IiksZz0obS5jc3NOdW1iZXJbYV18fCJweCIhPT1mJiYrZCkmJmJiLmV4ZWMobS5jc3MoYy5lbGVtLGEpKSxoPTEsaT0yMDtpZihnJiZnWzNdIT09Zil7Zj1mfHxnWzNdLGU9ZXx8W10sZz0rZHx8MTtkbyBoPWh8fCIuNSIsZy89aCxtLnN0eWxlKGMuZWxlbSxhLGcrZik7d2hpbGUoaCE9PShoPWMuY3VyKCkvZCkmJjEhPT1oJiYtLWkpfXJldHVybiBlJiYoZz1jLnN0YXJ0PStnfHwrZHx8MCxjLnVuaXQ9ZixjLmVuZD1lWzFdP2crKGVbMV0rMSkqZVsyXTorZVsyXSksY31dfTtmdW5jdGlvbiBmYigpe3JldHVybiBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7JGE9dm9pZCAwfSksJGE9bS5ub3coKX1mdW5jdGlvbiBnYihhLGIpe3ZhciBjLGQ9e2hlaWdodDphfSxlPTA7Zm9yKGI9Yj8xOjA7ND5lO2UrPTItYiljPVRbZV0sZFsibWFyZ2luIitjXT1kWyJwYWRkaW5nIitjXT1hO3JldHVybiBiJiYoZC5vcGFjaXR5PWQud2lkdGg9YSksZH1mdW5jdGlvbiBoYihhLGIsYyl7Zm9yKHZhciBkLGU9KGViW2JdfHxbXSkuY29uY2F0KGViWyIqIl0pLGY9MCxnPWUubGVuZ3RoO2c+ZjtmKyspaWYoZD1lW2ZdLmNhbGwoYyxiLGEpKXJldHVybiBkfWZ1bmN0aW9uIGliKGEsYixjKXt2YXIgZCxlLGYsZyxoLGksaixsLG49dGhpcyxvPXt9LHA9YS5zdHlsZSxxPWEubm9kZVR5cGUmJlUoYSkscj1tLl9kYXRhKGEsImZ4c2hvdyIpO2MucXVldWV8fChoPW0uX3F1ZXVlSG9va3MoYSwiZngiKSxudWxsPT1oLnVucXVldWVkJiYoaC51bnF1ZXVlZD0wLGk9aC5lbXB0eS5maXJlLGguZW1wdHkuZmlyZT1mdW5jdGlvbigpe2gudW5xdWV1ZWR8fGkoKX0pLGgudW5xdWV1ZWQrKyxuLmFsd2F5cyhmdW5jdGlvbigpe24uYWx3YXlzKGZ1bmN0aW9uKCl7aC51bnF1ZXVlZC0tLG0ucXVldWUoYSwiZngiKS5sZW5ndGh8fGguZW1wdHkuZmlyZSgpfSl9KSksMT09PWEubm9kZVR5cGUmJigiaGVpZ2h0ImluIGJ8fCJ3aWR0aCJpbiBiKSYmKGMub3ZlcmZsb3c9W3Aub3ZlcmZsb3cscC5vdmVyZmxvd1gscC5vdmVyZmxvd1ldLGo9bS5jc3MoYSwiZGlzcGxheSIpLGw9Im5vbmUiPT09aj9tLl9kYXRhKGEsIm9sZGRpc3BsYXkiKXx8RmEoYS5ub2RlTmFtZSk6aiwiaW5saW5lIj09PWwmJiJub25lIj09PW0uY3NzKGEsImZsb2F0IikmJihrLmlubGluZUJsb2NrTmVlZHNMYXlvdXQmJiJpbmxpbmUiIT09RmEoYS5ub2RlTmFtZSk/cC56b29tPTE6cC5kaXNwbGF5PSJpbmxpbmUtYmxvY2siKSksYy5vdmVyZmxvdyYmKHAub3ZlcmZsb3c9ImhpZGRlbiIsay5zaHJpbmtXcmFwQmxvY2tzKCl8fG4uYWx3YXlzKGZ1bmN0aW9uKCl7cC5vdmVyZmxvdz1jLm92ZXJmbG93WzBdLHAub3ZlcmZsb3dYPWMub3ZlcmZsb3dbMV0scC5vdmVyZmxvd1k9Yy5vdmVyZmxvd1syXX0pKTtmb3IoZCBpbiBiKWlmKGU9YltkXSxhYi5leGVjKGUpKXtpZihkZWxldGUgYltkXSxmPWZ8fCJ0b2dnbGUiPT09ZSxlPT09KHE/ImhpZGUiOiJzaG93Iikpe2lmKCJzaG93IiE9PWV8fCFyfHx2b2lkIDA9PT1yW2RdKWNvbnRpbnVlO3E9ITB9b1tkXT1yJiZyW2RdfHxtLnN0eWxlKGEsZCl9ZWxzZSBqPXZvaWQgMDtpZihtLmlzRW1wdHlPYmplY3QobykpImlubGluZSI9PT0oIm5vbmUiPT09aj9GYShhLm5vZGVOYW1lKTpqKSYmKHAuZGlzcGxheT1qKTtlbHNle3I/ImhpZGRlbiJpbiByJiYocT1yLmhpZGRlbik6cj1tLl9kYXRhKGEsImZ4c2hvdyIse30pLGYmJihyLmhpZGRlbj0hcSkscT9tKGEpLnNob3coKTpuLmRvbmUoZnVuY3Rpb24oKXttKGEpLmhpZGUoKX0pLG4uZG9uZShmdW5jdGlvbigpe3ZhciBiO20uX3JlbW92ZURhdGEoYSwiZnhzaG93Iik7Zm9yKGIgaW4gbyltLnN0eWxlKGEsYixvW2JdKX0pO2ZvcihkIGluIG8pZz1oYihxP3JbZF06MCxkLG4pLGQgaW4gcnx8KHJbZF09Zy5zdGFydCxxJiYoZy5lbmQ9Zy5zdGFydCxnLnN0YXJ0PSJ3aWR0aCI9PT1kfHwiaGVpZ2h0Ij09PWQ/MTowKSl9fWZ1bmN0aW9uIGpiKGEsYil7dmFyIGMsZCxlLGYsZztmb3IoYyBpbiBhKWlmKGQ9bS5jYW1lbENhc2UoYyksZT1iW2RdLGY9YVtjXSxtLmlzQXJyYXkoZikmJihlPWZbMV0sZj1hW2NdPWZbMF0pLGMhPT1kJiYoYVtkXT1mLGRlbGV0ZSBhW2NdKSxnPW0uY3NzSG9va3NbZF0sZyYmImV4cGFuZCJpbiBnKXtmPWcuZXhwYW5kKGYpLGRlbGV0ZSBhW2RdO2ZvcihjIGluIGYpYyBpbiBhfHwoYVtjXT1mW2NdLGJbY109ZSl9ZWxzZSBiW2RdPWV9ZnVuY3Rpb24ga2IoYSxiLGMpe3ZhciBkLGUsZj0wLGc9ZGIubGVuZ3RoLGg9bS5EZWZlcnJlZCgpLmFsd2F5cyhmdW5jdGlvbigpe2RlbGV0ZSBpLmVsZW19KSxpPWZ1bmN0aW9uKCl7aWYoZSlyZXR1cm4hMTtmb3IodmFyIGI9JGF8fGZiKCksYz1NYXRoLm1heCgwLGouc3RhcnRUaW1lK2ouZHVyYXRpb24tYiksZD1jL2ouZHVyYXRpb258fDAsZj0xLWQsZz0wLGk9ai50d2VlbnMubGVuZ3RoO2k+ZztnKyspai50d2VlbnNbZ10ucnVuKGYpO3JldHVybiBoLm5vdGlmeVdpdGgoYSxbaixmLGNdKSwxPmYmJmk/YzooaC5yZXNvbHZlV2l0aChhLFtqXSksITEpfSxqPWgucHJvbWlzZSh7ZWxlbTphLHByb3BzOm0uZXh0ZW5kKHt9LGIpLG9wdHM6bS5leHRlbmQoITAse3NwZWNpYWxFYXNpbmc6e319LGMpLG9yaWdpbmFsUHJvcGVydGllczpiLG9yaWdpbmFsT3B0aW9uczpjLHN0YXJ0VGltZTokYXx8ZmIoKSxkdXJhdGlvbjpjLmR1cmF0aW9uLHR3ZWVuczpbXSxjcmVhdGVUd2VlbjpmdW5jdGlvbihiLGMpe3ZhciBkPW0uVHdlZW4oYSxqLm9wdHMsYixjLGoub3B0cy5zcGVjaWFsRWFzaW5nW2JdfHxqLm9wdHMuZWFzaW5nKTtyZXR1cm4gai50d2VlbnMucHVzaChkKSxkfSxzdG9wOmZ1bmN0aW9uKGIpe3ZhciBjPTAsZD1iP2oudHdlZW5zLmxlbmd0aDowO2lmKGUpcmV0dXJuIHRoaXM7Zm9yKGU9ITA7ZD5jO2MrKylqLnR3ZWVuc1tjXS5ydW4oMSk7cmV0dXJuIGI/aC5yZXNvbHZlV2l0aChhLFtqLGJdKTpoLnJlamVjdFdpdGgoYSxbaixiXSksdGhpc319KSxrPWoucHJvcHM7Zm9yKGpiKGssai5vcHRzLnNwZWNpYWxFYXNpbmcpO2c+ZjtmKyspaWYoZD1kYltmXS5jYWxsKGosYSxrLGoub3B0cykpcmV0dXJuIGQ7cmV0dXJuIG0ubWFwKGssaGIsaiksbS5pc0Z1bmN0aW9uKGoub3B0cy5zdGFydCkmJmoub3B0cy5zdGFydC5jYWxsKGEsaiksbS5meC50aW1lcihtLmV4dGVuZChpLHtlbGVtOmEsYW5pbTpqLHF1ZXVlOmoub3B0cy5xdWV1ZX0pKSxqLnByb2dyZXNzKGoub3B0cy5wcm9ncmVzcykuZG9uZShqLm9wdHMuZG9uZSxqLm9wdHMuY29tcGxldGUpLmZhaWwoai5vcHRzLmZhaWwpLmFsd2F5cyhqLm9wdHMuYWx3YXlzKX1tLkFuaW1hdGlvbj1tLmV4dGVuZChrYix7dHdlZW5lcjpmdW5jdGlvbihhLGIpe20uaXNGdW5jdGlvbihhKT8oYj1hLGE9WyIqIl0pOmE9YS5zcGxpdCgiICIpO2Zvcih2YXIgYyxkPTAsZT1hLmxlbmd0aDtlPmQ7ZCsrKWM9YVtkXSxlYltjXT1lYltjXXx8W10sZWJbY10udW5zaGlmdChiKX0scHJlZmlsdGVyOmZ1bmN0aW9uKGEsYil7Yj9kYi51bnNoaWZ0KGEpOmRiLnB1c2goYSl9fSksbS5zcGVlZD1mdW5jdGlvbihhLGIsYyl7dmFyIGQ9YSYmIm9iamVjdCI9PXR5cGVvZiBhP20uZXh0ZW5kKHt9LGEpOntjb21wbGV0ZTpjfHwhYyYmYnx8bS5pc0Z1bmN0aW9uKGEpJiZhLGR1cmF0aW9uOmEsZWFzaW5nOmMmJmJ8fGImJiFtLmlzRnVuY3Rpb24oYikmJmJ9O3JldHVybiBkLmR1cmF0aW9uPW0uZngub2ZmPzA6Im51bWJlciI9PXR5cGVvZiBkLmR1cmF0aW9uP2QuZHVyYXRpb246ZC5kdXJhdGlvbiBpbiBtLmZ4LnNwZWVkcz9tLmZ4LnNwZWVkc1tkLmR1cmF0aW9uXTptLmZ4LnNwZWVkcy5fZGVmYXVsdCwobnVsbD09ZC5xdWV1ZXx8ZC5xdWV1ZT09PSEwKSYmKGQucXVldWU9ImZ4IiksZC5vbGQ9ZC5jb21wbGV0ZSxkLmNvbXBsZXRlPWZ1bmN0aW9uKCl7bS5pc0Z1bmN0aW9uKGQub2xkKSYmZC5vbGQuY2FsbCh0aGlzKSxkLnF1ZXVlJiZtLmRlcXVldWUodGhpcyxkLnF1ZXVlKX0sZH0sbS5mbi5leHRlbmQoe2ZhZGVUbzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gdGhpcy5maWx0ZXIoVSkuY3NzKCJvcGFjaXR5IiwwKS5zaG93KCkuZW5kKCkuYW5pbWF0ZSh7b3BhY2l0eTpifSxhLGMsZCl9LGFuaW1hdGU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIGU9bS5pc0VtcHR5T2JqZWN0KGEpLGY9bS5zcGVlZChiLGMsZCksZz1mdW5jdGlvbigpe3ZhciBiPWtiKHRoaXMsbS5leHRlbmQoe30sYSksZik7KGV8fG0uX2RhdGEodGhpcywiZmluaXNoIikpJiZiLnN0b3AoITApfTtyZXR1cm4gZy5maW5pc2g9ZyxlfHxmLnF1ZXVlPT09ITE/dGhpcy5lYWNoKGcpOnRoaXMucXVldWUoZi5xdWV1ZSxnKX0sc3RvcDpmdW5jdGlvbihhLGIsYyl7dmFyIGQ9ZnVuY3Rpb24oYSl7dmFyIGI9YS5zdG9wO2RlbGV0ZSBhLnN0b3AsYihjKX07cmV0dXJuInN0cmluZyIhPXR5cGVvZiBhJiYoYz1iLGI9YSxhPXZvaWQgMCksYiYmYSE9PSExJiZ0aGlzLnF1ZXVlKGF8fCJmeCIsW10pLHRoaXMuZWFjaChmdW5jdGlvbigpe3ZhciBiPSEwLGU9bnVsbCE9YSYmYSsicXVldWVIb29rcyIsZj1tLnRpbWVycyxnPW0uX2RhdGEodGhpcyk7aWYoZSlnW2VdJiZnW2VdLnN0b3AmJmQoZ1tlXSk7ZWxzZSBmb3IoZSBpbiBnKWdbZV0mJmdbZV0uc3RvcCYmY2IudGVzdChlKSYmZChnW2VdKTtmb3IoZT1mLmxlbmd0aDtlLS07KWZbZV0uZWxlbSE9PXRoaXN8fG51bGwhPWEmJmZbZV0ucXVldWUhPT1hfHwoZltlXS5hbmltLnN0b3AoYyksYj0hMSxmLnNwbGljZShlLDEpKTsoYnx8IWMpJiZtLmRlcXVldWUodGhpcyxhKX0pfSxmaW5pc2g6ZnVuY3Rpb24oYSl7cmV0dXJuIGEhPT0hMSYmKGE9YXx8ImZ4IiksdGhpcy5lYWNoKGZ1bmN0aW9uKCl7dmFyIGIsYz1tLl9kYXRhKHRoaXMpLGQ9Y1thKyJxdWV1ZSJdLGU9Y1thKyJxdWV1ZUhvb2tzIl0sZj1tLnRpbWVycyxnPWQ/ZC5sZW5ndGg6MDtmb3IoYy5maW5pc2g9ITAsbS5xdWV1ZSh0aGlzLGEsW10pLGUmJmUuc3RvcCYmZS5zdG9wLmNhbGwodGhpcywhMCksYj1mLmxlbmd0aDtiLS07KWZbYl0uZWxlbT09PXRoaXMmJmZbYl0ucXVldWU9PT1hJiYoZltiXS5hbmltLnN0b3AoITApLGYuc3BsaWNlKGIsMSkpO2ZvcihiPTA7Zz5iO2IrKylkW2JdJiZkW2JdLmZpbmlzaCYmZFtiXS5maW5pc2guY2FsbCh0aGlzKTtkZWxldGUgYy5maW5pc2h9KX19KSxtLmVhY2goWyJ0b2dnbGUiLCJzaG93IiwiaGlkZSJdLGZ1bmN0aW9uKGEsYil7dmFyIGM9bS5mbltiXTttLmZuW2JdPWZ1bmN0aW9uKGEsZCxlKXtyZXR1cm4gbnVsbD09YXx8ImJvb2xlYW4iPT10eXBlb2YgYT9jLmFwcGx5KHRoaXMsYXJndW1lbnRzKTp0aGlzLmFuaW1hdGUoZ2IoYiwhMCksYSxkLGUpfX0pLG0uZWFjaCh7c2xpZGVEb3duOmdiKCJzaG93Iiksc2xpZGVVcDpnYigiaGlkZSIpLHNsaWRlVG9nZ2xlOmdiKCJ0b2dnbGUiKSxmYWRlSW46e29wYWNpdHk6InNob3cifSxmYWRlT3V0OntvcGFjaXR5OiJoaWRlIn0sZmFkZVRvZ2dsZTp7b3BhY2l0eToidG9nZ2xlIn19LGZ1bmN0aW9uKGEsYil7bS5mblthXT1mdW5jdGlvbihhLGMsZCl7cmV0dXJuIHRoaXMuYW5pbWF0ZShiLGEsYyxkKX19KSxtLnRpbWVycz1bXSxtLmZ4LnRpY2s9ZnVuY3Rpb24oKXt2YXIgYSxiPW0udGltZXJzLGM9MDtmb3IoJGE9bS5ub3coKTtjPGIubGVuZ3RoO2MrKylhPWJbY10sYSgpfHxiW2NdIT09YXx8Yi5zcGxpY2UoYy0tLDEpO2IubGVuZ3RofHxtLmZ4LnN0b3AoKSwkYT12b2lkIDB9LG0uZngudGltZXI9ZnVuY3Rpb24oYSl7bS50aW1lcnMucHVzaChhKSxhKCk/bS5meC5zdGFydCgpOm0udGltZXJzLnBvcCgpfSxtLmZ4LmludGVydmFsPTEzLG0uZnguc3RhcnQ9ZnVuY3Rpb24oKXtfYXx8KF9hPXNldEludGVydmFsKG0uZngudGljayxtLmZ4LmludGVydmFsKSl9LG0uZnguc3RvcD1mdW5jdGlvbigpe2NsZWFySW50ZXJ2YWwoX2EpLF9hPW51bGx9LG0uZnguc3BlZWRzPXtzbG93OjYwMCxmYXN0OjIwMCxfZGVmYXVsdDo0MDB9LG0uZm4uZGVsYXk9ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT1tLmZ4P20uZnguc3BlZWRzW2FdfHxhOmEsYj1ifHwiZngiLHRoaXMucXVldWUoYixmdW5jdGlvbihiLGMpe3ZhciBkPXNldFRpbWVvdXQoYixhKTtjLnN0b3A9ZnVuY3Rpb24oKXtjbGVhclRpbWVvdXQoZCl9fSl9LGZ1bmN0aW9uKCl7dmFyIGEsYixjLGQsZTtiPXkuY3JlYXRlRWxlbWVudCgiZGl2IiksYi5zZXRBdHRyaWJ1dGUoImNsYXNzTmFtZSIsInQiKSxiLmlubmVySFRNTD0iICA8bGluay8+PHRhYmxlPjwvdGFibGU+PGEgaHJlZj0nL2EnPmE8L2E+PGlucHV0IHR5cGU9J2NoZWNrYm94Jy8+IixkPWIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImEiKVswXSxjPXkuY3JlYXRlRWxlbWVudCgic2VsZWN0IiksZT1jLmFwcGVuZENoaWxkKHkuY3JlYXRlRWxlbWVudCgib3B0aW9uIikpLGE9Yi5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaW5wdXQiKVswXSxkLnN0eWxlLmNzc1RleHQ9InRvcDoxcHgiLGsuZ2V0U2V0QXR0cmlidXRlPSJ0IiE9PWIuY2xhc3NOYW1lLGsuc3R5bGU9L3RvcC8udGVzdChkLmdldEF0dHJpYnV0ZSgic3R5bGUiKSksay5ocmVmTm9ybWFsaXplZD0iL2EiPT09ZC5nZXRBdHRyaWJ1dGUoImhyZWYiKSxrLmNoZWNrT249ISFhLnZhbHVlLGsub3B0U2VsZWN0ZWQ9ZS5zZWxlY3RlZCxrLmVuY3R5cGU9ISF5LmNyZWF0ZUVsZW1lbnQoImZvcm0iKS5lbmN0eXBlLGMuZGlzYWJsZWQ9ITAsay5vcHREaXNhYmxlZD0hZS5kaXNhYmxlZCxhPXkuY3JlYXRlRWxlbWVudCgiaW5wdXQiKSxhLnNldEF0dHJpYnV0ZSgidmFsdWUiLCIiKSxrLmlucHV0PSIiPT09YS5nZXRBdHRyaWJ1dGUoInZhbHVlIiksYS52YWx1ZT0idCIsYS5zZXRBdHRyaWJ1dGUoInR5cGUiLCJyYWRpbyIpLGsucmFkaW9WYWx1ZT0idCI9PT1hLnZhbHVlfSgpO3ZhciBsYj0vXHIvZzttLmZuLmV4dGVuZCh7dmFsOmZ1bmN0aW9uKGEpe3ZhciBiLGMsZCxlPXRoaXNbMF07e2lmKGFyZ3VtZW50cy5sZW5ndGgpcmV0dXJuIGQ9bS5pc0Z1bmN0aW9uKGEpLHRoaXMuZWFjaChmdW5jdGlvbihjKXt2YXIgZTsxPT09dGhpcy5ub2RlVHlwZSYmKGU9ZD9hLmNhbGwodGhpcyxjLG0odGhpcykudmFsKCkpOmEsbnVsbD09ZT9lPSIiOiJudW1iZXIiPT10eXBlb2YgZT9lKz0iIjptLmlzQXJyYXkoZSkmJihlPW0ubWFwKGUsZnVuY3Rpb24oYSl7cmV0dXJuIG51bGw9PWE/IiI6YSsiIn0pKSxiPW0udmFsSG9va3NbdGhpcy50eXBlXXx8bS52YWxIb29rc1t0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldLGImJiJzZXQiaW4gYiYmdm9pZCAwIT09Yi5zZXQodGhpcyxlLCJ2YWx1ZSIpfHwodGhpcy52YWx1ZT1lKSl9KTtpZihlKXJldHVybiBiPW0udmFsSG9va3NbZS50eXBlXXx8bS52YWxIb29rc1tlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCldLGImJiJnZXQiaW4gYiYmdm9pZCAwIT09KGM9Yi5nZXQoZSwidmFsdWUiKSk/YzooYz1lLnZhbHVlLCJzdHJpbmciPT10eXBlb2YgYz9jLnJlcGxhY2UobGIsIiIpOm51bGw9PWM/IiI6Yyl9fX0pLG0uZXh0ZW5kKHt2YWxIb29rczp7b3B0aW9uOntnZXQ6ZnVuY3Rpb24oYSl7dmFyIGI9bS5maW5kLmF0dHIoYSwidmFsdWUiKTtyZXR1cm4gbnVsbCE9Yj9iOm0udHJpbShtLnRleHQoYSkpfX0sc2VsZWN0OntnZXQ6ZnVuY3Rpb24oYSl7Zm9yKHZhciBiLGMsZD1hLm9wdGlvbnMsZT1hLnNlbGVjdGVkSW5kZXgsZj0ic2VsZWN0LW9uZSI9PT1hLnR5cGV8fDA+ZSxnPWY/bnVsbDpbXSxoPWY/ZSsxOmQubGVuZ3RoLGk9MD5lP2g6Zj9lOjA7aD5pO2krKylpZihjPWRbaV0sISghYy5zZWxlY3RlZCYmaSE9PWV8fChrLm9wdERpc2FibGVkP2MuZGlzYWJsZWQ6bnVsbCE9PWMuZ2V0QXR0cmlidXRlKCJkaXNhYmxlZCIpKXx8Yy5wYXJlbnROb2RlLmRpc2FibGVkJiZtLm5vZGVOYW1lKGMucGFyZW50Tm9kZSwib3B0Z3JvdXAiKSkpe2lmKGI9bShjKS52YWwoKSxmKXJldHVybiBiO2cucHVzaChiKX1yZXR1cm4gZ30sc2V0OmZ1bmN0aW9uKGEsYil7dmFyIGMsZCxlPWEub3B0aW9ucyxmPW0ubWFrZUFycmF5KGIpLGc9ZS5sZW5ndGg7d2hpbGUoZy0tKWlmKGQ9ZVtnXSxtLmluQXJyYXkobS52YWxIb29rcy5vcHRpb24uZ2V0KGQpLGYpPj0wKXRyeXtkLnNlbGVjdGVkPWM9ITB9Y2F0Y2goaCl7ZC5zY3JvbGxIZWlnaHR9ZWxzZSBkLnNlbGVjdGVkPSExO3JldHVybiBjfHwoYS5zZWxlY3RlZEluZGV4PS0xKSxlfX19fSksbS5lYWNoKFsicmFkaW8iLCJjaGVja2JveCJdLGZ1bmN0aW9uKCl7bS52YWxIb29rc1t0aGlzXT17c2V0OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG0uaXNBcnJheShiKT9hLmNoZWNrZWQ9bS5pbkFycmF5KG0oYSkudmFsKCksYik+PTA6dm9pZCAwfX0say5jaGVja09ufHwobS52YWxIb29rc1t0aGlzXS5nZXQ9ZnVuY3Rpb24oYSl7cmV0dXJuIG51bGw9PT1hLmdldEF0dHJpYnV0ZSgidmFsdWUiKT8ib24iOmEudmFsdWV9KX0pO3ZhciBtYixuYixvYj1tLmV4cHIuYXR0ckhhbmRsZSxwYj0vXig/OmNoZWNrZWR8c2VsZWN0ZWQpJC9pLHFiPWsuZ2V0U2V0QXR0cmlidXRlLHJiPWsuaW5wdXQ7bS5mbi5leHRlbmQoe2F0dHI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gVih0aGlzLG0uYXR0cixhLGIsYXJndW1lbnRzLmxlbmd0aD4xKX0scmVtb3ZlQXR0cjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKCl7bS5yZW1vdmVBdHRyKHRoaXMsYSl9KX19KSxtLmV4dGVuZCh7YXR0cjpmdW5jdGlvbihhLGIsYyl7dmFyIGQsZSxmPWEubm9kZVR5cGU7aWYoYSYmMyE9PWYmJjghPT1mJiYyIT09ZilyZXR1cm4gdHlwZW9mIGEuZ2V0QXR0cmlidXRlPT09Sz9tLnByb3AoYSxiLGMpOigxPT09ZiYmbS5pc1hNTERvYyhhKXx8KGI9Yi50b0xvd2VyQ2FzZSgpLGQ9bS5hdHRySG9va3NbYl18fChtLmV4cHIubWF0Y2guYm9vbC50ZXN0KGIpP25iOm1iKSksdm9pZCAwPT09Yz9kJiYiZ2V0ImluIGQmJm51bGwhPT0oZT1kLmdldChhLGIpKT9lOihlPW0uZmluZC5hdHRyKGEsYiksbnVsbD09ZT92b2lkIDA6ZSk6bnVsbCE9PWM/ZCYmInNldCJpbiBkJiZ2b2lkIDAhPT0oZT1kLnNldChhLGMsYikpP2U6KGEuc2V0QXR0cmlidXRlKGIsYysiIiksYyk6dm9pZCBtLnJlbW92ZUF0dHIoYSxiKSl9LHJlbW92ZUF0dHI6ZnVuY3Rpb24oYSxiKXt2YXIgYyxkLGU9MCxmPWImJmIubWF0Y2goRSk7aWYoZiYmMT09PWEubm9kZVR5cGUpd2hpbGUoYz1mW2UrK10pZD1tLnByb3BGaXhbY118fGMsbS5leHByLm1hdGNoLmJvb2wudGVzdChjKT9yYiYmcWJ8fCFwYi50ZXN0KGMpP2FbZF09ITE6YVttLmNhbWVsQ2FzZSgiZGVmYXVsdC0iK2MpXT1hW2RdPSExOm0uYXR0cihhLGMsIiIpLGEucmVtb3ZlQXR0cmlidXRlKHFiP2M6ZCl9LGF0dHJIb29rczp7dHlwZTp7c2V0OmZ1bmN0aW9uKGEsYil7aWYoIWsucmFkaW9WYWx1ZSYmInJhZGlvIj09PWImJm0ubm9kZU5hbWUoYSwiaW5wdXQiKSl7dmFyIGM9YS52YWx1ZTtyZXR1cm4gYS5zZXRBdHRyaWJ1dGUoInR5cGUiLGIpLGMmJihhLnZhbHVlPWMpLGJ9fX19fSksbmI9e3NldDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGI9PT0hMT9tLnJlbW92ZUF0dHIoYSxjKTpyYiYmcWJ8fCFwYi50ZXN0KGMpP2Euc2V0QXR0cmlidXRlKCFxYiYmbS5wcm9wRml4W2NdfHxjLGMpOmFbbS5jYW1lbENhc2UoImRlZmF1bHQtIitjKV09YVtjXT0hMCxjfX0sbS5lYWNoKG0uZXhwci5tYXRjaC5ib29sLnNvdXJjZS5tYXRjaCgvXHcrL2cpLGZ1bmN0aW9uKGEsYil7dmFyIGM9b2JbYl18fG0uZmluZC5hdHRyO29iW2JdPXJiJiZxYnx8IXBiLnRlc3QoYik/ZnVuY3Rpb24oYSxiLGQpe3ZhciBlLGY7cmV0dXJuIGR8fChmPW9iW2JdLG9iW2JdPWUsZT1udWxsIT1jKGEsYixkKT9iLnRvTG93ZXJDYXNlKCk6bnVsbCxvYltiXT1mKSxlfTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGM/dm9pZCAwOmFbbS5jYW1lbENhc2UoImRlZmF1bHQtIitiKV0/Yi50b0xvd2VyQ2FzZSgpOm51bGx9fSkscmImJnFifHwobS5hdHRySG9va3MudmFsdWU9e3NldDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG0ubm9kZU5hbWUoYSwiaW5wdXQiKT92b2lkKGEuZGVmYXVsdFZhbHVlPWIpOm1iJiZtYi5zZXQoYSxiLGMpfX0pLHFifHwobWI9e3NldDpmdW5jdGlvbihhLGIsYyl7dmFyIGQ9YS5nZXRBdHRyaWJ1dGVOb2RlKGMpO3JldHVybiBkfHxhLnNldEF0dHJpYnV0ZU5vZGUoZD1hLm93bmVyRG9jdW1lbnQuY3JlYXRlQXR0cmlidXRlKGMpKSxkLnZhbHVlPWIrPSIiLCJ2YWx1ZSI9PT1jfHxiPT09YS5nZXRBdHRyaWJ1dGUoYyk/Yjp2b2lkIDB9fSxvYi5pZD1vYi5uYW1lPW9iLmNvb3Jkcz1mdW5jdGlvbihhLGIsYyl7dmFyIGQ7cmV0dXJuIGM/dm9pZCAwOihkPWEuZ2V0QXR0cmlidXRlTm9kZShiKSkmJiIiIT09ZC52YWx1ZT9kLnZhbHVlOm51bGx9LG0udmFsSG9va3MuYnV0dG9uPXtnZXQ6ZnVuY3Rpb24oYSxiKXt2YXIgYz1hLmdldEF0dHJpYnV0ZU5vZGUoYik7cmV0dXJuIGMmJmMuc3BlY2lmaWVkP2MudmFsdWU6dm9pZCAwfSxzZXQ6bWIuc2V0fSxtLmF0dHJIb29rcy5jb250ZW50ZWRpdGFibGU9e3NldDpmdW5jdGlvbihhLGIsYyl7bWIuc2V0KGEsIiI9PT1iPyExOmIsYyl9fSxtLmVhY2goWyJ3aWR0aCIsImhlaWdodCJdLGZ1bmN0aW9uKGEsYil7bS5hdHRySG9va3NbYl09e3NldDpmdW5jdGlvbihhLGMpe3JldHVybiIiPT09Yz8oYS5zZXRBdHRyaWJ1dGUoYiwiYXV0byIpLGMpOnZvaWQgMH19fSkpLGsuc3R5bGV8fChtLmF0dHJIb29rcy5zdHlsZT17Z2V0OmZ1bmN0aW9uKGEpe3JldHVybiBhLnN0eWxlLmNzc1RleHR8fHZvaWQgMH0sc2V0OmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuc3R5bGUuY3NzVGV4dD1iKyIifX0pO3ZhciBzYj0vXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b258b2JqZWN0KSQvaSx0Yj0vXig/OmF8YXJlYSkkL2k7bS5mbi5leHRlbmQoe3Byb3A6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gVih0aGlzLG0ucHJvcCxhLGIsYXJndW1lbnRzLmxlbmd0aD4xKX0scmVtb3ZlUHJvcDpmdW5jdGlvbihhKXtyZXR1cm4gYT1tLnByb3BGaXhbYV18fGEsdGhpcy5lYWNoKGZ1bmN0aW9uKCl7dHJ5e3RoaXNbYV09dm9pZCAwLGRlbGV0ZSB0aGlzW2FdfWNhdGNoKGIpe319KX19KSxtLmV4dGVuZCh7cHJvcEZpeDp7ImZvciI6Imh0bWxGb3IiLCJjbGFzcyI6ImNsYXNzTmFtZSJ9LHByb3A6ZnVuY3Rpb24oYSxiLGMpe3ZhciBkLGUsZixnPWEubm9kZVR5cGU7aWYoYSYmMyE9PWcmJjghPT1nJiYyIT09ZylyZXR1cm4gZj0xIT09Z3x8IW0uaXNYTUxEb2MoYSksZiYmKGI9bS5wcm9wRml4W2JdfHxiLGU9bS5wcm9wSG9va3NbYl0pLHZvaWQgMCE9PWM/ZSYmInNldCJpbiBlJiZ2b2lkIDAhPT0oZD1lLnNldChhLGMsYikpP2Q6YVtiXT1jOmUmJiJnZXQiaW4gZSYmbnVsbCE9PShkPWUuZ2V0KGEsYikpP2Q6YVtiXX0scHJvcEhvb2tzOnt0YWJJbmRleDp7Z2V0OmZ1bmN0aW9uKGEpe3ZhciBiPW0uZmluZC5hdHRyKGEsInRhYmluZGV4Iik7cmV0dXJuIGI/cGFyc2VJbnQoYiwxMCk6c2IudGVzdChhLm5vZGVOYW1lKXx8dGIudGVzdChhLm5vZGVOYW1lKSYmYS5ocmVmPzA6LTF9fX19KSxrLmhyZWZOb3JtYWxpemVkfHxtLmVhY2goWyJocmVmIiwic3JjIl0sZnVuY3Rpb24oYSxiKXttLnByb3BIb29rc1tiXT17Z2V0OmZ1bmN0aW9uKGEpe3JldHVybiBhLmdldEF0dHJpYnV0ZShiLDQpfX19KSxrLm9wdFNlbGVjdGVkfHwobS5wcm9wSG9va3Muc2VsZWN0ZWQ9e2dldDpmdW5jdGlvbihhKXt2YXIgYj1hLnBhcmVudE5vZGU7cmV0dXJuIGImJihiLnNlbGVjdGVkSW5kZXgsYi5wYXJlbnROb2RlJiZiLnBhcmVudE5vZGUuc2VsZWN0ZWRJbmRleCksbnVsbH19KSxtLmVhY2goWyJ0YWJJbmRleCIsInJlYWRPbmx5IiwibWF4TGVuZ3RoIiwiY2VsbFNwYWNpbmciLCJjZWxsUGFkZGluZyIsInJvd1NwYW4iLCJjb2xTcGFuIiwidXNlTWFwIiwiZnJhbWVCb3JkZXIiLCJjb250ZW50RWRpdGFibGUiXSxmdW5jdGlvbigpe20ucHJvcEZpeFt0aGlzLnRvTG93ZXJDYXNlKCldPXRoaXN9KSxrLmVuY3R5cGV8fChtLnByb3BGaXguZW5jdHlwZT0iZW5jb2RpbmciKTt2YXIgdWI9L1tcdFxyXG5cZl0vZzttLmZuLmV4dGVuZCh7YWRkQ2xhc3M6ZnVuY3Rpb24oYSl7dmFyIGIsYyxkLGUsZixnLGg9MCxpPXRoaXMubGVuZ3RoLGo9InN0cmluZyI9PXR5cGVvZiBhJiZhO2lmKG0uaXNGdW5jdGlvbihhKSlyZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uKGIpe20odGhpcykuYWRkQ2xhc3MoYS5jYWxsKHRoaXMsYix0aGlzLmNsYXNzTmFtZSkpfSk7aWYoailmb3IoYj0oYXx8IiIpLm1hdGNoKEUpfHxbXTtpPmg7aCsrKWlmKGM9dGhpc1toXSxkPTE9PT1jLm5vZGVUeXBlJiYoYy5jbGFzc05hbWU/KCIgIitjLmNsYXNzTmFtZSsiICIpLnJlcGxhY2UodWIsIiAiKToiICIpKXtmPTA7d2hpbGUoZT1iW2YrK10pZC5pbmRleE9mKCIgIitlKyIgIik8MCYmKGQrPWUrIiAiKTtnPW0udHJpbShkKSxjLmNsYXNzTmFtZSE9PWcmJihjLmNsYXNzTmFtZT1nKX1yZXR1cm4gdGhpc30scmVtb3ZlQ2xhc3M6ZnVuY3Rpb24oYSl7dmFyIGIsYyxkLGUsZixnLGg9MCxpPXRoaXMubGVuZ3RoLGo9MD09PWFyZ3VtZW50cy5sZW5ndGh8fCJzdHJpbmciPT10eXBlb2YgYSYmYTtpZihtLmlzRnVuY3Rpb24oYSkpcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihiKXttKHRoaXMpLnJlbW92ZUNsYXNzKGEuY2FsbCh0aGlzLGIsdGhpcy5jbGFzc05hbWUpKX0pO2lmKGopZm9yKGI9KGF8fCIiKS5tYXRjaChFKXx8W107aT5oO2grKylpZihjPXRoaXNbaF0sZD0xPT09Yy5ub2RlVHlwZSYmKGMuY2xhc3NOYW1lPygiICIrYy5jbGFzc05hbWUrIiAiKS5yZXBsYWNlKHViLCIgIik6IiIpKXtmPTA7d2hpbGUoZT1iW2YrK10pd2hpbGUoZC5pbmRleE9mKCIgIitlKyIgIik+PTApZD1kLnJlcGxhY2UoIiAiK2UrIiAiLCIgIik7Zz1hP20udHJpbShkKToiIixjLmNsYXNzTmFtZSE9PWcmJihjLmNsYXNzTmFtZT1nKX1yZXR1cm4gdGhpc30sdG9nZ2xlQ2xhc3M6ZnVuY3Rpb24oYSxiKXt2YXIgYz10eXBlb2YgYTtyZXR1cm4iYm9vbGVhbiI9PXR5cGVvZiBiJiYic3RyaW5nIj09PWM/Yj90aGlzLmFkZENsYXNzKGEpOnRoaXMucmVtb3ZlQ2xhc3MoYSk6dGhpcy5lYWNoKG0uaXNGdW5jdGlvbihhKT9mdW5jdGlvbihjKXttKHRoaXMpLnRvZ2dsZUNsYXNzKGEuY2FsbCh0aGlzLGMsdGhpcy5jbGFzc05hbWUsYiksYil9OmZ1bmN0aW9uKCl7aWYoInN0cmluZyI9PT1jKXt2YXIgYixkPTAsZT1tKHRoaXMpLGY9YS5tYXRjaChFKXx8W107d2hpbGUoYj1mW2QrK10pZS5oYXNDbGFzcyhiKT9lLnJlbW92ZUNsYXNzKGIpOmUuYWRkQ2xhc3MoYil9ZWxzZShjPT09S3x8ImJvb2xlYW4iPT09YykmJih0aGlzLmNsYXNzTmFtZSYmbS5fZGF0YSh0aGlzLCJfX2NsYXNzTmFtZV9fIix0aGlzLmNsYXNzTmFtZSksdGhpcy5jbGFzc05hbWU9dGhpcy5jbGFzc05hbWV8fGE9PT0hMT8iIjptLl9kYXRhKHRoaXMsIl9fY2xhc3NOYW1lX18iKXx8IiIpfSl9LGhhc0NsYXNzOmZ1bmN0aW9uKGEpe2Zvcih2YXIgYj0iICIrYSsiICIsYz0wLGQ9dGhpcy5sZW5ndGg7ZD5jO2MrKylpZigxPT09dGhpc1tjXS5ub2RlVHlwZSYmKCIgIit0aGlzW2NdLmNsYXNzTmFtZSsiICIpLnJlcGxhY2UodWIsIiAiKS5pbmRleE9mKGIpPj0wKXJldHVybiEwO3JldHVybiExfX0pLG0uZWFjaCgiYmx1ciBmb2N1cyBmb2N1c2luIGZvY3Vzb3V0IGxvYWQgcmVzaXplIHNjcm9sbCB1bmxvYWQgY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgY2hhbmdlIHNlbGVjdCBzdWJtaXQga2V5ZG93biBrZXlwcmVzcyBrZXl1cCBlcnJvciBjb250ZXh0bWVudSIuc3BsaXQoIiAiKSxmdW5jdGlvbihhLGIpe20uZm5bYl09ZnVuY3Rpb24oYSxjKXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aD4wP3RoaXMub24oYixudWxsLGEsYyk6dGhpcy50cmlnZ2VyKGIpfX0pLG0uZm4uZXh0ZW5kKHtob3ZlcjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLm1vdXNlZW50ZXIoYSkubW91c2VsZWF2ZShifHxhKX0sYmluZDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHRoaXMub24oYSxudWxsLGIsYyl9LHVuYmluZDpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLm9mZihhLG51bGwsYil9LGRlbGVnYXRlOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiB0aGlzLm9uKGIsYSxjLGQpfSx1bmRlbGVnYXRlOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gMT09PWFyZ3VtZW50cy5sZW5ndGg/dGhpcy5vZmYoYSwiKioiKTp0aGlzLm9mZihiLGF8fCIqKiIsYyl9fSk7dmFyIHZiPW0ubm93KCksd2I9L1w/Lyx4Yj0vKCwpfChcW3x7KXwofXxdKXwiKD86W14iXFxcclxuXXxcXFsiXFxcL2JmbnJ0XXxcXHVbXGRhLWZBLUZdezR9KSoiXHMqOj98dHJ1ZXxmYWxzZXxudWxsfC0/KD8hMFxkKVxkKyg/OlwuXGQrfCkoPzpbZUVdWystXT9cZCt8KS9nO20ucGFyc2VKU09OPWZ1bmN0aW9uKGIpe2lmKGEuSlNPTiYmYS5KU09OLnBhcnNlKXJldHVybiBhLkpTT04ucGFyc2UoYisiIik7dmFyIGMsZD1udWxsLGU9bS50cmltKGIrIiIpO3JldHVybiBlJiYhbS50cmltKGUucmVwbGFjZSh4YixmdW5jdGlvbihhLGIsZSxmKXtyZXR1cm4gYyYmYiYmKGQ9MCksMD09PWQ/YTooYz1lfHxiLGQrPSFmLSFlLCIiKX0pKT9GdW5jdGlvbigicmV0dXJuICIrZSkoKTptLmVycm9yKCJJbnZhbGlkIEpTT046ICIrYil9LG0ucGFyc2VYTUw9ZnVuY3Rpb24oYil7dmFyIGMsZDtpZighYnx8InN0cmluZyIhPXR5cGVvZiBiKXJldHVybiBudWxsO3RyeXthLkRPTVBhcnNlcj8oZD1uZXcgRE9NUGFyc2VyLGM9ZC5wYXJzZUZyb21TdHJpbmcoYiwidGV4dC94bWwiKSk6KGM9bmV3IEFjdGl2ZVhPYmplY3QoIk1pY3Jvc29mdC5YTUxET00iKSxjLmFzeW5jPSJmYWxzZSIsYy5sb2FkWE1MKGIpKX1jYXRjaChlKXtjPXZvaWQgMH1yZXR1cm4gYyYmYy5kb2N1bWVudEVsZW1lbnQmJiFjLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJwYXJzZXJlcnJvciIpLmxlbmd0aHx8bS5lcnJvcigiSW52YWxpZCBYTUw6ICIrYiksY307dmFyIHliLHpiLEFiPS8jLiokLyxCYj0vKFs/Jl0pXz1bXiZdKi8sQ2I9L14oLio/KTpbIFx0XSooW15cclxuXSopXHI/JC9nbSxEYj0vXig/OmFib3V0fGFwcHxhcHAtc3RvcmFnZXwuKy1leHRlbnNpb258ZmlsZXxyZXN8d2lkZ2V0KTokLyxFYj0vXig/OkdFVHxIRUFEKSQvLEZiPS9eXC9cLy8sR2I9L14oW1x3ListXSs6KSg/OlwvXC8oPzpbXlwvPyNdKkB8KShbXlwvPyM6XSopKD86OihcZCspfCl8KS8sSGI9e30sSWI9e30sSmI9IiovIi5jb25jYXQoIioiKTt0cnl7emI9bG9jYXRpb24uaHJlZn1jYXRjaChLYil7emI9eS5jcmVhdGVFbGVtZW50KCJhIiksemIuaHJlZj0iIix6Yj16Yi5ocmVmfXliPUdiLmV4ZWMoemIudG9Mb3dlckNhc2UoKSl8fFtdO2Z1bmN0aW9uIExiKGEpe3JldHVybiBmdW5jdGlvbihiLGMpeyJzdHJpbmciIT10eXBlb2YgYiYmKGM9YixiPSIqIik7dmFyIGQsZT0wLGY9Yi50b0xvd2VyQ2FzZSgpLm1hdGNoKEUpfHxbXTtpZihtLmlzRnVuY3Rpb24oYykpd2hpbGUoZD1mW2UrK10pIisiPT09ZC5jaGFyQXQoMCk/KGQ9ZC5zbGljZSgxKXx8IioiLChhW2RdPWFbZF18fFtdKS51bnNoaWZ0KGMpKTooYVtkXT1hW2RdfHxbXSkucHVzaChjKX19ZnVuY3Rpb24gTWIoYSxiLGMsZCl7dmFyIGU9e30sZj1hPT09SWI7ZnVuY3Rpb24gZyhoKXt2YXIgaTtyZXR1cm4gZVtoXT0hMCxtLmVhY2goYVtoXXx8W10sZnVuY3Rpb24oYSxoKXt2YXIgaj1oKGIsYyxkKTtyZXR1cm4ic3RyaW5nIiE9dHlwZW9mIGp8fGZ8fGVbal0/Zj8hKGk9aik6dm9pZCAwOihiLmRhdGFUeXBlcy51bnNoaWZ0KGopLGcoaiksITEpfSksaX1yZXR1cm4gZyhiLmRhdGFUeXBlc1swXSl8fCFlWyIqIl0mJmcoIioiKX1mdW5jdGlvbiBOYihhLGIpe3ZhciBjLGQsZT1tLmFqYXhTZXR0aW5ncy5mbGF0T3B0aW9uc3x8e307Zm9yKGQgaW4gYil2b2lkIDAhPT1iW2RdJiYoKGVbZF0/YTpjfHwoYz17fSkpW2RdPWJbZF0pO3JldHVybiBjJiZtLmV4dGVuZCghMCxhLGMpLGF9ZnVuY3Rpb24gT2IoYSxiLGMpe3ZhciBkLGUsZixnLGg9YS5jb250ZW50cyxpPWEuZGF0YVR5cGVzO3doaWxlKCIqIj09PWlbMF0paS5zaGlmdCgpLHZvaWQgMD09PWUmJihlPWEubWltZVR5cGV8fGIuZ2V0UmVzcG9uc2VIZWFkZXIoIkNvbnRlbnQtVHlwZSIpKTtpZihlKWZvcihnIGluIGgpaWYoaFtnXSYmaFtnXS50ZXN0KGUpKXtpLnVuc2hpZnQoZyk7YnJlYWt9aWYoaVswXWluIGMpZj1pWzBdO2Vsc2V7Zm9yKGcgaW4gYyl7aWYoIWlbMF18fGEuY29udmVydGVyc1tnKyIgIitpWzBdXSl7Zj1nO2JyZWFrfWR8fChkPWcpfWY9Znx8ZH1yZXR1cm4gZj8oZiE9PWlbMF0mJmkudW5zaGlmdChmKSxjW2ZdKTp2b2lkIDB9ZnVuY3Rpb24gUGIoYSxiLGMsZCl7dmFyIGUsZixnLGgsaSxqPXt9LGs9YS5kYXRhVHlwZXMuc2xpY2UoKTtpZihrWzFdKWZvcihnIGluIGEuY29udmVydGVycylqW2cudG9Mb3dlckNhc2UoKV09YS5jb252ZXJ0ZXJzW2ddO2Y9ay5zaGlmdCgpO3doaWxlKGYpaWYoYS5yZXNwb25zZUZpZWxkc1tmXSYmKGNbYS5yZXNwb25zZUZpZWxkc1tmXV09YiksIWkmJmQmJmEuZGF0YUZpbHRlciYmKGI9YS5kYXRhRmlsdGVyKGIsYS5kYXRhVHlwZSkpLGk9ZixmPWsuc2hpZnQoKSlpZigiKiI9PT1mKWY9aTtlbHNlIGlmKCIqIiE9PWkmJmkhPT1mKXtpZihnPWpbaSsiICIrZl18fGpbIiogIitmXSwhZylmb3IoZSBpbiBqKWlmKGg9ZS5zcGxpdCgiICIpLGhbMV09PT1mJiYoZz1qW2krIiAiK2hbMF1dfHxqWyIqICIraFswXV0pKXtnPT09ITA/Zz1qW2VdOmpbZV0hPT0hMCYmKGY9aFswXSxrLnVuc2hpZnQoaFsxXSkpO2JyZWFrfWlmKGchPT0hMClpZihnJiZhWyJ0aHJvd3MiXSliPWcoYik7ZWxzZSB0cnl7Yj1nKGIpfWNhdGNoKGwpe3JldHVybntzdGF0ZToicGFyc2VyZXJyb3IiLGVycm9yOmc/bDoiTm8gY29udmVyc2lvbiBmcm9tICIraSsiIHRvICIrZn19fXJldHVybntzdGF0ZToic3VjY2VzcyIsZGF0YTpifX1tLmV4dGVuZCh7YWN0aXZlOjAsbGFzdE1vZGlmaWVkOnt9LGV0YWc6e30sYWpheFNldHRpbmdzOnt1cmw6emIsdHlwZToiR0VUIixpc0xvY2FsOkRiLnRlc3QoeWJbMV0pLGdsb2JhbDohMCxwcm9jZXNzRGF0YTohMCxhc3luYzohMCxjb250ZW50VHlwZToiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkOyBjaGFyc2V0PVVURi04IixhY2NlcHRzOnsiKiI6SmIsdGV4dDoidGV4dC9wbGFpbiIsaHRtbDoidGV4dC9odG1sIix4bWw6ImFwcGxpY2F0aW9uL3htbCwgdGV4dC94bWwiLGpzb246ImFwcGxpY2F0aW9uL2pzb24sIHRleHQvamF2YXNjcmlwdCJ9LGNvbnRlbnRzOnt4bWw6L3htbC8saHRtbDovaHRtbC8sanNvbjovanNvbi99LHJlc3BvbnNlRmllbGRzOnt4bWw6InJlc3BvbnNlWE1MIix0ZXh0OiJyZXNwb25zZVRleHQiLGpzb246InJlc3BvbnNlSlNPTiJ9LGNvbnZlcnRlcnM6eyIqIHRleHQiOlN0cmluZywidGV4dCBodG1sIjohMCwidGV4dCBqc29uIjptLnBhcnNlSlNPTiwidGV4dCB4bWwiOm0ucGFyc2VYTUx9LGZsYXRPcHRpb25zOnt1cmw6ITAsY29udGV4dDohMH19LGFqYXhTZXR1cDpmdW5jdGlvbihhLGIpe3JldHVybiBiP05iKE5iKGEsbS5hamF4U2V0dGluZ3MpLGIpOk5iKG0uYWpheFNldHRpbmdzLGEpfSxhamF4UHJlZmlsdGVyOkxiKEhiKSxhamF4VHJhbnNwb3J0OkxiKEliKSxhamF4OmZ1bmN0aW9uKGEsYil7Im9iamVjdCI9PXR5cGVvZiBhJiYoYj1hLGE9dm9pZCAwKSxiPWJ8fHt9O3ZhciBjLGQsZSxmLGcsaCxpLGosaz1tLmFqYXhTZXR1cCh7fSxiKSxsPWsuY29udGV4dHx8ayxuPWsuY29udGV4dCYmKGwubm9kZVR5cGV8fGwuanF1ZXJ5KT9tKGwpOm0uZXZlbnQsbz1tLkRlZmVycmVkKCkscD1tLkNhbGxiYWNrcygib25jZSBtZW1vcnkiKSxxPWsuc3RhdHVzQ29kZXx8e30scj17fSxzPXt9LHQ9MCx1PSJjYW5jZWxlZCIsdj17cmVhZHlTdGF0ZTowLGdldFJlc3BvbnNlSGVhZGVyOmZ1bmN0aW9uKGEpe3ZhciBiO2lmKDI9PT10KXtpZighail7aj17fTt3aGlsZShiPUNiLmV4ZWMoZikpaltiWzFdLnRvTG93ZXJDYXNlKCldPWJbMl19Yj1qW2EudG9Mb3dlckNhc2UoKV19cmV0dXJuIG51bGw9PWI/bnVsbDpifSxnZXRBbGxSZXNwb25zZUhlYWRlcnM6ZnVuY3Rpb24oKXtyZXR1cm4gMj09PXQ/ZjpudWxsfSxzZXRSZXF1ZXN0SGVhZGVyOmZ1bmN0aW9uKGEsYil7dmFyIGM9YS50b0xvd2VyQ2FzZSgpO3JldHVybiB0fHwoYT1zW2NdPXNbY118fGEsclthXT1iKSx0aGlzfSxvdmVycmlkZU1pbWVUeXBlOmZ1bmN0aW9uKGEpe3JldHVybiB0fHwoay5taW1lVHlwZT1hKSx0aGlzfSxzdGF0dXNDb2RlOmZ1bmN0aW9uKGEpe3ZhciBiO2lmKGEpaWYoMj50KWZvcihiIGluIGEpcVtiXT1bcVtiXSxhW2JdXTtlbHNlIHYuYWx3YXlzKGFbdi5zdGF0dXNdKTtyZXR1cm4gdGhpc30sYWJvcnQ6ZnVuY3Rpb24oYSl7dmFyIGI9YXx8dTtyZXR1cm4gaSYmaS5hYm9ydChiKSx4KDAsYiksdGhpc319O2lmKG8ucHJvbWlzZSh2KS5jb21wbGV0ZT1wLmFkZCx2LnN1Y2Nlc3M9di5kb25lLHYuZXJyb3I9di5mYWlsLGsudXJsPSgoYXx8ay51cmx8fHpiKSsiIikucmVwbGFjZShBYiwiIikucmVwbGFjZShGYix5YlsxXSsiLy8iKSxrLnR5cGU9Yi5tZXRob2R8fGIudHlwZXx8ay5tZXRob2R8fGsudHlwZSxrLmRhdGFUeXBlcz1tLnRyaW0oay5kYXRhVHlwZXx8IioiKS50b0xvd2VyQ2FzZSgpLm1hdGNoKEUpfHxbIiJdLG51bGw9PWsuY3Jvc3NEb21haW4mJihjPUdiLmV4ZWMoay51cmwudG9Mb3dlckNhc2UoKSksay5jcm9zc0RvbWFpbj0hKCFjfHxjWzFdPT09eWJbMV0mJmNbMl09PT15YlsyXSYmKGNbM118fCgiaHR0cDoiPT09Y1sxXT8iODAiOiI0NDMiKSk9PT0oeWJbM118fCgiaHR0cDoiPT09eWJbMV0/IjgwIjoiNDQzIikpKSksay5kYXRhJiZrLnByb2Nlc3NEYXRhJiYic3RyaW5nIiE9dHlwZW9mIGsuZGF0YSYmKGsuZGF0YT1tLnBhcmFtKGsuZGF0YSxrLnRyYWRpdGlvbmFsKSksTWIoSGIsayxiLHYpLDI9PT10KXJldHVybiB2O2g9bS5ldmVudCYmay5nbG9iYWwsaCYmMD09PW0uYWN0aXZlKysmJm0uZXZlbnQudHJpZ2dlcigiYWpheFN0YXJ0Iiksay50eXBlPWsudHlwZS50b1VwcGVyQ2FzZSgpLGsuaGFzQ29udGVudD0hRWIudGVzdChrLnR5cGUpLGU9ay51cmwsay5oYXNDb250ZW50fHwoay5kYXRhJiYoZT1rLnVybCs9KHdiLnRlc3QoZSk/IiYiOiI/Iikray5kYXRhLGRlbGV0ZSBrLmRhdGEpLGsuY2FjaGU9PT0hMSYmKGsudXJsPUJiLnRlc3QoZSk/ZS5yZXBsYWNlKEJiLCIkMV89Iit2YisrKTplKyh3Yi50ZXN0KGUpPyImIjoiPyIpKyJfPSIrdmIrKykpLGsuaWZNb2RpZmllZCYmKG0ubGFzdE1vZGlmaWVkW2VdJiZ2LnNldFJlcXVlc3RIZWFkZXIoIklmLU1vZGlmaWVkLVNpbmNlIixtLmxhc3RNb2RpZmllZFtlXSksbS5ldGFnW2VdJiZ2LnNldFJlcXVlc3RIZWFkZXIoIklmLU5vbmUtTWF0Y2giLG0uZXRhZ1tlXSkpLChrLmRhdGEmJmsuaGFzQ29udGVudCYmay5jb250ZW50VHlwZSE9PSExfHxiLmNvbnRlbnRUeXBlKSYmdi5zZXRSZXF1ZXN0SGVhZGVyKCJDb250ZW50LVR5cGUiLGsuY29udGVudFR5cGUpLHYuc2V0UmVxdWVzdEhlYWRlcigiQWNjZXB0IixrLmRhdGFUeXBlc1swXSYmay5hY2NlcHRzW2suZGF0YVR5cGVzWzBdXT9rLmFjY2VwdHNbay5kYXRhVHlwZXNbMF1dKygiKiIhPT1rLmRhdGFUeXBlc1swXT8iLCAiK0piKyI7IHE9MC4wMSI6IiIpOmsuYWNjZXB0c1siKiJdKTtmb3IoZCBpbiBrLmhlYWRlcnMpdi5zZXRSZXF1ZXN0SGVhZGVyKGQsay5oZWFkZXJzW2RdKTtpZihrLmJlZm9yZVNlbmQmJihrLmJlZm9yZVNlbmQuY2FsbChsLHYsayk9PT0hMXx8Mj09PXQpKXJldHVybiB2LmFib3J0KCk7dT0iYWJvcnQiO2ZvcihkIGlue3N1Y2Nlc3M6MSxlcnJvcjoxLGNvbXBsZXRlOjF9KXZbZF0oa1tkXSk7aWYoaT1NYihJYixrLGIsdikpe3YucmVhZHlTdGF0ZT0xLGgmJm4udHJpZ2dlcigiYWpheFNlbmQiLFt2LGtdKSxrLmFzeW5jJiZrLnRpbWVvdXQ+MCYmKGc9c2V0VGltZW91dChmdW5jdGlvbigpe3YuYWJvcnQoInRpbWVvdXQiKX0say50aW1lb3V0KSk7dHJ5e3Q9MSxpLnNlbmQocix4KX1jYXRjaCh3KXtpZighKDI+dCkpdGhyb3cgdzt4KC0xLHcpfX1lbHNlIHgoLTEsIk5vIFRyYW5zcG9ydCIpO2Z1bmN0aW9uIHgoYSxiLGMsZCl7dmFyIGoscixzLHUsdyx4PWI7MiE9PXQmJih0PTIsZyYmY2xlYXJUaW1lb3V0KGcpLGk9dm9pZCAwLGY9ZHx8IiIsdi5yZWFkeVN0YXRlPWE+MD80OjAsaj1hPj0yMDAmJjMwMD5hfHwzMDQ9PT1hLGMmJih1PU9iKGssdixjKSksdT1QYihrLHUsdixqKSxqPyhrLmlmTW9kaWZpZWQmJih3PXYuZ2V0UmVzcG9uc2VIZWFkZXIoIkxhc3QtTW9kaWZpZWQiKSx3JiYobS5sYXN0TW9kaWZpZWRbZV09dyksdz12LmdldFJlc3BvbnNlSGVhZGVyKCJldGFnIiksdyYmKG0uZXRhZ1tlXT13KSksMjA0PT09YXx8IkhFQUQiPT09ay50eXBlP3g9Im5vY29udGVudCI6MzA0PT09YT94PSJub3Rtb2RpZmllZCI6KHg9dS5zdGF0ZSxyPXUuZGF0YSxzPXUuZXJyb3Isaj0hcykpOihzPXgsKGF8fCF4KSYmKHg9ImVycm9yIiwwPmEmJihhPTApKSksdi5zdGF0dXM9YSx2LnN0YXR1c1RleHQ9KGJ8fHgpKyIiLGo/by5yZXNvbHZlV2l0aChsLFtyLHgsdl0pOm8ucmVqZWN0V2l0aChsLFt2LHgsc10pLHYuc3RhdHVzQ29kZShxKSxxPXZvaWQgMCxoJiZuLnRyaWdnZXIoaj8iYWpheFN1Y2Nlc3MiOiJhamF4RXJyb3IiLFt2LGssaj9yOnNdKSxwLmZpcmVXaXRoKGwsW3YseF0pLGgmJihuLnRyaWdnZXIoImFqYXhDb21wbGV0ZSIsW3Ysa10pLC0tbS5hY3RpdmV8fG0uZXZlbnQudHJpZ2dlcigiYWpheFN0b3AiKSkpfXJldHVybiB2fSxnZXRKU09OOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbS5nZXQoYSxiLGMsImpzb24iKX0sZ2V0U2NyaXB0OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG0uZ2V0KGEsdm9pZCAwLGIsInNjcmlwdCIpfX0pLG0uZWFjaChbImdldCIsInBvc3QiXSxmdW5jdGlvbihhLGIpe21bYl09ZnVuY3Rpb24oYSxjLGQsZSl7cmV0dXJuIG0uaXNGdW5jdGlvbihjKSYmKGU9ZXx8ZCxkPWMsYz12b2lkIDApLG0uYWpheCh7dXJsOmEsdHlwZTpiLGRhdGFUeXBlOmUsZGF0YTpjLHN1Y2Nlc3M6ZH0pfX0pLG0uX2V2YWxVcmw9ZnVuY3Rpb24oYSl7cmV0dXJuIG0uYWpheCh7dXJsOmEsdHlwZToiR0VUIixkYXRhVHlwZToic2NyaXB0Iixhc3luYzohMSxnbG9iYWw6ITEsInRocm93cyI6ITB9KX0sbS5mbi5leHRlbmQoe3dyYXBBbGw6ZnVuY3Rpb24oYSl7aWYobS5pc0Z1bmN0aW9uKGEpKXJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oYil7bSh0aGlzKS53cmFwQWxsKGEuY2FsbCh0aGlzLGIpKX0pO2lmKHRoaXNbMF0pe3ZhciBiPW0oYSx0aGlzWzBdLm93bmVyRG9jdW1lbnQpLmVxKDApLmNsb25lKCEwKTt0aGlzWzBdLnBhcmVudE5vZGUmJmIuaW5zZXJ0QmVmb3JlKHRoaXNbMF0pLGIubWFwKGZ1bmN0aW9uKCl7dmFyIGE9dGhpczt3aGlsZShhLmZpcnN0Q2hpbGQmJjE9PT1hLmZpcnN0Q2hpbGQubm9kZVR5cGUpYT1hLmZpcnN0Q2hpbGQ7cmV0dXJuIGF9KS5hcHBlbmQodGhpcyl9cmV0dXJuIHRoaXN9LHdyYXBJbm5lcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5lYWNoKG0uaXNGdW5jdGlvbihhKT9mdW5jdGlvbihiKXttKHRoaXMpLndyYXBJbm5lcihhLmNhbGwodGhpcyxiKSl9OmZ1bmN0aW9uKCl7dmFyIGI9bSh0aGlzKSxjPWIuY29udGVudHMoKTtjLmxlbmd0aD9jLndyYXBBbGwoYSk6Yi5hcHBlbmQoYSl9KX0sd3JhcDpmdW5jdGlvbihhKXt2YXIgYj1tLmlzRnVuY3Rpb24oYSk7cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbihjKXttKHRoaXMpLndyYXBBbGwoYj9hLmNhbGwodGhpcyxjKTphKX0pfSx1bndyYXA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5wYXJlbnQoKS5lYWNoKGZ1bmN0aW9uKCl7bS5ub2RlTmFtZSh0aGlzLCJib2R5Iil8fG0odGhpcykucmVwbGFjZVdpdGgodGhpcy5jaGlsZE5vZGVzKX0pLmVuZCgpfX0pLG0uZXhwci5maWx0ZXJzLmhpZGRlbj1mdW5jdGlvbihhKXtyZXR1cm4gYS5vZmZzZXRXaWR0aDw9MCYmYS5vZmZzZXRIZWlnaHQ8PTB8fCFrLnJlbGlhYmxlSGlkZGVuT2Zmc2V0cygpJiYibm9uZSI9PT0oYS5zdHlsZSYmYS5zdHlsZS5kaXNwbGF5fHxtLmNzcyhhLCJkaXNwbGF5IikpfSxtLmV4cHIuZmlsdGVycy52aXNpYmxlPWZ1bmN0aW9uKGEpe3JldHVybiFtLmV4cHIuZmlsdGVycy5oaWRkZW4oYSl9O3ZhciBRYj0vJTIwL2csUmI9L1xbXF0kLyxTYj0vXHI/XG4vZyxUYj0vXig/OnN1Ym1pdHxidXR0b258aW1hZ2V8cmVzZXR8ZmlsZSkkL2ksVWI9L14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pO2Z1bmN0aW9uIFZiKGEsYixjLGQpe3ZhciBlO2lmKG0uaXNBcnJheShiKSltLmVhY2goYixmdW5jdGlvbihiLGUpe2N8fFJiLnRlc3QoYSk/ZChhLGUpOlZiKGErIlsiKygib2JqZWN0Ij09dHlwZW9mIGU/YjoiIikrIl0iLGUsYyxkKX0pO2Vsc2UgaWYoY3x8Im9iamVjdCIhPT1tLnR5cGUoYikpZChhLGIpO2Vsc2UgZm9yKGUgaW4gYilWYihhKyJbIitlKyJdIixiW2VdLGMsZCl9bS5wYXJhbT1mdW5jdGlvbihhLGIpe3ZhciBjLGQ9W10sZT1mdW5jdGlvbihhLGIpe2I9bS5pc0Z1bmN0aW9uKGIpP2IoKTpudWxsPT1iPyIiOmIsZFtkLmxlbmd0aF09ZW5jb2RlVVJJQ29tcG9uZW50KGEpKyI9IitlbmNvZGVVUklDb21wb25lbnQoYil9O2lmKHZvaWQgMD09PWImJihiPW0uYWpheFNldHRpbmdzJiZtLmFqYXhTZXR0aW5ncy50cmFkaXRpb25hbCksbS5pc0FycmF5KGEpfHxhLmpxdWVyeSYmIW0uaXNQbGFpbk9iamVjdChhKSltLmVhY2goYSxmdW5jdGlvbigpe2UodGhpcy5uYW1lLHRoaXMudmFsdWUpfSk7ZWxzZSBmb3IoYyBpbiBhKVZiKGMsYVtjXSxiLGUpO3JldHVybiBkLmpvaW4oIiYiKS5yZXBsYWNlKFFiLCIrIil9LG0uZm4uZXh0ZW5kKHtzZXJpYWxpemU6ZnVuY3Rpb24oKXtyZXR1cm4gbS5wYXJhbSh0aGlzLnNlcmlhbGl6ZUFycmF5KCkpfSxzZXJpYWxpemVBcnJheTpmdW5jdGlvbigpe3JldHVybiB0aGlzLm1hcChmdW5jdGlvbigpe3ZhciBhPW0ucHJvcCh0aGlzLCJlbGVtZW50cyIpO3JldHVybiBhP20ubWFrZUFycmF5KGEpOnRoaXN9KS5maWx0ZXIoZnVuY3Rpb24oKXt2YXIgYT10aGlzLnR5cGU7cmV0dXJuIHRoaXMubmFtZSYmIW0odGhpcykuaXMoIjpkaXNhYmxlZCIpJiZVYi50ZXN0KHRoaXMubm9kZU5hbWUpJiYhVGIudGVzdChhKSYmKHRoaXMuY2hlY2tlZHx8IVcudGVzdChhKSl9KS5tYXAoZnVuY3Rpb24oYSxiKXt2YXIgYz1tKHRoaXMpLnZhbCgpO3JldHVybiBudWxsPT1jP251bGw6bS5pc0FycmF5KGMpP20ubWFwKGMsZnVuY3Rpb24oYSl7cmV0dXJue25hbWU6Yi5uYW1lLHZhbHVlOmEucmVwbGFjZShTYiwiXHJcbiIpfX0pOntuYW1lOmIubmFtZSx2YWx1ZTpjLnJlcGxhY2UoU2IsIlxyXG4iKX19KS5nZXQoKX19KSxtLmFqYXhTZXR0aW5ncy54aHI9dm9pZCAwIT09YS5BY3RpdmVYT2JqZWN0P2Z1bmN0aW9uKCl7cmV0dXJuIXRoaXMuaXNMb2NhbCYmL14oZ2V0fHBvc3R8aGVhZHxwdXR8ZGVsZXRlfG9wdGlvbnMpJC9pLnRlc3QodGhpcy50eXBlKSYmWmIoKXx8JGIoKX06WmI7dmFyIFdiPTAsWGI9e30sWWI9bS5hamF4U2V0dGluZ3MueGhyKCk7YS5hdHRhY2hFdmVudCYmYS5hdHRhY2hFdmVudCgib251bmxvYWQiLGZ1bmN0aW9uKCl7Zm9yKHZhciBhIGluIFhiKVhiW2FdKHZvaWQgMCwhMCl9KSxrLmNvcnM9ISFZYiYmIndpdGhDcmVkZW50aWFscyJpbiBZYixZYj1rLmFqYXg9ISFZYixZYiYmbS5hamF4VHJhbnNwb3J0KGZ1bmN0aW9uKGEpe2lmKCFhLmNyb3NzRG9tYWlufHxrLmNvcnMpe3ZhciBiO3JldHVybntzZW5kOmZ1bmN0aW9uKGMsZCl7dmFyIGUsZj1hLnhocigpLGc9KytXYjtpZihmLm9wZW4oYS50eXBlLGEudXJsLGEuYXN5bmMsYS51c2VybmFtZSxhLnBhc3N3b3JkKSxhLnhockZpZWxkcylmb3IoZSBpbiBhLnhockZpZWxkcylmW2VdPWEueGhyRmllbGRzW2VdO2EubWltZVR5cGUmJmYub3ZlcnJpZGVNaW1lVHlwZSYmZi5vdmVycmlkZU1pbWVUeXBlKGEubWltZVR5cGUpLGEuY3Jvc3NEb21haW58fGNbIlgtUmVxdWVzdGVkLVdpdGgiXXx8KGNbIlgtUmVxdWVzdGVkLVdpdGgiXT0iWE1MSHR0cFJlcXVlc3QiKTtmb3IoZSBpbiBjKXZvaWQgMCE9PWNbZV0mJmYuc2V0UmVxdWVzdEhlYWRlcihlLGNbZV0rIiIpO2Yuc2VuZChhLmhhc0NvbnRlbnQmJmEuZGF0YXx8bnVsbCksYj1mdW5jdGlvbihjLGUpe3ZhciBoLGksajtpZihiJiYoZXx8ND09PWYucmVhZHlTdGF0ZSkpaWYoZGVsZXRlIFhiW2ddLGI9dm9pZCAwLGYub25yZWFkeXN0YXRlY2hhbmdlPW0ubm9vcCxlKTQhPT1mLnJlYWR5U3RhdGUmJmYuYWJvcnQoKTtlbHNle2o9e30saD1mLnN0YXR1cywic3RyaW5nIj09dHlwZW9mIGYucmVzcG9uc2VUZXh0JiYoai50ZXh0PWYucmVzcG9uc2VUZXh0KTt0cnl7aT1mLnN0YXR1c1RleHR9Y2F0Y2goayl7aT0iIn1ofHwhYS5pc0xvY2FsfHxhLmNyb3NzRG9tYWluPzEyMjM9PT1oJiYoaD0yMDQpOmg9ai50ZXh0PzIwMDo0MDR9aiYmZChoLGksaixmLmdldEFsbFJlc3BvbnNlSGVhZGVycygpKX0sYS5hc3luYz80PT09Zi5yZWFkeVN0YXRlP3NldFRpbWVvdXQoYik6Zi5vbnJlYWR5c3RhdGVjaGFuZ2U9WGJbZ109YjpiKCl9LGFib3J0OmZ1bmN0aW9uKCl7YiYmYih2b2lkIDAsITApfX19fSk7ZnVuY3Rpb24gWmIoKXt0cnl7cmV0dXJuIG5ldyBhLlhNTEh0dHBSZXF1ZXN0fWNhdGNoKGIpe319ZnVuY3Rpb24gJGIoKXt0cnl7cmV0dXJuIG5ldyBhLkFjdGl2ZVhPYmplY3QoIk1pY3Jvc29mdC5YTUxIVFRQIil9Y2F0Y2goYil7fX1tLmFqYXhTZXR1cCh7YWNjZXB0czp7c2NyaXB0OiJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2VjbWFzY3JpcHQsIGFwcGxpY2F0aW9uL3gtZWNtYXNjcmlwdCJ9LGNvbnRlbnRzOntzY3JpcHQ6Lyg/OmphdmF8ZWNtYSlzY3JpcHQvfSxjb252ZXJ0ZXJzOnsidGV4dCBzY3JpcHQiOmZ1bmN0aW9uKGEpe3JldHVybiBtLmdsb2JhbEV2YWwoYSksYX19fSksbS5hamF4UHJlZmlsdGVyKCJzY3JpcHQiLGZ1bmN0aW9uKGEpe3ZvaWQgMD09PWEuY2FjaGUmJihhLmNhY2hlPSExKSxhLmNyb3NzRG9tYWluJiYoYS50eXBlPSJHRVQiLGEuZ2xvYmFsPSExKX0pLG0uYWpheFRyYW5zcG9ydCgic2NyaXB0IixmdW5jdGlvbihhKXtpZihhLmNyb3NzRG9tYWluKXt2YXIgYixjPXkuaGVhZHx8bSgiaGVhZCIpWzBdfHx5LmRvY3VtZW50RWxlbWVudDtyZXR1cm57c2VuZDpmdW5jdGlvbihkLGUpe2I9eS5jcmVhdGVFbGVtZW50KCJzY3JpcHQiKSxiLmFzeW5jPSEwLGEuc2NyaXB0Q2hhcnNldCYmKGIuY2hhcnNldD1hLnNjcmlwdENoYXJzZXQpLGIuc3JjPWEudXJsLGIub25sb2FkPWIub25yZWFkeXN0YXRlY2hhbmdlPWZ1bmN0aW9uKGEsYyl7KGN8fCFiLnJlYWR5U3RhdGV8fC9sb2FkZWR8Y29tcGxldGUvLnRlc3QoYi5yZWFkeVN0YXRlKSkmJihiLm9ubG9hZD1iLm9ucmVhZHlzdGF0ZWNoYW5nZT1udWxsLGIucGFyZW50Tm9kZSYmYi5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGIpLGI9bnVsbCxjfHxlKDIwMCwic3VjY2VzcyIpKX0sYy5pbnNlcnRCZWZvcmUoYixjLmZpcnN0Q2hpbGQpfSxhYm9ydDpmdW5jdGlvbigpe2ImJmIub25sb2FkKHZvaWQgMCwhMCl9fX19KTt2YXIgX2I9W10sYWM9Lyg9KVw/KD89JnwkKXxcP1w/LzttLmFqYXhTZXR1cCh7anNvbnA6ImNhbGxiYWNrIixqc29ucENhbGxiYWNrOmZ1bmN0aW9uKCl7dmFyIGE9X2IucG9wKCl8fG0uZXhwYW5kbysiXyIrdmIrKztyZXR1cm4gdGhpc1thXT0hMCxhfX0pLG0uYWpheFByZWZpbHRlcigianNvbiBqc29ucCIsZnVuY3Rpb24oYixjLGQpe3ZhciBlLGYsZyxoPWIuanNvbnAhPT0hMSYmKGFjLnRlc3QoYi51cmwpPyJ1cmwiOiJzdHJpbmciPT10eXBlb2YgYi5kYXRhJiYhKGIuY29udGVudFR5cGV8fCIiKS5pbmRleE9mKCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQiKSYmYWMudGVzdChiLmRhdGEpJiYiZGF0YSIpO3JldHVybiBofHwianNvbnAiPT09Yi5kYXRhVHlwZXNbMF0/KGU9Yi5qc29ucENhbGxiYWNrPW0uaXNGdW5jdGlvbihiLmpzb25wQ2FsbGJhY2spP2IuanNvbnBDYWxsYmFjaygpOmIuanNvbnBDYWxsYmFjayxoP2JbaF09YltoXS5yZXBsYWNlKGFjLCIkMSIrZSk6Yi5qc29ucCE9PSExJiYoYi51cmwrPSh3Yi50ZXN0KGIudXJsKT8iJiI6Ij8iKStiLmpzb25wKyI9IitlKSxiLmNvbnZlcnRlcnNbInNjcmlwdCBqc29uIl09ZnVuY3Rpb24oKXtyZXR1cm4gZ3x8bS5lcnJvcihlKyIgd2FzIG5vdCBjYWxsZWQiKSxnWzBdfSxiLmRhdGFUeXBlc1swXT0ianNvbiIsZj1hW2VdLGFbZV09ZnVuY3Rpb24oKXtnPWFyZ3VtZW50c30sZC5hbHdheXMoZnVuY3Rpb24oKXthW2VdPWYsYltlXSYmKGIuanNvbnBDYWxsYmFjaz1jLmpzb25wQ2FsbGJhY2ssX2IucHVzaChlKSksZyYmbS5pc0Z1bmN0aW9uKGYpJiZmKGdbMF0pLGc9Zj12b2lkIDB9KSwic2NyaXB0Iik6dm9pZCAwfSksbS5wYXJzZUhUTUw9ZnVuY3Rpb24oYSxiLGMpe2lmKCFhfHwic3RyaW5nIiE9dHlwZW9mIGEpcmV0dXJuIG51bGw7ImJvb2xlYW4iPT10eXBlb2YgYiYmKGM9YixiPSExKSxiPWJ8fHk7dmFyIGQ9dS5leGVjKGEpLGU9IWMmJltdO3JldHVybiBkP1tiLmNyZWF0ZUVsZW1lbnQoZFsxXSldOihkPW0uYnVpbGRGcmFnbWVudChbYV0sYixlKSxlJiZlLmxlbmd0aCYmbShlKS5yZW1vdmUoKSxtLm1lcmdlKFtdLGQuY2hpbGROb2RlcykpfTt2YXIgYmM9bS5mbi5sb2FkO20uZm4ubG9hZD1mdW5jdGlvbihhLGIsYyl7aWYoInN0cmluZyIhPXR5cGVvZiBhJiZiYylyZXR1cm4gYmMuYXBwbHkodGhpcyxhcmd1bWVudHMpO3ZhciBkLGUsZixnPXRoaXMsaD1hLmluZGV4T2YoIiAiKTtyZXR1cm4gaD49MCYmKGQ9bS50cmltKGEuc2xpY2UoaCxhLmxlbmd0aCkpLGE9YS5zbGljZSgwLGgpKSxtLmlzRnVuY3Rpb24oYik/KGM9YixiPXZvaWQgMCk6YiYmIm9iamVjdCI9PXR5cGVvZiBiJiYoZj0iUE9TVCIpLGcubGVuZ3RoPjAmJm0uYWpheCh7dXJsOmEsdHlwZTpmLGRhdGFUeXBlOiJodG1sIixkYXRhOmJ9KS5kb25lKGZ1bmN0aW9uKGEpe2U9YXJndW1lbnRzLGcuaHRtbChkP20oIjxkaXY+IikuYXBwZW5kKG0ucGFyc2VIVE1MKGEpKS5maW5kKGQpOmEpfSkuY29tcGxldGUoYyYmZnVuY3Rpb24oYSxiKXtnLmVhY2goYyxlfHxbYS5yZXNwb25zZVRleHQsYixhXSl9KSx0aGlzfSxtLmVhY2goWyJhamF4U3RhcnQiLCJhamF4U3RvcCIsImFqYXhDb21wbGV0ZSIsImFqYXhFcnJvciIsImFqYXhTdWNjZXNzIiwiYWpheFNlbmQiXSxmdW5jdGlvbihhLGIpe20uZm5bYl09ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMub24oYixhKX19KSxtLmV4cHIuZmlsdGVycy5hbmltYXRlZD1mdW5jdGlvbihhKXtyZXR1cm4gbS5ncmVwKG0udGltZXJzLGZ1bmN0aW9uKGIpe3JldHVybiBhPT09Yi5lbGVtfSkubGVuZ3RofTt2YXIgY2M9YS5kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7ZnVuY3Rpb24gZGMoYSl7cmV0dXJuIG0uaXNXaW5kb3coYSk/YTo5PT09YS5ub2RlVHlwZT9hLmRlZmF1bHRWaWV3fHxhLnBhcmVudFdpbmRvdzohMX1tLm9mZnNldD17c2V0T2Zmc2V0OmZ1bmN0aW9uKGEsYixjKXt2YXIgZCxlLGYsZyxoLGksaixrPW0uY3NzKGEsInBvc2l0aW9uIiksbD1tKGEpLG49e307InN0YXRpYyI9PT1rJiYoYS5zdHlsZS5wb3NpdGlvbj0icmVsYXRpdmUiKSxoPWwub2Zmc2V0KCksZj1tLmNzcyhhLCJ0b3AiKSxpPW0uY3NzKGEsImxlZnQiKSxqPSgiYWJzb2x1dGUiPT09a3x8ImZpeGVkIj09PWspJiZtLmluQXJyYXkoImF1dG8iLFtmLGldKT4tMSxqPyhkPWwucG9zaXRpb24oKSxnPWQudG9wLGU9ZC5sZWZ0KTooZz1wYXJzZUZsb2F0KGYpfHwwLGU9cGFyc2VGbG9hdChpKXx8MCksbS5pc0Z1bmN0aW9uKGIpJiYoYj1iLmNhbGwoYSxjLGgpKSxudWxsIT1iLnRvcCYmKG4udG9wPWIudG9wLWgudG9wK2cpLG51bGwhPWIubGVmdCYmKG4ubGVmdD1iLmxlZnQtaC5sZWZ0K2UpLCJ1c2luZyJpbiBiP2IudXNpbmcuY2FsbChhLG4pOmwuY3NzKG4pfX0sbS5mbi5leHRlbmQoe29mZnNldDpmdW5jdGlvbihhKXtpZihhcmd1bWVudHMubGVuZ3RoKXJldHVybiB2b2lkIDA9PT1hP3RoaXM6dGhpcy5lYWNoKGZ1bmN0aW9uKGIpe20ub2Zmc2V0LnNldE9mZnNldCh0aGlzLGEsYil9KTt2YXIgYixjLGQ9e3RvcDowLGxlZnQ6MH0sZT10aGlzWzBdLGY9ZSYmZS5vd25lckRvY3VtZW50O2lmKGYpcmV0dXJuIGI9Zi5kb2N1bWVudEVsZW1lbnQsbS5jb250YWlucyhiLGUpPyh0eXBlb2YgZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QhPT1LJiYoZD1lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpKSxjPWRjKGYpLHt0b3A6ZC50b3ArKGMucGFnZVlPZmZzZXR8fGIuc2Nyb2xsVG9wKS0oYi5jbGllbnRUb3B8fDApLGxlZnQ6ZC5sZWZ0KyhjLnBhZ2VYT2Zmc2V0fHxiLnNjcm9sbExlZnQpLShiLmNsaWVudExlZnR8fDApfSk6ZH0scG9zaXRpb246ZnVuY3Rpb24oKXtpZih0aGlzWzBdKXt2YXIgYSxiLGM9e3RvcDowLGxlZnQ6MH0sZD10aGlzWzBdO3JldHVybiJmaXhlZCI9PT1tLmNzcyhkLCJwb3NpdGlvbiIpP2I9ZC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTooYT10aGlzLm9mZnNldFBhcmVudCgpLGI9dGhpcy5vZmZzZXQoKSxtLm5vZGVOYW1lKGFbMF0sImh0bWwiKXx8KGM9YS5vZmZzZXQoKSksYy50b3ArPW0uY3NzKGFbMF0sImJvcmRlclRvcFdpZHRoIiwhMCksYy5sZWZ0Kz1tLmNzcyhhWzBdLCJib3JkZXJMZWZ0V2lkdGgiLCEwKSkse3RvcDpiLnRvcC1jLnRvcC1tLmNzcyhkLCJtYXJnaW5Ub3AiLCEwKSxsZWZ0OmIubGVmdC1jLmxlZnQtbS5jc3MoZCwibWFyZ2luTGVmdCIsITApfX19LG9mZnNldFBhcmVudDpmdW5jdGlvbigpe3JldHVybiB0aGlzLm1hcChmdW5jdGlvbigpe3ZhciBhPXRoaXMub2Zmc2V0UGFyZW50fHxjYzt3aGlsZShhJiYhbS5ub2RlTmFtZShhLCJodG1sIikmJiJzdGF0aWMiPT09bS5jc3MoYSwicG9zaXRpb24iKSlhPWEub2Zmc2V0UGFyZW50O3JldHVybiBhfHxjY30pfX0pLG0uZWFjaCh7c2Nyb2xsTGVmdDoicGFnZVhPZmZzZXQiLHNjcm9sbFRvcDoicGFnZVlPZmZzZXQifSxmdW5jdGlvbihhLGIpe3ZhciBjPS9ZLy50ZXN0KGIpO20uZm5bYV09ZnVuY3Rpb24oZCl7cmV0dXJuIFYodGhpcyxmdW5jdGlvbihhLGQsZSl7dmFyIGY9ZGMoYSk7cmV0dXJuIHZvaWQgMD09PWU/Zj9iIGluIGY/ZltiXTpmLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFtkXTphW2RdOnZvaWQoZj9mLnNjcm9sbFRvKGM/bShmKS5zY3JvbGxMZWZ0KCk6ZSxjP2U6bShmKS5zY3JvbGxUb3AoKSk6YVtkXT1lKX0sYSxkLGFyZ3VtZW50cy5sZW5ndGgsbnVsbCl9fSksbS5lYWNoKFsidG9wIiwibGVmdCJdLGZ1bmN0aW9uKGEsYil7bS5jc3NIb29rc1tiXT1MYShrLnBpeGVsUG9zaXRpb24sZnVuY3Rpb24oYSxjKXtyZXR1cm4gYz8oYz1KYShhLGIpLEhhLnRlc3QoYyk/bShhKS5wb3NpdGlvbigpW2JdKyJweCI6Yyk6dm9pZCAwfSl9KSxtLmVhY2goe0hlaWdodDoiaGVpZ2h0IixXaWR0aDoid2lkdGgifSxmdW5jdGlvbihhLGIpe20uZWFjaCh7cGFkZGluZzoiaW5uZXIiK2EsY29udGVudDpiLCIiOiJvdXRlciIrYX0sZnVuY3Rpb24oYyxkKXttLmZuW2RdPWZ1bmN0aW9uKGQsZSl7dmFyIGY9YXJndW1lbnRzLmxlbmd0aCYmKGN8fCJib29sZWFuIiE9dHlwZW9mIGQpLGc9Y3x8KGQ9PT0hMHx8ZT09PSEwPyJtYXJnaW4iOiJib3JkZXIiKTtyZXR1cm4gVih0aGlzLGZ1bmN0aW9uKGIsYyxkKXt2YXIgZTtyZXR1cm4gbS5pc1dpbmRvdyhiKT9iLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsiY2xpZW50IithXTo5PT09Yi5ub2RlVHlwZT8oZT1iLmRvY3VtZW50RWxlbWVudCxNYXRoLm1heChiLmJvZHlbInNjcm9sbCIrYV0sZVsic2Nyb2xsIithXSxiLmJvZHlbIm9mZnNldCIrYV0sZVsib2Zmc2V0IithXSxlWyJjbGllbnQiK2FdKSk6dm9pZCAwPT09ZD9tLmN
gitextract_wdvkn2_7/
├── .cargo/
│ └── config.toml
├── .envrc
├── .git-blame-ignore-revs
├── .git_archival.txt
├── .gitattributes
├── .github/
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── asv.yml
│ ├── build_wheel.yml
│ ├── build_wheel_all_archs.yml
│ ├── codspeed.yml
│ ├── dev_envs.yml
│ ├── draft-pdf.yml
│ ├── hypothesis.yml
│ ├── metadata.yml
│ ├── python.yml
│ └── rust.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .readthedocs.yml
├── .sonarcloud.properties
├── .zenodo.json
├── CITATION.cff
├── CODE_OF_CONDUCT.rst
├── CONTRIBUTING.md
├── Cargo.toml
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── asv.conf.json
├── benchmarks/
│ ├── README.md
│ ├── __init__.py
│ └── benchmarks.py
├── binder/
│ ├── README.md
│ └── environment.yml
├── codecov.yml
├── codemeta.json
├── data/
│ └── README.md
├── default.nix
├── deny.toml
├── dev.yml
├── doc/
│ ├── Makefile
│ ├── README.md
│ ├── _static/
│ │ ├── custom.css
│ │ ├── ecoli-cmp.Rmd
│ │ ├── ecoli-cmp.html
│ │ └── ecoli.cmp.csv
│ ├── _templates/
│ │ └── .empty
│ ├── api-example.md
│ ├── api.md
│ ├── cite.md
│ ├── classifying-signatures.md
│ ├── command-line.md
│ ├── conf.py
│ ├── databases-advanced.md
│ ├── databases-md/
│ │ ├── gtdb220.md
│ │ ├── gtdb226.md
│ │ ├── ncbi_euks_2025_01.md
│ │ └── ncbi_viruses_2025_01.md
│ ├── databases.md
│ ├── dev_plugins.md
│ ├── developer.md
│ ├── faq.md
│ ├── funding.md
│ ├── howto-rocksdb.md
│ ├── index.md
│ ├── kmers-and-minhash.ipynb
│ ├── legacy-databases.md
│ ├── more-info.md
│ ├── other-languages.md
│ ├── plotting-compare.ipynb
│ ├── podar-lineage.csv
│ ├── publications.md
│ ├── release-notes/
│ │ ├── releases.md
│ │ ├── sourmash-2.0.md
│ │ ├── sourmash-3.0.md
│ │ ├── sourmash-4.0.md
│ │ └── sourmash-5.0.md
│ ├── release.md
│ ├── requirements.md
│ ├── runtime.txt
│ ├── sidebar.md
│ ├── sourmash-collections.ipynb
│ ├── sourmash-examples.ipynb
│ ├── sourmash-internals.md
│ ├── sourmash-sketch.md
│ ├── storage.md
│ ├── support.md
│ ├── toc.md
│ ├── tutorial-basic.md
│ ├── tutorial-install.md
│ ├── tutorial-lemonade.md
│ ├── tutorial-lin-taxonomy.md
│ ├── tutorial-long.md
│ ├── tutorials-lca.md
│ ├── tutorials.md
│ ├── using-LCA-database-API.ipynb
│ └── using-sourmash-a-guide.md
├── flake.nix
├── include/
│ └── sourmash.h
├── matplotlibrc
├── paper.bib
├── paper.md
├── pyproject.toml
├── requirements.txt
├── shell.nix
├── src/
│ ├── core/
│ │ ├── CHANGELOG.md
│ │ ├── Cargo.toml
│ │ ├── README.md
│ │ ├── benches/
│ │ │ ├── compute.rs
│ │ │ ├── gather.rs
│ │ │ ├── minhash.rs
│ │ │ └── nodegraph.rs
│ │ ├── build.rs
│ │ ├── cbindgen.toml
│ │ ├── examples/
│ │ │ └── generate_mqfs.rs
│ │ ├── src/
│ │ │ ├── ani_utils.rs
│ │ │ ├── cmd.rs
│ │ │ ├── collection.rs
│ │ │ ├── encodings.rs
│ │ │ ├── errors.rs
│ │ │ ├── ffi/
│ │ │ │ ├── cmd/
│ │ │ │ │ ├── compute.rs
│ │ │ │ │ └── mod.rs
│ │ │ │ ├── hyperloglog.rs
│ │ │ │ ├── index/
│ │ │ │ │ ├── mod.rs
│ │ │ │ │ └── revindex.rs
│ │ │ │ ├── manifest.rs
│ │ │ │ ├── minhash.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── nodegraph.rs
│ │ │ │ ├── signature.rs
│ │ │ │ ├── storage.rs
│ │ │ │ └── utils.rs
│ │ │ ├── index/
│ │ │ │ ├── linear.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── revindex/
│ │ │ │ │ ├── disk_revindex.rs
│ │ │ │ │ ├── mem_revindex.rs
│ │ │ │ │ └── mod.rs
│ │ │ │ └── search.rs
│ │ │ ├── lib.rs
│ │ │ ├── manifest.rs
│ │ │ ├── prelude.rs
│ │ │ ├── selection.rs
│ │ │ ├── signature.rs
│ │ │ ├── sketch/
│ │ │ │ ├── hyperloglog/
│ │ │ │ │ ├── estimators.rs
│ │ │ │ │ └── mod.rs
│ │ │ │ ├── minhash.rs
│ │ │ │ ├── mod.rs
│ │ │ │ └── nodegraph.rs
│ │ │ ├── storage/
│ │ │ │ ├── mod.rs
│ │ │ │ └── rocksdb.rs
│ │ │ └── wasm.rs
│ │ └── tests/
│ │ ├── dedicated_worker.rs
│ │ ├── finch.rs
│ │ ├── minhash.rs
│ │ ├── node.rs
│ │ ├── service_worker.rs
│ │ ├── shared_worker.rs
│ │ ├── storage.rs
│ │ ├── test.rs
│ │ └── web.rs
│ └── sourmash/
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli/
│ │ ├── .gitignore
│ │ ├── __init__.py
│ │ ├── categorize.py
│ │ ├── compare.py
│ │ ├── compute.py
│ │ ├── gather.py
│ │ ├── import_csv.py
│ │ ├── index.py
│ │ ├── info.py
│ │ ├── lca/
│ │ │ ├── __init__.py
│ │ │ ├── classify.py
│ │ │ ├── compare_csv.py
│ │ │ ├── index.py
│ │ │ ├── rankinfo.py
│ │ │ └── summarize.py
│ │ ├── migrate.py
│ │ ├── multigather.py
│ │ ├── plot.py
│ │ ├── prefetch.py
│ │ ├── sbt_combine.py
│ │ ├── scripts/
│ │ │ └── __init__.py
│ │ ├── search.py
│ │ ├── sig/
│ │ │ ├── __init__.py
│ │ │ ├── cat.py
│ │ │ ├── check.py
│ │ │ ├── collect.py
│ │ │ ├── describe.py
│ │ │ ├── downsample.py
│ │ │ ├── export.py
│ │ │ ├── extract.py
│ │ │ ├── fileinfo.py
│ │ │ ├── filter.py
│ │ │ ├── flatten.py
│ │ │ ├── grep.py
│ │ │ ├── inflate.py
│ │ │ ├── ingest.py
│ │ │ ├── intersect.py
│ │ │ ├── kmers.py
│ │ │ ├── manifest.py
│ │ │ ├── merge.py
│ │ │ ├── overlap.py
│ │ │ ├── rename.py
│ │ │ ├── split.py
│ │ │ └── subtract.py
│ │ ├── sketch/
│ │ │ ├── __init__.py
│ │ │ ├── dna.py
│ │ │ ├── fromfile.py
│ │ │ ├── protein.py
│ │ │ └── translate.py
│ │ ├── storage/
│ │ │ ├── __init__.py
│ │ │ └── convert.py
│ │ ├── tax/
│ │ │ ├── __init__.py
│ │ │ ├── annotate.py
│ │ │ ├── genome.py
│ │ │ ├── grep.py
│ │ │ ├── metagenome.py
│ │ │ ├── prepare.py
│ │ │ └── summarize.py
│ │ ├── utils.py
│ │ └── watch.py
│ ├── command_compute.py
│ ├── command_sketch.py
│ ├── commands.py
│ ├── compare.py
│ ├── distance_utils.py
│ ├── exceptions.py
│ ├── fig.py
│ ├── hll.py
│ ├── index/
│ │ ├── __init__.py
│ │ ├── revindex.py
│ │ └── sqlite_index.py
│ ├── lca/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ ├── command_classify.py
│ │ ├── command_compare_csv.py
│ │ ├── command_index.py
│ │ ├── command_rankinfo.py
│ │ ├── command_summarize.py
│ │ ├── lca_db.py
│ │ └── lca_utils.py
│ ├── logging.py
│ ├── manifest.py
│ ├── minhash.py
│ ├── nodegraph.py
│ ├── np_utils.py
│ ├── picklist.py
│ ├── plugins.py
│ ├── save_load.py
│ ├── sbt.py
│ ├── sbt_storage.py
│ ├── sbtmh.py
│ ├── search.py
│ ├── sig/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ └── grep.py
│ ├── signature.py
│ ├── sketchcomparison.py
│ ├── sourmash_args.py
│ ├── sqlite_utils.py
│ ├── tax/
│ │ ├── __init__.py
│ │ ├── __main__.py
│ │ └── tax_utils.py
│ └── utils.py
├── tests/
│ ├── conftest.py
│ ├── sourmash_tst_utils.py
│ ├── test-data/
│ │ ├── .sbt.leaves/
│ │ │ ├── 0107d767a345eff67ecdaed2ee5cd7ba
│ │ │ ├── 4e94e60265e04f0763142e20b52c0da1
│ │ │ ├── 60f7e23c24a8d94791cc7a8680c493f9
│ │ │ ├── 6d6e87e1154e95b279e5e7db414bc37b
│ │ │ ├── b59473c94ff2889eca5d7165936e64b3
│ │ │ ├── f0c834bc306651d2b9321fb21d3e8d8f
│ │ │ └── f71e78178af9e45e6f1d87a0c53c465c
│ │ ├── .sbt.subset/
│ │ │ ├── 004459575e3657bca8a3d0424545f082
│ │ │ ├── 01bb2bac3849b82dee57a6ecf8725432
│ │ │ ├── 0382590e3740e4c94455b4d52fff9143
│ │ │ ├── 0418b8351b86bb41c8224d9d15474614
│ │ │ ├── 09cc8e435e5570a5ba3b086bed8c831f
│ │ │ ├── 0d5e85e6ec8d82f2ae38ecb7f1394a04
│ │ │ ├── 0f6508728e178731f3884f59dc7ff3c3
│ │ │ ├── 1131a68ec746703c8c4a2bd13557bf6a
│ │ │ ├── 133743f147335b4d31b0e91480606339
│ │ │ ├── 175e67b69e1833bdee0859a3a99495b1
│ │ │ ├── 1bc3dc1d05e30383d4d098b7de944951
│ │ │ ├── 1f86e7c6c52baed6ce168b05f23013fc
│ │ │ ├── 1fb580f790c207278b55c408a68ff391
│ │ │ ├── 205c4b9623e7331a907f293865925dfa
│ │ │ ├── 20c1ca3c7ff0bb437afd69042bb5f852
│ │ │ ├── 2ac8b6220c4d44ae3dbbbfc7e939df61
│ │ │ ├── 2b28f083395d8f5e7b88c1899ff4a212
│ │ │ ├── 2d8b4d96cf9d790c1b225e681f8d57dd
│ │ │ ├── 3685ee5f820ab6e840ec6b0fe090e754
│ │ │ ├── 38cf0b7d644963ee846734251e9c0175
│ │ │ ├── 3988811e454e96213af488031d84eed9
│ │ │ ├── 3e18cd65bcc35fa150185fea0f162549
│ │ │ ├── 43637330e78d1518b4d8f7603fdb6899
│ │ │ ├── 43fcce1eeeebc8d40162d5247202aef8
│ │ │ ├── 46656e34e01f58e22f22a622f44fa658
│ │ │ ├── 4b57274be5a768732716b9dc600a1f14
│ │ │ ├── 4f1bf83d739fa4d420ceb0aae9403400
│ │ │ ├── 56b9e7bddb830ebe3faaf9923322b51e
│ │ │ ├── 57256c01ec9b9980ecda5b97acb236c3
│ │ │ ├── 57c3b9f54148e7ea9ebfdabbe530f131
│ │ │ ├── 58459874f43a5d202d46018eb8f06e4c
│ │ │ ├── 589cddfc349d8950af5bbd90f5db7060
│ │ │ ├── 5c07a864e3f86a705a73b89bd517979f
│ │ │ ├── 5d19af7826508594c035efe76443138c
│ │ │ ├── 5d813a4d317f9ad17154a99d296d081b
│ │ │ ├── 633f4c15ae21310dac488c09d66c2d38
│ │ │ ├── 6381609c5cdcd210887f5add4bab44d9
│ │ │ ├── 66d40738bd608b83ef35b205a561eaa5
│ │ │ ├── 736138545b801b99385439231a69ab77
│ │ │ ├── 7574dd67e829221b9ae553692c2d5258
│ │ │ ├── 7d859a1c0be4c97c9e1c6c8272950772
│ │ │ ├── 7ddb71d74edc6d1e0c724a8f1bd3c8cc
│ │ │ ├── 7e22d796abc7a6c49dadb94c4dae16b3
│ │ │ ├── 802dc6bf5787992180db6ca259313edf
│ │ │ ├── 81d3020367359d305b0e21933faece1b
│ │ │ ├── 826776746a37223786ffec552e769c88
│ │ │ ├── 8276440e3138e74a1c91b4d91f21072b
│ │ │ ├── 82e0290a438650db9a93ce29276f931b
│ │ │ ├── 849cf867719c1edecd4ec5cf2fb01a32
│ │ │ ├── 857129e817ea9f95c22893d652c98a23
│ │ │ ├── 85ac23fb1585cbe148318b4947a702b7
│ │ │ ├── 8963a3ad29f88d2b9869c51ac102ddf6
│ │ │ ├── 896f1c578904fad60f17061146946732
│ │ │ ├── 8b5bef6feeb06603e70fde66df521edf
│ │ │ ├── 8bdbd61dd2e99b7716968338bcfe9660
│ │ │ ├── 8f9573dec32c97fe824c06edaa16c979
│ │ │ ├── 91fea76b0361f4f812c07e7d43f434f3
│ │ │ ├── 95fd78a08b85bfc006555fe7cbd7e3de
│ │ │ ├── 972d83aa010954aaf5ad0a56f30f43b6
│ │ │ ├── 978c4674f45437d4e84d0a0fc11c424b
│ │ │ ├── 97c19c413385bc830c6b2ddc855ac23a
│ │ │ ├── 9893ff8c4def73d5566baa3541b0a806
│ │ │ ├── 9d3cbd4300d2ca17479b351d152ea677
│ │ │ ├── 9f1f319740e92e9632ce9255f0c57114
│ │ │ ├── a04ede5f60924719bfaabef59c1de821
│ │ │ ├── a20adff6c30627dc22e74d57d7f9b7db
│ │ │ ├── a448b639491a6f75649c2b1c960780d9
│ │ │ ├── a532ca6bf98299efeb2915715b9a21c3
│ │ │ ├── a573351886e921b7204064508010fde0
│ │ │ ├── a893a18ca62dd4e2bcb3c9aaf9c1957b
│ │ │ ├── a897a797fc00c21ec3ef5062b38cfb90
│ │ │ ├── b1ffa01e0fa86ef9025003261eb181e3
│ │ │ ├── b23715f6943b9a84bd64315d27cc8bd5
│ │ │ ├── b3068619013f7ce1bddaa4a67305a571
│ │ │ ├── b476935e55355147395b4d4ac5c7fc8d
│ │ │ ├── bd0ce2248788b643ddfb8276aea4b659
│ │ │ ├── bf69634e838466bf0b83aa42a5fd1cd1
│ │ │ ├── c0c13a28a687b655688f8e10551e8df1
│ │ │ ├── c2e8e26fb3377705376b1d6d434e1233
│ │ │ ├── c3569a0e65500c3fd92ae9b8c3ac617b
│ │ │ ├── c4bcae8b1308ed48980134bb4d83f804
│ │ │ ├── c6487fc895704808bfbd28461eb5406d
│ │ │ ├── c787b5e7ee5160e73735755b872c0a41
│ │ │ ├── d719ca7fca663697fd096fb757b89920
│ │ │ ├── da939f28327bdd52576eec2c516a9ad3
│ │ │ ├── de7c51531b29594960229029a8eb6bd3
│ │ │ ├── e0de0a27b7e73c2def0370febf06b399
│ │ │ ├── e1595bc3bec4961c61a5304c1df226f0
│ │ │ ├── e2057ff9c72f6820163717d7ca69bf55
│ │ │ ├── e32a1cc092043108ec5025c1098a1dc8
│ │ │ ├── e4521446df02458bd88840687af212c5
│ │ │ ├── e5e9f136633ee06623a457e6c5bd9eac
│ │ │ ├── e6c06dd6393e96514f79db5d3bca100a
│ │ │ ├── ea077bf729e6510381278c68ee7c2b07
│ │ │ ├── ecc266c69b70073c8b0f6682498d0675
│ │ │ ├── edbfe6ac404682ef420377507d52ca4d
│ │ │ ├── f13c7b1cf4a5280dcc066d583c09bf78
│ │ │ ├── f20e83bfa143ade475b9403b9e21641f
│ │ │ ├── f8f0617cdbe162dec828ac596feae35d
│ │ │ ├── fcc0a2c84b265a77211ff0d4bd4a413a
│ │ │ ├── internal.0
│ │ │ ├── internal.1
│ │ │ ├── internal.10
│ │ │ ├── internal.11
│ │ │ ├── internal.12
│ │ │ ├── internal.13
│ │ │ ├── internal.14
│ │ │ ├── internal.15
│ │ │ ├── internal.16
│ │ │ ├── internal.17
│ │ │ ├── internal.18
│ │ │ ├── internal.19
│ │ │ ├── internal.2
│ │ │ ├── internal.20
│ │ │ ├── internal.21
│ │ │ ├── internal.22
│ │ │ ├── internal.23
│ │ │ ├── internal.24
│ │ │ ├── internal.25
│ │ │ ├── internal.26
│ │ │ ├── internal.27
│ │ │ ├── internal.28
│ │ │ ├── internal.29
│ │ │ ├── internal.3
│ │ │ ├── internal.30
│ │ │ ├── internal.31
│ │ │ ├── internal.32
│ │ │ ├── internal.33
│ │ │ ├── internal.34
│ │ │ ├── internal.35
│ │ │ ├── internal.36
│ │ │ ├── internal.37
│ │ │ ├── internal.38
│ │ │ ├── internal.39
│ │ │ ├── internal.4
│ │ │ ├── internal.40
│ │ │ ├── internal.41
│ │ │ ├── internal.42
│ │ │ ├── internal.43
│ │ │ ├── internal.44
│ │ │ ├── internal.45
│ │ │ ├── internal.46
│ │ │ ├── internal.47
│ │ │ ├── internal.48
│ │ │ ├── internal.49
│ │ │ ├── internal.5
│ │ │ ├── internal.50
│ │ │ ├── internal.51
│ │ │ ├── internal.52
│ │ │ ├── internal.53
│ │ │ ├── internal.54
│ │ │ ├── internal.55
│ │ │ ├── internal.56
│ │ │ ├── internal.57
│ │ │ ├── internal.58
│ │ │ ├── internal.59
│ │ │ ├── internal.6
│ │ │ ├── internal.60
│ │ │ ├── internal.61
│ │ │ ├── internal.62
│ │ │ ├── internal.63
│ │ │ ├── internal.64
│ │ │ ├── internal.65
│ │ │ ├── internal.66
│ │ │ ├── internal.67
│ │ │ ├── internal.68
│ │ │ ├── internal.69
│ │ │ ├── internal.7
│ │ │ ├── internal.70
│ │ │ ├── internal.71
│ │ │ ├── internal.72
│ │ │ ├── internal.73
│ │ │ ├── internal.74
│ │ │ ├── internal.75
│ │ │ ├── internal.76
│ │ │ ├── internal.77
│ │ │ ├── internal.78
│ │ │ ├── internal.79
│ │ │ ├── internal.8
│ │ │ ├── internal.80
│ │ │ ├── internal.81
│ │ │ ├── internal.82
│ │ │ ├── internal.83
│ │ │ ├── internal.84
│ │ │ ├── internal.85
│ │ │ ├── internal.86
│ │ │ ├── internal.87
│ │ │ ├── internal.88
│ │ │ ├── internal.89
│ │ │ ├── internal.9
│ │ │ ├── internal.90
│ │ │ ├── internal.91
│ │ │ ├── internal.92
│ │ │ ├── internal.93
│ │ │ ├── internal.94
│ │ │ ├── internal.95
│ │ │ ├── internal.96
│ │ │ ├── internal.97
│ │ │ └── internal.98
│ │ ├── .sbt.v2/
│ │ │ ├── v2.0107d767a345eff67ecdaed2ee5cd7ba.sbt
│ │ │ ├── v2.4e94e60265e04f0763142e20b52c0da1.sbt
│ │ │ ├── v2.60f7e23c24a8d94791cc7a8680c493f9.sbt
│ │ │ ├── v2.6d6e87e1154e95b279e5e7db414bc37b.sbt
│ │ │ ├── v2.b59473c94ff2889eca5d7165936e64b3.sbt
│ │ │ ├── v2.f0c834bc306651d2b9321fb21d3e8d8f.sbt
│ │ │ ├── v2.f71e78178af9e45e6f1d87a0c53c465c.sbt
│ │ │ ├── v2.internal.0.sbt
│ │ │ ├── v2.internal.1.sbt
│ │ │ ├── v2.internal.2.sbt
│ │ │ ├── v2.internal.3.sbt
│ │ │ ├── v2.internal.4.sbt
│ │ │ └── v2.internal.5.sbt
│ │ ├── .sbt.v3/
│ │ │ ├── 0107d767a345eff67ecdaed2ee5cd7ba
│ │ │ ├── 4e94e60265e04f0763142e20b52c0da1
│ │ │ ├── 60f7e23c24a8d94791cc7a8680c493f9
│ │ │ ├── 6d6e87e1154e95b279e5e7db414bc37b
│ │ │ ├── b59473c94ff2889eca5d7165936e64b3
│ │ │ ├── f0c834bc306651d2b9321fb21d3e8d8f
│ │ │ ├── f71e78178af9e45e6f1d87a0c53c465c
│ │ │ ├── internal.0
│ │ │ ├── internal.1
│ │ │ ├── internal.2
│ │ │ ├── internal.3
│ │ │ ├── internal.4
│ │ │ └── internal.5
│ │ ├── .sbt.v5_mhmt/
│ │ │ ├── 0107d767a345eff67ecdaed2ee5cd7ba
│ │ │ ├── 4e94e60265e04f0763142e20b52c0da1
│ │ │ ├── 60f7e23c24a8d94791cc7a8680c493f9
│ │ │ ├── 6d6e87e1154e95b279e5e7db414bc37b
│ │ │ ├── b59473c94ff2889eca5d7165936e64b3
│ │ │ ├── f0c834bc306651d2b9321fb21d3e8d8f
│ │ │ ├── f71e78178af9e45e6f1d87a0c53c465c
│ │ │ ├── internal.0
│ │ │ ├── internal.1
│ │ │ ├── internal.2
│ │ │ ├── internal.3
│ │ │ ├── internal.4
│ │ │ └── internal.5
│ │ ├── 10x-example/
│ │ │ ├── barcodes.tsv
│ │ │ ├── barcodes_renamer.tsv
│ │ │ ├── possorted_genome_bam.bam
│ │ │ ├── possorted_genome_bam.bam.bai
│ │ │ └── possorted_genome_bam_filtered.bam
│ │ ├── 2sigs.branch_0913.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── 3sigs.branch_0913.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── compare/
│ │ │ └── labels_from-test.csv
│ │ ├── duplicate-sigs/
│ │ │ └── README.md
│ │ ├── ecoli.faa
│ │ ├── ecoli.genes.fna
│ │ ├── fake-abund/
│ │ │ └── README.md
│ │ ├── gather/
│ │ │ ├── all-picklist.csv
│ │ │ ├── campy-picklist.csv
│ │ │ ├── salmonella-picklist-diffcolumn.csv
│ │ │ ├── salmonella-picklist.csv
│ │ │ └── thermotoga-picklist.csv
│ │ ├── genome-s11.fa.gz.msh.json_dump
│ │ ├── hmp-sigs/
│ │ │ ├── G36354-matches.lineages.csv
│ │ │ └── README.md
│ │ ├── lca/
│ │ │ ├── 47+63.lca.json
│ │ │ ├── bad-spreadsheet-2.csv
│ │ │ ├── bad-spreadsheet-3.csv
│ │ │ ├── bad-spreadsheet.csv
│ │ │ ├── both.lca.json
│ │ │ ├── classify-by-both.csv
│ │ │ ├── delmont-1.csv
│ │ │ ├── delmont-1.lca.json
│ │ │ ├── delmont-1.tsv
│ │ │ ├── delmont-2.csv
│ │ │ ├── delmont-2.lca.json
│ │ │ ├── delmont-3.csv
│ │ │ ├── delmont-4.csv
│ │ │ ├── delmont-5.csv
│ │ │ ├── delmont-6.csv
│ │ │ ├── dir1.lca.json
│ │ │ ├── dir2.lca.json
│ │ │ ├── old-db-format-1.json
│ │ │ ├── podar-lineage.csv
│ │ │ ├── separate.csv
│ │ │ ├── tara-delmont-SuppTable3.csv
│ │ │ ├── tully-genome-sigs.classify.csv
│ │ │ └── tully-query.delmont-db.sigs.classify.csv
│ │ ├── lca-root/
│ │ │ └── tax.csv
│ │ ├── leaves.sbt.json
│ │ ├── picklist/
│ │ │ └── empty.csv
│ │ ├── prot/
│ │ │ ├── build.sh
│ │ │ ├── dayhoff.rocksdb/
│ │ │ │ ├── 000008.log
│ │ │ │ ├── 000009.sst
│ │ │ │ ├── 000010.sst
│ │ │ │ ├── CURRENT
│ │ │ │ ├── IDENTITY
│ │ │ │ ├── LOCK
│ │ │ │ ├── MANIFEST-000005
│ │ │ │ └── OPTIONS-000007
│ │ │ ├── dna-sig.noext
│ │ │ ├── gtdb-subset-lineages.csv
│ │ │ ├── hp.rocksdb/
│ │ │ │ ├── 000008.log
│ │ │ │ ├── 000009.sst
│ │ │ │ ├── 000010.sst
│ │ │ │ ├── CURRENT
│ │ │ │ ├── IDENTITY
│ │ │ │ ├── LOCK
│ │ │ │ ├── MANIFEST-000005
│ │ │ │ └── OPTIONS-000007
│ │ │ └── protein.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── scaled/
│ │ │ ├── all.lca.json
│ │ │ ├── empty-lineage.csv
│ │ │ ├── mf.csv
│ │ │ └── pathlist.txt
│ │ ├── shewanella.faa
│ │ ├── short.fa.msh.dump
│ │ ├── sketch_fromfile/
│ │ │ ├── salmonella-badseq.csv
│ │ │ ├── salmonella-missing.csv
│ │ │ ├── salmonella-mult.csv
│ │ │ ├── salmonella-noname.csv
│ │ │ └── salmonella.csv
│ │ ├── sqlite/
│ │ │ ├── README.md
│ │ │ ├── delmont-6.csv
│ │ │ ├── index.sqldb
│ │ │ ├── lca-2.sqldb
│ │ │ ├── lca.sqldb
│ │ │ ├── prot.sqlmf
│ │ │ └── shewanella-lineage.csv
│ │ ├── subset.sbt.json
│ │ ├── tax/
│ │ │ ├── 47+63_x_gtdb-rs202.gather.csv
│ │ │ ├── bacteria_refseq_lineage.csv
│ │ │ ├── lemonade-MAG3.x.gtdb.csv
│ │ │ ├── lemonade-MAG3.x.gtdb.matches.tax.csv
│ │ │ ├── protozoa_genbank_lineage.csv
│ │ │ ├── test-empty-line.taxonomy.csv
│ │ │ ├── test-empty-ranks-2.taxonomy.csv
│ │ │ ├── test-empty-ranks-3.taxonomy.csv
│ │ │ ├── test-empty-ranks.taxonomy.csv
│ │ │ ├── test-missing-ranks.taxonomy.csv
│ │ │ ├── test-strain.taxonomy.csv
│ │ │ ├── test.LIN-taxonomy.csv
│ │ │ ├── test.ictv-taxonomy.csv
│ │ │ ├── test.ncbi-taxonomy.csv
│ │ │ ├── test.taxonomy.csv
│ │ │ ├── test1.gather.csv
│ │ │ ├── test1.gather.v450.csv
│ │ │ ├── test1.gather.with-lineages.csv
│ │ │ ├── test1.gather_old.csv
│ │ │ └── test1_x_gtdbrs202_genbank_euks.gather.csv
│ │ ├── track_abund/
│ │ │ └── 47+63.abund.rocksdb/
│ │ │ ├── 000008.log
│ │ │ ├── 000009.sst
│ │ │ ├── 000010.sst
│ │ │ ├── CURRENT
│ │ │ ├── IDENTITY
│ │ │ ├── LOCK
│ │ │ ├── MANIFEST-000005
│ │ │ └── OPTIONS-000007
│ │ ├── v1.sbt.json
│ │ ├── v2.sbt.json
│ │ ├── v3.sbt.json
│ │ ├── v4.sbt.json
│ │ ├── v5.sbt.json
│ │ ├── v5_mhmt.sbt.json
│ │ ├── v6.sbt.json
│ │ └── v6.sbt.zip.mf.csv
│ ├── test__minhash_hypothesis.py
│ ├── test_api.py
│ ├── test_bugs.py
│ ├── test_cmd_index.py
│ ├── test_cmd_signature.py
│ ├── test_cmd_signature_collect.py
│ ├── test_cmd_signature_fileinfo.py
│ ├── test_cmd_signature_grep.py
│ ├── test_compare.py
│ ├── test_deprecated.py
│ ├── test_distance_utils.py
│ ├── test_hll.py
│ ├── test_index.py
│ ├── test_index_protocol.py
│ ├── test_jaccard.py
│ ├── test_lca.py
│ ├── test_lca_db_protocol.py
│ ├── test_lca_functions.py
│ ├── test_manifest.py
│ ├── test_manifest_protocol.py
│ ├── test_minhash.py
│ ├── test_moltypes.py
│ ├── test_nodegraph.py
│ ├── test_np_utils.py
│ ├── test_picklist.py
│ ├── test_plugin_framework.py
│ ├── test_prefetch.py
│ ├── test_revindex.py
│ ├── test_rustobj.py
│ ├── test_sbt.py
│ ├── test_search.py
│ ├── test_signature.py
│ ├── test_sketchcomparison.py
│ ├── test_sourmash.py
│ ├── test_sourmash_args.py
│ ├── test_sourmash_compute.py
│ ├── test_sourmash_sketch.py
│ ├── test_sqlite_index.py
│ ├── test_tax.py
│ ├── test_tax_utils.py
│ └── test_test_framework.py
├── tox.ini
└── utils/
├── .gitignore
├── README.md
├── cardinality_estimate_confidence.py
├── check-tree.py
├── compute-dna-mh-another-way.py
├── compute-input-prot-another-way.py
├── compute-prot-mh-another-way.py
├── toml-to-zenodo-json.py
└── trim-noV.sh
Showing preview only (421K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4731 symbols across 197 files)
FILE: benchmarks/benchmarks.py
function load_sequences (line 26) | def load_sequences():
class TimeMinHashSuite (line 36) | class TimeMinHashSuite:
method setup (line 37) | def setup(self):
method time_add_sequence (line 48) | def time_add_sequence(self):
method time_add_protein (line 54) | def time_add_protein(self):
method time_get_mins (line 60) | def time_get_mins(self):
method time_add_hash (line 65) | def time_add_hash(self):
method time_add_many (line 70) | def time_add_many(self):
method time_similarity (line 74) | def time_similarity(self):
method time_count_common (line 80) | def time_count_common(self):
method time_merge (line 86) | def time_merge(self):
method time_copy (line 92) | def time_copy(self):
method time_concat (line 97) | def time_concat(self):
class PeakmemMinHashSuite (line 104) | class PeakmemMinHashSuite:
method setup (line 105) | def setup(self):
method peakmem_add_sequence (line 112) | def peakmem_add_sequence(self):
method peakmem_add_protein (line 118) | def peakmem_add_protein(self):
method peakmem_add_hash (line 124) | def peakmem_add_hash(self):
method peakmem_add_many (line 129) | def peakmem_add_many(self):
class TimeMinAbundanceSuite (line 137) | class TimeMinAbundanceSuite(TimeMinHashSuite):
method setup (line 138) | def setup(self):
method time_get_mins_abundance (line 146) | def time_get_mins_abundance(self):
method time_set_abundances (line 151) | def time_set_abundances(self):
method time_set_abundances_noclear (line 157) | def time_set_abundances_noclear(self):
class PeakmemMinAbundanceSuite (line 164) | class PeakmemMinAbundanceSuite(PeakmemMinHashSuite):
method setup (line 165) | def setup(self):
class TimeZipStorageSuite (line 173) | class TimeZipStorageSuite:
method setup (line 174) | def setup(self):
method time_load_from_zipstorage (line 188) | def time_load_from_zipstorage(self):
method time_load_small_from_zipstorage (line 193) | def time_load_small_from_zipstorage(self):
method teardown (line 198) | def teardown(self):
class PeakmemZipStorageSuite (line 202) | class PeakmemZipStorageSuite:
method setup (line 203) | def setup(self):
method peakmem_load_from_zipstorage (line 217) | def peakmem_load_from_zipstorage(self):
method peakmem_load_small_from_zipstorage (line 222) | def peakmem_load_small_from_zipstorage(self):
method teardown (line 227) | def teardown(self):
FILE: include/sourmash.h
type HashFunctions (line 11) | enum HashFunctions {
type HashFunctions (line 19) | typedef uint32_t HashFunctions;
type SourmashErrorCode (line 21) | enum SourmashErrorCode {
type SourmashErrorCode (line 60) | typedef uint32_t SourmashErrorCode;
type SourmashComputeParameters (line 62) | typedef struct SourmashComputeParameters SourmashComputeParameters;
type SourmashDatasetPicklist (line 64) | typedef struct SourmashDatasetPicklist SourmashDatasetPicklist;
type SourmashHyperLogLog (line 66) | typedef struct SourmashHyperLogLog SourmashHyperLogLog;
type SourmashKmerMinHash (line 68) | typedef struct SourmashKmerMinHash SourmashKmerMinHash;
type SourmashManifest (line 70) | typedef struct SourmashManifest SourmashManifest;
type SourmashManifestRowIter (line 72) | typedef struct SourmashManifestRowIter SourmashManifestRowIter;
type SourmashNodegraph (line 74) | typedef struct SourmashNodegraph SourmashNodegraph;
type SourmashRevIndex (line 76) | typedef struct SourmashRevIndex SourmashRevIndex;
type SourmashRevIndex_CounterGather (line 78) | typedef struct SourmashRevIndex_CounterGather SourmashRevIndex_CounterGa...
type SourmashSearchResult (line 80) | typedef struct SourmashSearchResult SourmashSearchResult;
type SourmashSignature (line 82) | typedef struct SourmashSignature SourmashSignature;
type SourmashZipStorage (line 84) | typedef struct SourmashZipStorage SourmashZipStorage;
type ScaledType (line 86) | typedef uint32_t ScaledType;
type SourmashStr (line 91) | typedef struct {
type SourmashManifestRow (line 106) | typedef struct {
FILE: src/core/benches/compute.rs
function add_sequence (line 10) | fn add_sequence(c: &mut Criterion) {
function add_sequence_protein (line 76) | fn add_sequence_protein(c: &mut Criterion) {
FILE: src/core/benches/gather.rs
function gather_stats_benchmarks (line 11) | fn gather_stats_benchmarks(c: &mut Criterion) {
FILE: src/core/benches/minhash.rs
function intersection (line 11) | fn intersection(c: &mut Criterion) {
FILE: src/core/benches/nodegraph.rs
function save_load (line 8) | fn save_load(c: &mut Criterion) {
FILE: src/core/build.rs
function main (line 3) | fn main() {
function copy_c_bindings (line 9) | fn copy_c_bindings(_crate_dir: &str) {}
function copy_c_bindings (line 12) | fn copy_c_bindings(crate_dir: &str) {
FILE: src/core/examples/generate_mqfs.rs
function main (line 12) | fn main() {
FILE: src/core/src/ani_utils.rs
function exp_n_mutated (line 10) | fn exp_n_mutated(l: f64, k: f64, r1: f64) -> f64 {
function var_n_mutated (line 15) | fn var_n_mutated(l: f64, k: f64, r1: f64, q: Option<f64>) -> Result<f64,...
function exp_n_mutated_squared (line 35) | fn exp_n_mutated_squared(l: f64, k: f64, p: f64) -> Result<f64, Error> {
function probit (line 41) | fn probit(p: f64) -> f64 {
function r1_to_q (line 45) | fn r1_to_q(k: f64, r1: f64) -> f64 {
function get_exp_probability_nothing_common (line 59) | fn get_exp_probability_nothing_common(
function ani_from_containment (line 82) | pub fn ani_from_containment(containment: f64, ksize: f64) -> f64 {
function ani_ci_from_containment (line 93) | pub fn ani_ci_from_containment(
function test_containment_to_ani_zero (line 153) | fn test_containment_to_ani_zero() {
function test_containment_to_ani_one (line 172) | fn test_containment_to_ani_one() {
function test_containment_to_ani_scaled1 (line 188) | fn test_containment_to_ani_scaled1() {
function test_containment_to_ani_scaled100 (line 204) | fn test_containment_to_ani_scaled100() {
function test_containment_to_ani_scaled100_2 (line 220) | fn test_containment_to_ani_scaled100_2() {
function test_var_n_mutated_zero (line 236) | fn test_var_n_mutated_zero() {
function test_var_n_mutated_value_error (line 245) | fn test_var_n_mutated_value_error() {
function test_var_n_mutated_success (line 260) | fn test_var_n_mutated_success() {
function test_r1_to_q (line 273) | fn test_r1_to_q() {
function test_exp_n_mutated (line 290) | fn test_exp_n_mutated() {
function test_get_exp_probability_nothing_common_ani_zero (line 313) | fn test_get_exp_probability_nothing_common_ani_zero() {
function test_get_exp_probability_nothing_common_ani_one (line 329) | fn test_get_exp_probability_nothing_common_ani_one() {
function test_get_exp_probability_nothing_common (line 345) | fn test_get_exp_probability_nothing_common() {
FILE: src/core/src/cmd.rs
method from_params (line 10) | pub fn from_params(params: &ComputeParameters) -> Signature {
type ComputeParameters (line 24) | pub struct ComputeParameters {
method default (line 111) | fn default() -> Self {
function build_template (line 116) | pub fn build_template(params: &ComputeParameters) -> Vec<Sketch> {
FILE: src/core/src/collection.rs
type Collection (line 18) | pub struct Collection {
method new (line 100) | pub fn new(manifest: Manifest, storage: InnerStorage) -> Self {
method iter (line 104) | pub fn iter(&self) -> impl Iterator<Item = (Idx, &Record)> {
method par_iter (line 109) | pub fn par_iter(&self) -> impl IndexedParallelIterator<Item = (Idx, &R...
method len (line 116) | pub fn len(&self) -> usize {
method is_empty (line 120) | pub fn is_empty(&self) -> bool {
method manifest (line 124) | pub fn manifest(&self) -> &Manifest {
method storage (line 128) | pub fn storage(&self) -> &InnerStorage {
method check_superset (line 132) | pub fn check_superset(&self, other: &Collection) -> Result<usize> {
method from_zipfile (line 141) | pub fn from_zipfile<P: AsRef<Path>>(zipfile: P) -> Result<Self> {
method from_rocksdb (line 152) | pub fn from_rocksdb<P: AsRef<Path>>(dirname: P) -> Result<Self> {
method from_sigs (line 162) | pub fn from_sigs(sigs: Vec<Signature>) -> Result<Self> {
method from_paths (line 190) | pub fn from_paths(paths: &[PathBuf]) -> Result<Self> {
method record_for_dataset (line 205) | pub fn record_for_dataset(&self, dataset_id: Idx) -> Result<&Record> {
method sig_for_dataset (line 209) | pub fn sig_for_dataset(&self, dataset_id: Idx) -> Result<SigStore> {
method sig_from_record (line 224) | pub fn sig_from_record(&self, record: &Record) -> Result<SigStore> {
method intersect_manifest (line 232) | pub fn intersect_manifest(&mut self, mf: &Manifest) {
method min_max_scaled (line 237) | pub fn min_max_scaled(&self) -> Option<(&ScaledType, &ScaledType)> {
type CollectionSet (line 26) | pub struct CollectionSet {
type Error (line 45) | type Error = crate::Error;
method try_from (line 47) | fn try_from(collection: Collection) -> Result<Self> {
method into_inner (line 78) | pub fn into_inner(self) -> Collection {
method selection (line 82) | pub fn selection(&self) -> Selection {
method set_storage_unchecked (line 94) | pub unsafe fn set_storage_unchecked(&mut self, storage: InnerStorage) {
type Target (line 31) | type Target = Collection;
method deref (line 33) | fn deref(&self) -> &Self::Target {
method deref_mut (line 39) | fn deref_mut(&mut self) -> &mut Self::Target {
method select (line 71) | fn select(mut self, selection: &Selection) -> Result<Self> {
method select (line 249) | fn select(mut self, selection: &Selection) -> Result<Self> {
function sigstore_selection_with_downsample (line 272) | fn sigstore_selection_with_downsample() {
function sigstore_selection_with_downsample_too_low (line 298) | fn sigstore_selection_with_downsample_too_low() {
function sigstore_selection_scaled_handle_num_sig (line 318) | fn sigstore_selection_scaled_handle_num_sig() {
function sigstore_selection_num (line 340) | fn sigstore_selection_num() {
function sigstore_selection_num_handle_scaled_sig (line 370) | fn sigstore_selection_num_handle_scaled_sig() {
function collection_intersect_manifest (line 392) | fn collection_intersect_manifest() {
function sigstore_sig_from_record (line 418) | fn sigstore_sig_from_record() {
function sigstore_sig_from_record_2 (line 445) | fn sigstore_sig_from_record_2() {
function sigstore_selection_moltype_zip (line 461) | fn sigstore_selection_moltype_zip() {
function sigstore_selection_moltype_sig (line 484) | fn sigstore_selection_moltype_sig() {
function collection_from_collectionset (line 511) | fn collection_from_collectionset() -> () {
function collection_selection (line 537) | fn collection_selection() -> () {
function collection_from_collectionset_fail (line 568) | fn collection_from_collectionset_fail() -> () {
function collection_from_rocksdb_storage (line 586) | fn collection_from_rocksdb_storage() -> Result<()> {
FILE: src/core/src/encodings.rs
type Color (line 18) | pub type Color = u64;
type Idx (line 19) | pub type Idx = u32;
type IdxTracker (line 20) | type IdxTracker = (vec_collections::VecSet<[Idx; 8]>, u64);
type ColorToIdx (line 21) | type ColorToIdx = HashMap<Color, IdxTracker, BuildNoHashHasher<Color>>;
type HashFunctions (line 29) | pub enum HashFunctions {
method dna (line 40) | pub fn dna(&self) -> bool {
method protein (line 44) | pub fn protein(&self) -> bool {
method dayhoff (line 48) | pub fn dayhoff(&self) -> bool {
method hp (line 52) | pub fn hp(&self) -> bool {
method skipm1n3 (line 56) | pub fn skipm1n3(&self) -> bool {
method skipm2n3 (line 60) | pub fn skipm2n3(&self) -> bool {
method fmt (line 66) | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
type Error (line 84) | type Error = Error;
method try_from (line 86) | fn try_from(moltype: &str) -> Result<Self, Self::Error> {
constant COMPLEMENT (line 101) | const COMPLEMENT: [u8; 256] = {
function revcomp (line 112) | pub fn revcomp(seq: &[u8]) -> Vec<u8> {
function translate_codon (line 323) | pub fn translate_codon(codon: &[u8]) -> Result<u8, Error> {
function aa_to_dayhoff (line 350) | pub fn aa_to_dayhoff(aa: u8) -> u8 {
function aa_to_hp (line 357) | pub fn aa_to_hp(aa: u8) -> u8 {
function to_aa (line 365) | pub fn to_aa(seq: &[u8], dayhoff: bool, hp: bool) -> Result<Vec<u8>, Err...
constant VALID (line 386) | pub const VALID: [bool; 256] = {
type Colors (line 396) | pub struct Colors {
method new (line 401) | pub fn new() -> Colors {
method update (line 413) | pub fn update<'a, I: IntoIterator<Item = &'a Idx>>(
method compute_color (line 476) | fn compute_color(idxs: &IdxTracker) -> Color {
method len (line 481) | pub fn len(&self) -> usize {
method is_empty (line 485) | pub fn is_empty(&self) -> bool {
method contains (line 489) | pub fn contains(&self, color: Color, idx: Idx) -> bool {
method indices (line 497) | pub fn indices(&self, color: &Color) -> Indices<'_> {
method retain (line 504) | pub fn retain<F>(&mut self, f: F)
type Indices (line 512) | pub struct Indices<'a> {
type Item (line 517) | type Item = &'a Idx;
method next (line 519) | fn next(&mut self) -> Option<Self::Item> {
type Xxh3Hash128 (line 526) | pub(crate) struct Xxh3Hash128(twox_hash::XxHash3_128);
method finish (line 530) | fn finish(&self) -> u64 {
method write (line 537) | fn write(&mut self, bytes: &[u8]) {
function colors_update (line 548) | fn colors_update() {
function colors_retain (line 566) | fn colors_retain() {
function test_dna_method (line 615) | fn test_dna_method() {
function test_protein_method (line 622) | fn test_protein_method() {
function test_dayhoff_method (line 629) | fn test_dayhoff_method() {
function test_hp_method (line 636) | fn test_hp_method() {
function test_skipm1n3_method (line 643) | fn test_skipm1n3_method() {
function test_skipm2n3_method (line 650) | fn test_skipm2n3_method() {
function test_display_hashfunctions (line 657) | fn test_display_hashfunctions() {
function test_try_from_str_valid (line 671) | fn test_try_from_str_valid() {
function test_try_from_str_invalid (line 699) | fn test_try_from_str_invalid() {
FILE: src/core/src/errors.rs
type SourmashError (line 5) | pub enum SourmashError {
type ReadDataError (line 113) | pub enum ReadDataError {
type SourmashErrorCode (line 120) | pub enum SourmashErrorCode {
method from_error (line 170) | pub fn from_error(error: &SourmashError) -> SourmashErrorCode {
FILE: src/core/src/ffi/cmd/compute.rs
type SourmashComputeParameters (line 8) | pub struct SourmashComputeParameters;
type RustObject (line 11) | type RustObject = ComputeParameters;
function computeparams_new (line 15) | pub unsafe extern "C" fn computeparams_new() -> *mut SourmashComputePara...
function computeparams_free (line 20) | pub unsafe extern "C" fn computeparams_free(ptr: *mut SourmashComputePar...
function computeparams_seed (line 25) | pub unsafe extern "C" fn computeparams_seed(ptr: *const SourmashComputeP...
function computeparams_set_seed (line 31) | pub unsafe extern "C" fn computeparams_set_seed(
function computeparams_ksizes_free (line 51) | pub unsafe extern "C" fn computeparams_ksizes_free(ptr: *mut u32, insize...
function computeparams_protein (line 79) | pub unsafe extern "C" fn computeparams_protein(ptr: *const SourmashCompu...
function computeparams_set_protein (line 85) | pub unsafe extern "C" fn computeparams_set_protein(ptr: *mut SourmashCom...
function computeparams_dayhoff (line 91) | pub unsafe extern "C" fn computeparams_dayhoff(ptr: *const SourmashCompu...
function computeparams_set_dayhoff (line 97) | pub unsafe extern "C" fn computeparams_set_dayhoff(ptr: *mut SourmashCom...
function computeparams_hp (line 103) | pub unsafe extern "C" fn computeparams_hp(ptr: *const SourmashComputePar...
function computeparams_set_hp (line 109) | pub unsafe extern "C" fn computeparams_set_hp(ptr: *mut SourmashComputeP...
function computeparams_dna (line 115) | pub unsafe extern "C" fn computeparams_dna(ptr: *const SourmashComputePa...
function computeparams_set_dna (line 121) | pub unsafe extern "C" fn computeparams_set_dna(ptr: *mut SourmashCompute...
function computeparams_skipm1n3 (line 127) | pub unsafe extern "C" fn computeparams_skipm1n3(ptr: *const SourmashComp...
function computeparams_set_skipm1n3 (line 133) | pub unsafe extern "C" fn computeparams_set_skipm1n3(ptr: *mut SourmashCo...
function computeparams_skipm2n3 (line 139) | pub unsafe extern "C" fn computeparams_skipm2n3(ptr: *const SourmashComp...
function computeparams_set_skipm2n3 (line 145) | pub unsafe extern "C" fn computeparams_set_skipm2n3(ptr: *mut SourmashCo...
function computeparams_track_abundance (line 151) | pub unsafe extern "C" fn computeparams_track_abundance(
function computeparams_set_track_abundance (line 159) | pub unsafe extern "C" fn computeparams_set_track_abundance(
function computeparams_num_hashes (line 168) | pub unsafe extern "C" fn computeparams_num_hashes(ptr: *const SourmashCo...
function computeparams_set_num_hashes (line 174) | pub unsafe extern "C" fn computeparams_set_num_hashes(
function computeparams_scaled (line 183) | pub unsafe extern "C" fn computeparams_scaled(ptr: *const SourmashComput...
function computeparams_set_scaled (line 189) | pub unsafe extern "C" fn computeparams_set_scaled(
FILE: src/core/src/ffi/hyperloglog.rs
type SourmashHyperLogLog (line 12) | pub struct SourmashHyperLogLog;
type RustObject (line 15) | type RustObject = HyperLogLog;
function hll_new (line 19) | pub unsafe extern "C" fn hll_new() -> *mut SourmashHyperLogLog {
function hll_free (line 24) | pub unsafe extern "C" fn hll_free(ptr: *mut SourmashHyperLogLog) {
function hll_ksize (line 39) | pub unsafe extern "C" fn hll_ksize(ptr: *const SourmashHyperLogLog) -> u...
function hll_cardinality (line 44) | pub unsafe extern "C" fn hll_cardinality(ptr: *const SourmashHyperLogLog...
function hll_similarity (line 49) | pub unsafe extern "C" fn hll_similarity(
function hll_containment (line 57) | pub unsafe extern "C" fn hll_containment(
function hll_intersection_size (line 65) | pub unsafe extern "C" fn hll_intersection_size(
function hll_add_hash (line 92) | pub unsafe extern "C" fn hll_add_hash(ptr: *mut SourmashHyperLogLog, has...
function hll_matches (line 123) | pub unsafe extern "C" fn hll_matches(
FILE: src/core/src/ffi/index/mod.rs
type SourmashSearchResult (line 9) | pub struct SourmashSearchResult;
type RustObject (line 12) | type RustObject = (f64, Signature, String);
function searchresult_free (line 16) | pub unsafe extern "C" fn searchresult_free(ptr: *mut SourmashSearchResul...
function searchresult_score (line 21) | pub unsafe extern "C" fn searchresult_score(ptr: *const SourmashSearchRe...
function searchresult_filename (line 27) | pub unsafe extern "C" fn searchresult_filename(ptr: *const SourmashSearc...
function searchresult_signature (line 33) | pub unsafe extern "C" fn searchresult_signature(
FILE: src/core/src/ffi/index/revindex.rs
type SourmashRevIndex (line 26) | pub struct SourmashRevIndex;
type RustObject (line 28) | type RustObject = module::RevIndex;
type SourmashDatasetPicklist (line 33) | pub struct SourmashDatasetPicklist;
type RustObject (line 35) | type RustObject = DatasetPicklist;
type SourmashRevIndex_CounterGather (line 42) | pub struct SourmashRevIndex_CounterGather;
type RustObject (line 44) | type RustObject = CounterGather;
function retrieve_picklist (line 47) | pub unsafe fn retrieve_picklist(
function revindex_free (line 114) | pub unsafe extern "C" fn revindex_free(ptr: *mut SourmashRevIndex) {
function revindex_countergather_free (line 119) | pub unsafe extern "C" fn revindex_countergather_free(ptr: *mut SourmashR...
function dataset_picklist_free (line 145) | pub unsafe extern "C" fn dataset_picklist_free(ptr: *mut SourmashDataset...
function revindex_len (line 150) | pub unsafe extern "C" fn revindex_len(
function revindex_ksize (line 179) | pub unsafe extern "C" fn revindex_ksize(ptr: *const SourmashRevIndex) ->...
function revindex_scaled (line 192) | pub unsafe extern "C" fn revindex_scaled(ptr: *const SourmashRevIndex) -...
function revindex_moltype (line 204) | pub unsafe extern "C" fn revindex_moltype(ptr: *const SourmashRevIndex) ...
function from_template (line 552) | pub fn from_template(template: &Sketch) -> Selection {
FILE: src/core/src/ffi/manifest.rs
type SourmashManifest (line 5) | pub struct SourmashManifest;
type RustObject (line 8) | type RustObject = Manifest;
function manifest_free (line 12) | pub unsafe extern "C" fn manifest_free(ptr: *mut SourmashManifest) {
type ManifestRowIterator (line 18) | pub struct ManifestRowIterator {
type SourmashManifestRowIter (line 22) | pub struct SourmashManifestRowIter;
type RustObject (line 25) | type RustObject = ManifestRowIterator;
function manifest_rows_iter_next (line 29) | pub unsafe extern "C" fn manifest_rows_iter_next(
function manifest_rows (line 41) | pub unsafe extern "C" fn manifest_rows(
type SourmashManifestRow (line 51) | pub struct SourmashManifestRow {
method from (line 76) | fn from(record: &Record) -> SourmashManifestRow {
type RustObject (line 65) | type RustObject = SourmashManifestRow;
function manifestrow_free (line 69) | pub unsafe extern "C" fn manifestrow_free(ptr: *mut SourmashManifestRow) {
FILE: src/core/src/ffi/minhash.rs
type SourmashKmerMinHash (line 12) | pub struct SourmashKmerMinHash;
type RustObject (line 15) | type RustObject = KmerMinHash;
function kmerminhash_new (line 19) | pub unsafe extern "C" fn kmerminhash_new(
function kmerminhash_free (line 33) | pub unsafe extern "C" fn kmerminhash_free(ptr: *mut SourmashKmerMinHash) {
function kmerminhash_slice_free (line 38) | pub unsafe extern "C" fn kmerminhash_slice_free(ptr: *mut u64, insize: u...
function kmerminhash_clear (line 130) | pub unsafe extern "C" fn kmerminhash_clear(ptr: *mut SourmashKmerMinHash) {
function kmerminhash_add_hash (line 137) | pub unsafe extern "C" fn kmerminhash_add_hash(ptr: *mut SourmashKmerMinH...
function kmerminhash_add_hash_with_abundance (line 144) | pub unsafe extern "C" fn kmerminhash_add_hash_with_abundance(
function kmerminhash_add_word (line 155) | pub unsafe extern "C" fn kmerminhash_add_word(ptr: *mut SourmashKmerMinH...
function sourmash_aa_to_dayhoff (line 182) | pub unsafe extern "C" fn sourmash_aa_to_dayhoff(aa: c_char) -> c_char {
function sourmash_aa_to_hp (line 187) | pub unsafe extern "C" fn sourmash_aa_to_hp(aa: c_char) -> c_char {
function kmerminhash_remove_hash (line 192) | pub unsafe extern "C" fn kmerminhash_remove_hash(ptr: *mut SourmashKmerM...
function kmerminhash_remove_many (line 199) | pub unsafe extern "C" fn kmerminhash_remove_many(
function kmerminhash_get_mins_size (line 274) | pub unsafe extern "C" fn kmerminhash_get_mins_size(ptr: *const SourmashK...
function kmerminhash_is_protein (line 317) | pub unsafe extern "C" fn kmerminhash_is_protein(ptr: *const SourmashKmer...
function kmerminhash_dayhoff (line 323) | pub unsafe extern "C" fn kmerminhash_dayhoff(ptr: *const SourmashKmerMin...
function kmerminhash_hp (line 329) | pub unsafe extern "C" fn kmerminhash_hp(ptr: *const SourmashKmerMinHash)...
function kmerminhash_skipm1n3 (line 335) | pub unsafe extern "C" fn kmerminhash_skipm1n3(ptr: *const SourmashKmerMi...
function kmerminhash_skipm2n3 (line 341) | pub unsafe extern "C" fn kmerminhash_skipm2n3(ptr: *const SourmashKmerMi...
function kmerminhash_seed (line 347) | pub unsafe extern "C" fn kmerminhash_seed(ptr: *const SourmashKmerMinHas...
function kmerminhash_track_abundance (line 353) | pub unsafe extern "C" fn kmerminhash_track_abundance(ptr: *const Sourmas...
function kmerminhash_disable_abundance (line 359) | pub unsafe extern "C" fn kmerminhash_disable_abundance(ptr: *mut Sourmas...
function kmerminhash_num (line 373) | pub unsafe extern "C" fn kmerminhash_num(ptr: *const SourmashKmerMinHash...
function kmerminhash_ksize (line 379) | pub unsafe extern "C" fn kmerminhash_ksize(ptr: *const SourmashKmerMinHa...
function kmerminhash_max_hash (line 385) | pub unsafe extern "C" fn kmerminhash_max_hash(ptr: *const SourmashKmerMi...
function kmerminhash_hash_function (line 391) | pub unsafe extern "C" fn kmerminhash_hash_function(
function kmerminhash_is_compatible (line 415) | pub unsafe extern "C" fn kmerminhash_is_compatible(
FILE: src/core/src/ffi/mod.rs
function hash_murmur (line 24) | pub unsafe extern "C" fn hash_murmur(kmer: *const c_char, seed: u64) -> ...
type HashFunctions (line 35) | pub enum HashFunctions {
method from (line 62) | fn from(v: crate::encodings::HashFunctions) -> HashFunctions {
function from (line 45) | fn from(v: HashFunctions) -> crate::encodings::HashFunctions {
FILE: src/core/src/ffi/nodegraph.rs
type SourmashNodegraph (line 11) | pub struct SourmashNodegraph;
type RustObject (line 14) | type RustObject = Nodegraph;
function nodegraph_new (line 18) | pub unsafe extern "C" fn nodegraph_new() -> *mut SourmashNodegraph {
function nodegraph_free (line 23) | pub unsafe extern "C" fn nodegraph_free(ptr: *mut SourmashNodegraph) {
function nodegraph_buffer_free (line 28) | pub unsafe extern "C" fn nodegraph_buffer_free(ptr: *mut u8, insize: usi...
function nodegraph_with_tables (line 36) | pub unsafe extern "C" fn nodegraph_with_tables(
function nodegraph_count (line 46) | pub unsafe extern "C" fn nodegraph_count(ptr: *mut SourmashNodegraph, h:...
function nodegraph_count_kmer (line 52) | pub unsafe extern "C" fn nodegraph_count_kmer(
function nodegraph_get (line 69) | pub unsafe extern "C" fn nodegraph_get(ptr: *const SourmashNodegraph, h:...
function nodegraph_get_kmer (line 75) | pub unsafe extern "C" fn nodegraph_get_kmer(
function nodegraph_expected_collisions (line 92) | pub unsafe extern "C" fn nodegraph_expected_collisions(ptr: *const Sourm...
function nodegraph_ksize (line 98) | pub unsafe extern "C" fn nodegraph_ksize(ptr: *const SourmashNodegraph) ...
function nodegraph_hashsizes (line 104) | pub unsafe extern "C" fn nodegraph_hashsizes(
function nodegraph_ntables (line 119) | pub unsafe extern "C" fn nodegraph_ntables(ptr: *const SourmashNodegraph...
function nodegraph_noccupied (line 125) | pub unsafe extern "C" fn nodegraph_noccupied(ptr: *const SourmashNodegra...
function nodegraph_matches (line 131) | pub unsafe extern "C" fn nodegraph_matches(
function nodegraph_update (line 143) | pub unsafe extern "C" fn nodegraph_update(
function nodegraph_update_mh (line 157) | pub unsafe extern "C" fn nodegraph_update_mh(
FILE: src/core/src/ffi/signature.rs
type SourmashSignature (line 18) | pub struct SourmashSignature;
type RustObject (line 21) | type RustObject = Signature;
function signature_new (line 27) | pub unsafe extern "C" fn signature_new() -> *mut SourmashSignature {
function signature_from_params (line 32) | pub unsafe extern "C" fn signature_from_params(
function signature_free (line 42) | pub unsafe extern "C" fn signature_free(ptr: *mut SourmashSignature) {
function signature_len (line 47) | pub unsafe extern "C" fn signature_len(ptr: *const SourmashSignature) ->...
FILE: src/core/src/ffi/storage.rs
type SourmashZipStorage (line 9) | pub struct SourmashZipStorage;
type RustObject (line 12) | type RustObject = Arc<ZipStorage>;
function zipstorage_free (line 29) | pub unsafe extern "C" fn zipstorage_free(ptr: *mut SourmashZipStorage) {
FILE: src/core/src/ffi/utils.rs
type ForeignObject (line 22) | pub trait ForeignObject: Sized {
method from_rust (line 26) | unsafe fn from_rust(object: Self::RustObject) -> *mut Self {
method from_ref (line 31) | unsafe fn from_ref(object: &Self::RustObject) -> *const Self {
method as_rust (line 36) | unsafe fn as_rust<'a>(pointer: *const Self) -> &'a Self::RustObject {
method as_rust_mut (line 41) | unsafe fn as_rust_mut<'a>(pointer: *mut Self) -> &'a mut Self::RustObj...
method into_rust (line 46) | unsafe fn into_rust(pointer: *mut Self) -> Box<Self::RustObject> {
method drop (line 51) | unsafe fn drop(pointer: *mut Self) {
type RustObject (line 321) | type RustObject = SourmashStr;
type Panic (line 88) | pub struct Panic(String);
function sourmash_err_get_last_message (line 95) | pub unsafe extern "C" fn sourmash_err_get_last_message() -> SourmashStr {
function sourmash_err_get_backtrace (line 113) | pub unsafe extern "C" fn sourmash_err_get_backtrace() -> SourmashStr {
function sourmash_err_clear (line 135) | pub unsafe extern "C" fn sourmash_err_clear() {
function sourmash_init (line 143) | pub unsafe extern "C" fn sourmash_init() {
function sourmash_err_get_last_code (line 153) | pub unsafe extern "C" fn sourmash_err_get_last_code() -> SourmashErrorCo...
function set_last_error (line 163) | fn set_last_error(err: Error) {
function set_panic_hook (line 169) | pub unsafe fn set_panic_hook() {
function landingpad (line 197) | pub unsafe fn landingpad<F, T>(f: F) -> T
type SourmashStr (line 213) | pub struct SourmashStr {
method new (line 233) | pub fn new(s: &str) -> SourmashStr {
method from_string (line 241) | pub fn from_string(mut s: String) -> SourmashStr {
method free (line 252) | pub unsafe fn free(&mut self) {
method as_str (line 261) | pub fn as_str(&self) -> &str {
method from (line 273) | fn from(string: String) -> SourmashStr {
method from (line 279) | fn from(string: &str) -> SourmashStr {
method from (line 285) | fn from(cow: Cow<'a, str>) -> SourmashStr {
method default (line 223) | fn default() -> SourmashStr {
method drop (line 267) | fn drop(&mut self) {
function sourmash_str_free (line 314) | pub unsafe extern "C" fn sourmash_str_free(s: *mut SourmashStr) {
FILE: src/core/src/index/linear.rs
type LinearIndex (line 21) | pub struct LinearIndex {
method from_collection (line 27) | pub fn from_collection(collection: CollectionSet) -> Self {
method sig_for_dataset (line 36) | pub fn sig_for_dataset(&self, dataset_id: Idx) -> Result<SigStore> {
method collection (line 40) | pub fn collection(&self) -> &CollectionSet {
method template (line 44) | pub fn template(&self) -> &Sketch {
method location (line 48) | pub fn location(&self) -> Option<String> {
method counter_for_query (line 52) | pub fn counter_for_query(&self, query: &KmerMinHash) -> SigCounter {
method search (line 115) | pub fn search(
method gather_round (line 141) | pub fn gather_round(
method stats_for_match (line 166) | fn stats_for_match(
method gather (line 247) | pub fn gather(
method signatures_iter (line 329) | pub fn signatures_iter(&self) -> impl Iterator<Item = SigStore> + '_ {
type Item (line 354) | type Item = SigStore;
method insert (line 356) | fn insert(&mut self, _node: Self::Item) -> Result<()> {
method save (line 360) | fn save<P: AsRef<std::path::Path>>(&self, _path: P) -> Result<()> {
method load (line 364) | fn load<P: AsRef<std::path::Path>>(_path: P) -> Result<()> {
method len (line 368) | fn len(&self) -> usize {
method signatures (line 372) | fn signatures(&self) -> Vec<Self::Item> {
method signature_refs (line 383) | fn signature_refs(&self) -> Vec<&Self::Item> {
method select (line 339) | fn select(self, selection: &Selection) -> Result<Self> {
FILE: src/core/src/index/mod.rs
type GatherResult (line 34) | pub struct GatherResult {
method get_match (line 122) | pub fn get_match(&self) -> Signature {
type SigCounter (line 127) | type SigCounter = counter::Counter<Idx>;
type Index (line 129) | pub trait Index<'a> {
method find (line 133) | fn find<F>(&self, search_fn: F, sig: &Self::Item, threshold: f64) -> R...
method search (line 150) | fn search(
method insert (line 165) | fn insert(&mut self, node: Self::Item) -> Result<()>;
method batch_insert (line 167) | fn batch_insert(&mut self, nodes: Vec<Self::Item>) -> Result<()> {
method save (line 175) | fn save<P: AsRef<Path>>(&self, path: P) -> Result<()>;
method load (line 177) | fn load<P: AsRef<Path>>(path: P) -> Result<()>;
method signatures (line 179) | fn signatures(&self) -> Vec<Self::Item>;
method signature_refs (line 181) | fn signature_refs(&self) -> Vec<&Self::Item>;
method len (line 183) | fn len(&self) -> usize {
method is_empty (line 187) | fn is_empty(&self) -> bool {
function similarity (line 200) | fn similarity(&self, other: &L) -> f64 {
function containment (line 204) | fn containment(&self, other: &L) -> f64 {
function calculate_gather_stats (line 210) | pub fn calculate_gather_stats(
constant EPSILON (line 366) | const EPSILON: f64 = 0.01;
function test_calculate_gather_stats (line 369) | fn test_calculate_gather_stats() {
FILE: src/core/src/index/revindex/disk_revindex.rs
constant DB_VERSION (line 30) | const DB_VERSION: u8 = 1;
constant MANIFEST (line 33) | const MANIFEST: &str = "manifest";
constant STORAGE_SPEC (line 34) | const STORAGE_SPEC: &str = "storage_spec";
constant VERSION (line 35) | const VERSION: &str = "version";
constant PROCESSED (line 36) | const PROCESSED: &str = "processed";
function compute_color (line 38) | fn compute_color(idxs: &Datasets) -> Color {
type DiskRevIndex (line 44) | pub struct DiskRevIndex {
method create (line 78) | pub fn create(path: &Path, collection: CollectionSet) -> Result<module...
method open (line 134) | pub fn open<P: AsRef<Path>>(
method db (line 183) | pub unsafe fn db(&self) -> Arc<DB> {
method load_processed (line 187) | fn load_processed(
method load_collection_from_rocksdb (line 204) | fn load_collection_from_rocksdb(
method save_collection (line 233) | fn save_collection(&self) -> Result<()> {
method map_hashes_colors (line 259) | fn map_hashes_colors(&self, dataset_id: Idx) {
function merge_datasets (line 51) | pub(crate) fn merge_datasets(
method location (line 297) | fn location(&self) -> &str {
method counter_for_query (line 301) | fn counter_for_query(
method prepare_gather_counters (line 338) | fn prepare_gather_counters(
method gather (line 402) | fn gather(
method update (line 489) | fn update(mut self, collection: CollectionSet) -> Result<module::RevInde...
method check (line 541) | fn check(&self, quick: bool) -> DbStats {
method compact (line 545) | fn compact(&self) {
method flush (line 552) | fn flush(&self) -> Result<()> {
method collection (line 563) | fn collection(&self) -> &CollectionSet {
method internalize_storage (line 567) | fn internalize_storage(&mut self) -> Result<()> {
method convert (line 603) | fn convert(&self, _output_db: module::RevIndex) -> Result<()> {
method find_signatures (line 644) | fn find_signatures(
FILE: src/core/src/index/revindex/mem_revindex.rs
type MemRevIndex (line 26) | pub struct MemRevIndex {
method new (line 91) | pub fn new(
method from_zipfile (line 108) | pub fn from_zipfile<P: AsRef<Path>>(
method merge_queries (line 124) | fn merge_queries(qs: &[KmerMinHash], threshold: usize) -> Option<KmerM...
method new_with_sigs (line 136) | pub fn new_with_sigs(
method map_hashes_colors (line 153) | fn map_hashes_colors(
method search (line 199) | pub fn search(
method template (line 208) | pub fn template(&self) -> Sketch {
method scaled (line 212) | pub fn scaled(&self) -> ScaledType {
type Item (line 413) | type Item = Signature;
method insert (line 415) | fn insert(&mut self, _node: Self::Item) -> Result<()> {
method save (line 419) | fn save<P: AsRef<std::path::Path>>(&self, _path: P) -> Result<()> {
method load (line 423) | fn load<P: AsRef<std::path::Path>>(_path: P) -> Result<()> {
method len (line 427) | fn len(&self) -> usize {
method signatures (line 431) | fn signatures(&self) -> Vec<Self::Item> {
method signature_refs (line 439) | fn signature_refs(&self) -> Vec<&Self::Item> {
method index (line 33) | fn index(
method location (line 222) | fn location(&self) -> &str {
method counter_for_query (line 226) | fn counter_for_query(
method prepare_gather_counters (line 246) | fn prepare_gather_counters(
method gather (line 282) | fn gather(
method update (line 328) | fn update(self, _collection: CollectionSet) -> Result<module::RevIndex> {
method check (line 332) | fn check(&self, _quick: bool) -> DbStats {
method compact (line 336) | fn compact(&self) {}
method flush (line 338) | fn flush(&self) -> Result<()> {
method collection (line 342) | fn collection(&self) -> &CollectionSet {
method internalize_storage (line 346) | fn internalize_storage(&mut self) -> Result<()> {
method convert (line 350) | fn convert(&self, _output_db: module::RevIndex) -> Result<()> {
method find_signatures (line 354) | fn find_signatures(
function mem_revindex_new (line 452) | fn mem_revindex_new() -> Result<()> {
function mem_revindex_many (line 471) | fn mem_revindex_many() -> Result<()> {
function mem_revindex_from_sigs (line 505) | fn mem_revindex_from_sigs() -> Result<()> {
function mem_revindex_from_zipstorage (line 540) | fn mem_revindex_from_zipstorage() -> Result<()> {
function mem_revindex_test_gather_2 (line 593) | fn mem_revindex_test_gather_2() -> Result<()> {
function mem_revindex_test_gather_3 (line 628) | fn mem_revindex_test_gather_3() -> Result<()> {
function mem_revindex_load_and_gather_2 (line 670) | fn mem_revindex_load_and_gather_2() -> Result<()> {
function revindex_load_and_test_counter_gather (line 821) | fn revindex_load_and_test_counter_gather() -> Result<()> {
function revindex_load_and_gather_picklist (line 877) | fn revindex_load_and_gather_picklist() -> Result<()> {
function mem_revindex_find_signatures (line 951) | fn mem_revindex_find_signatures() -> Result<()> {
FILE: src/core/src/index/revindex/mod.rs
type QueryColors (line 29) | type QueryColors = HashMap<Color, Datasets>;
type HashToColorT (line 31) | type HashToColorT = HashMap<HashIntoType, Color, BuildNoHashHasher<HashI...
type HashToColor (line 34) | pub struct HashToColor(HashToColorT);
method new (line 235) | fn new() -> Self {
method get (line 243) | fn get(&self, hash: &HashIntoType) -> Option<&Color> {
method len (line 247) | fn len(&self) -> usize {
method is_empty (line 251) | fn is_empty(&self) -> bool {
method add_to (line 255) | fn add_to(&mut self, colors: &mut Colors, dataset_id: Idx, matched_has...
method reduce_hashes_colors (line 264) | fn reduce_hashes_colors(
method from_iter (line 303) | fn from_iter<T>(iter: T) -> Self
type CounterGather (line 39) | pub struct CounterGather {
method is_empty (line 169) | pub fn is_empty(&self) -> bool {
method len (line 173) | pub fn len(&self) -> usize {
method found_hashes (line 178) | pub fn found_hashes(&self, template: &KmerMinHash) -> KmerMinHash {
method peek (line 189) | pub fn peek(&self, threshold: usize) -> Option<(Idx, usize)> {
method dataset_ids (line 202) | pub fn dataset_ids(&self) -> Vec<Idx> {
method consume (line 207) | pub fn consume(&mut self, intersect_mh: &KmerMinHash) {
type RevIndex (line 46) | pub enum RevIndex {
method create (line 321) | pub fn create<P: AsRef<Path>>(index: P, collection: CollectionSet) -> ...
method open (line 325) | pub fn open<P: AsRef<Path>>(index: P, read_only: bool, spec: Option<&s...
type DatasetPicklist (line 52) | pub struct DatasetPicklist {
type RevIndexOps (line 57) | pub trait RevIndexOps {
method location (line 62) | fn location(&self) -> &str;
method len (line 64) | fn len(&self) -> usize {
method is_empty (line 68) | fn is_empty(&self) -> bool {
method signatures (line 72) | fn signatures(&self) -> Vec<Signature> {
method counter_for_query (line 82) | fn counter_for_query(
method matches_from_counter (line 88) | fn matches_from_counter(&self, counter: SigCounter, threshold: usize) ...
method records_from_counter (line 112) | fn records_from_counter(&self, counter: SigCounter, threshold: usize) ...
method prepare_gather_counters (line 130) | fn prepare_gather_counters(
method update (line 136) | fn update(self, collection: CollectionSet) -> Result<RevIndex>
method compact (line 140) | fn compact(&self);
method flush (line 142) | fn flush(&self) -> Result<()>;
method convert (line 144) | fn convert(&self, output_db: RevIndex) -> Result<()>;
method check (line 146) | fn check(&self, quick: bool) -> DbStats;
method gather (line 148) | fn gather(
method collection (line 156) | fn collection(&self) -> &CollectionSet;
method internalize_storage (line 158) | fn internalize_storage(&mut self) -> Result<()>;
method find_signatures (line 160) | fn find_signatures(
function prepare_query (line 339) | pub fn prepare_query(search_sig: Signature, selection: &Selection) -> Op...
type Datasets (line 352) | pub enum Datasets {
method extend (line 390) | fn extend<T>(&mut self, iter: T)
method new (line 418) | pub fn new(vals: &[Idx]) -> Self {
method from_slice (line 428) | pub fn from_slice(slice: &[u8]) -> Result<Self> {
method as_bytes (line 445) | fn as_bytes(&self) -> Option<Vec<u8>> {
method union (line 463) | fn union(&mut self, other: Datasets) {
method is_empty (line 485) | pub fn is_empty(&self) -> bool {
method len (line 489) | pub fn len(&self) -> usize {
method contains (line 497) | fn contains(&self, value: &Idx) -> bool {
method hash (line 360) | fn hash<H>(&self, state: &mut H)
type Item (line 377) | type Item = Idx;
type IntoIter (line 378) | type IntoIter = Box<dyn Iterator<Item = Self::Item>>;
method into_iter (line 380) | fn into_iter(self) -> Self::IntoIter {
type DbStats (line 507) | pub struct DbStats {
function stats_for_cf (line 524) | fn stats_for_cf(db: Arc<DB>, cf_name: &str, deep_check: bool, quick: boo...
function disk_revindex_index (line 582) | fn disk_revindex_index() -> Result<()> {
function disk_revindex_update (line 622) | fn disk_revindex_update() -> Result<()> {
function disk_revindex_load_and_gather (line 670) | fn disk_revindex_load_and_gather() -> Result<()> {
function disk_revindex_load_and_gather_2 (line 715) | fn disk_revindex_load_and_gather_2() -> Result<()> {
function disk_revindex_load_and_gather_3 (line 872) | fn disk_revindex_load_and_gather_3() -> Result<()> {
function revindex_load_and_gather_picklist (line 955) | fn revindex_load_and_gather_picklist() -> Result<()> {
function disk_revindex_find_signatures (line 1033) | fn disk_revindex_find_signatures() -> Result<()> {
function disk_revindex_move (line 1082) | fn disk_revindex_move() -> Result<()> {
function disk_revindex_internalize_storage (line 1143) | fn disk_revindex_internalize_storage() -> Result<()> {
function rocksdb_storage_from_path (line 1200) | fn rocksdb_storage_from_path() -> Result<()> {
function rocksdb_storage_fail_bad_directory (line 1271) | fn rocksdb_storage_fail_bad_directory() -> Result<()> {
function countergather_basic (line 1281) | fn countergather_basic() -> Result<()> {
FILE: src/core/src/index/search.rs
function search_minhashes (line 3) | pub fn search_minhashes<L>(node: &dyn Comparable<L>, query: &L, threshol...
function search_minhashes_containment (line 7) | pub fn search_minhashes_containment<L>(
function search_minhashes_find_best (line 15) | pub fn search_minhashes_find_best<L>() -> fn(&dyn Comparable<L>, &L, f64...
FILE: src/core/src/lib.rs
type Result (line 24) | pub type Result<T> = std::result::Result<T, Error>;
type HashIntoType (line 66) | type HashIntoType = u64;
type ScaledType (line 67) | pub type ScaledType = u32;
function _hash_murmur (line 69) | pub fn _hash_murmur(kmer: &[u8], seed: u64) -> u64 {
FILE: src/core/src/manifest.rs
type Record (line 23) | pub struct Record {
method fmt (line 86) | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::result::Resul...
method from_sig (line 100) | pub fn from_sig(sig: &Signature, path: &str) -> Vec<Self> {
method moltype (line 152) | pub fn moltype(&self) -> HashFunctions {
method check_compatible (line 156) | pub fn check_compatible(&self, other: &Record) -> Result<()> {
function intbool (line 57) | fn intbool<S>(x: &bool, s: S) -> std::result::Result<S::Ok, S::Error>
function to_bool (line 68) | fn to_bool<'de, D>(deserializer: D) -> std::result::Result<bool, D::Error>
type Manifest (line 94) | pub struct Manifest {
method from_reader (line 219) | pub fn from_reader<R: Read>(rdr: R) -> Result<Self> {
method to_writer (line 232) | pub fn to_writer<W: Write>(&self, mut wtr: W) -> Result<()> {
method internal_locations (line 244) | pub fn internal_locations(&self) -> impl Iterator<Item = &str> {
method iter (line 248) | pub fn iter(&self) -> impl Iterator<Item = &Record> {
method intersect_manifest (line 252) | pub fn intersect_manifest(&self, other: &Manifest) -> Self {
method from (line 338) | fn from(records: Vec<Record>) -> Self {
method from (line 344) | fn from(paths: &[PathBuf]) -> Self {
method from (line 367) | fn from(pathlist: &PathBuf) -> Self {
method eq (line 189) | fn eq(&self, other: &Self) -> bool {
method hash (line 205) | fn hash<H: Hasher>(&self, state: &mut H) {
method select (line 270) | fn select(self, selection: &Selection) -> Result<Self> {
method select (line 320) | fn select(self, selection: &Selection) -> Result<Self> {
type Target (line 382) | type Target = Vec<Record>;
method deref (line 384) | fn deref(&self) -> &Self::Target {
function manifest_from_pathlist (line 402) | fn manifest_from_pathlist() {
function manifest_from_pathlist_nonexistent_file (line 434) | fn manifest_from_pathlist_nonexistent_file() {
function manifest_from_pathlist_badfile (line 441) | fn manifest_from_pathlist_badfile() {
function manifest_from_paths_badpath (line 459) | fn manifest_from_paths_badpath() {
function manifest_to_writer_bools (line 476) | fn manifest_to_writer_bools() {
function manifest_to_writer_moltype_dna (line 514) | fn manifest_to_writer_moltype_dna() {
function manifest_selection (line 545) | fn manifest_selection() {
function manifest_intersect (line 591) | fn manifest_intersect() {
FILE: src/core/src/prelude.rs
type ToWriter (line 9) | pub trait ToWriter {
method to_writer (line 10) | fn to_writer<W>(&self, writer: &mut W) -> Result<()>
type Update (line 15) | pub trait Update<O> {
method update (line 16) | fn update(&self, other: &mut O) -> Result<()>;
type FromFactory (line 19) | pub trait FromFactory<N> {
method factory (line 20) | fn factory(&self, name: &str) -> Result<N>;
type ReadData (line 24) | pub trait ReadData<D> {
method data (line 25) | fn data(&self) -> Result<&D>;
type Comparable (line 29) | pub trait Comparable<O> {
method similarity (line 30) | fn similarity(&self, other: &O) -> f64;
method containment (line 31) | fn containment(&self, other: &O) -> f64;
FILE: src/core/src/selection.rs
type Selection (line 9) | pub struct Selection {
method ksize (line 66) | pub fn ksize(&self) -> Option<u32> {
method set_ksize (line 70) | pub fn set_ksize(&mut self, ksize: u32) {
method abund (line 74) | pub fn abund(&self) -> Option<bool> {
method set_abund (line 78) | pub fn set_abund(&mut self, value: bool) {
method num (line 82) | pub fn num(&self) -> Option<u32> {
method set_num (line 86) | pub fn set_num(&mut self, num: u32) {
method scaled (line 90) | pub fn scaled(&self) -> Option<ScaledType> {
method set_scaled (line 94) | pub fn set_scaled(&mut self, scaled: ScaledType) {
method containment (line 98) | pub fn containment(&self) -> Option<bool> {
method set_containment (line 102) | pub fn set_containment(&mut self, containment: bool) {
method moltype (line 106) | pub fn moltype(&self) -> Option<HashFunctions> {
method set_moltype (line 110) | pub fn set_moltype(&mut self, value: HashFunctions) {
method picklist (line 114) | pub fn picklist(&self) -> Option<Picklist> {
method set_picklist (line 118) | pub fn set_picklist(&mut self, value: Picklist) {
method from_record (line 122) | pub fn from_record(row: &Record) -> Result<Self> {
type Picklist (line 33) | pub struct Picklist {
type PickStyle (line 53) | pub enum PickStyle {
type Select (line 59) | pub trait Select {
method select (line 60) | fn select(self, selection: &Selection) -> Result<Self>
FILE: src/core/src/signature.rs
type SigsTrait (line 29) | pub trait SigsTrait {
method size (line 30) | fn size(&self) -> usize;
method to_vec (line 31) | fn to_vec(&self) -> Vec<u64>;
method ksize (line 32) | fn ksize(&self) -> usize;
method check_compatible (line 33) | fn check_compatible(&self, other: &Self) -> Result<(), Error>;
method seed (line 34) | fn seed(&self) -> u64;
method hash_function (line 36) | fn hash_function(&self) -> HashFunctions;
method add_hash (line 38) | fn add_hash(&mut self, hash: HashIntoType);
method add_sequence (line 40) | fn add_sequence(&mut self, seq: &[u8], force: bool) -> Result<(), Erro...
method add_protein (line 62) | fn add_protein(&mut self, seq: &[u8]) -> Result<(), Error> {
method size (line 86) | fn size(&self) -> usize {
method to_vec (line 94) | fn to_vec(&self) -> Vec<u64> {
method ksize (line 102) | fn ksize(&self) -> usize {
method seed (line 110) | fn seed(&self) -> u64 {
method hash_function (line 118) | fn hash_function(&self) -> HashFunctions {
method add_hash (line 126) | fn add_hash(&mut self, hash: HashIntoType) {
method check_compatible (line 134) | fn check_compatible(&self, other: &Self) -> Result<(), Error> {
method add_sequence (line 151) | fn add_sequence(&mut self, seq: &[u8], force: bool) -> Result<(), Erro...
method add_protein (line 159) | fn add_protein(&mut self, seq: &[u8]) -> Result<(), Error> {
type ReadingFrame (line 169) | pub enum ReadingFrame {
method fmt (line 182) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method new_dna (line 201) | pub fn new_dna(sequence: &[u8]) -> Self {
method new_protein (line 208) | pub fn new_protein(sequence: &[u8], dayhoff: bool, hp: bool) -> Self {
method new_skipmer (line 222) | pub fn new_skipmer(
method new_translated (line 246) | pub fn new_translated(
method fw (line 279) | pub fn fw(&self) -> &[u8] {
method rc (line 288) | pub fn rc(&self) -> &[u8] {
method length (line 296) | pub fn length(&self) -> usize {
method frame_type (line 304) | pub fn frame_type(&self) -> &'static str {
type SeqToHashes (line 312) | pub struct SeqToHashes {
method new (line 323) | pub fn new(
method dna_frames (line 365) | fn dna_frames(seq: &[u8]) -> Vec<ReadingFrame> {
method protein_frames (line 370) | fn protein_frames(seq: &[u8], hash_function: &HashFunctions) -> Vec<Re...
method translated_frames (line 379) | fn translated_frames(
method skipmer_frames (line 409) | fn skipmer_frames(
method out_of_bounds (line 429) | fn out_of_bounds(&self, frame: &ReadingFrame) -> bool {
type Item (line 435) | type Item = Result<u64, Error>;
method next (line 437) | fn next(&mut self) -> Option<Self::Item> {
type Signature (line 508) | pub struct Signature {
method name (line 550) | pub fn name(&self) -> Option<String> {
method name_str (line 555) | pub fn name_str(&self) -> String {
method set_name (line 559) | pub fn set_name(&mut self, name: &str) {
method filename (line 563) | pub fn filename(&self) -> String {
method set_filename (line 571) | pub fn set_filename(&mut self, name: &str) {
method size (line 575) | pub fn size(&self) -> usize {
method sketches (line 579) | pub fn sketches(&self) -> Vec<Sketch> {
method reset_sketches (line 583) | pub fn reset_sketches(&mut self) {
method push (line 587) | pub fn push(&mut self, sketch: Sketch) {
method license (line 591) | pub fn license(&self) -> String {
method class (line 595) | pub fn class(&self) -> String {
method hash_function (line 599) | pub fn hash_function(&self) -> String {
method email (line 603) | pub fn email(&self) -> String {
method md5sum (line 607) | pub fn md5sum(&self) -> String {
method select_sketch (line 620) | pub fn select_sketch(&self, sketch: &Sketch) -> Option<&Sketch> {
method get_sketch (line 638) | pub fn get_sketch(&self) -> Option<&Sketch> {
method minhash (line 654) | pub fn minhash(&self) -> Option<&KmerMinHash> {
method from_path (line 670) | pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Vec<Signature>, Er...
method from_reader (line 675) | pub fn from_reader<R>(rdr: R) -> Result<Vec<Signature>, Error>
method load_signatures (line 685) | pub fn load_signatures<R>(
method add_sequence (line 762) | pub fn add_sequence(&mut self, seq: &[u8], force: bool) -> Result<(), ...
method add_protein (line 780) | pub fn add_protein(&mut self, seq: &[u8]) -> Result<(), Error> {
method iter_mut (line 800) | pub fn iter_mut(&mut self) -> IterMut<'_> {
method iter (line 808) | pub fn iter(&self) -> Iter<'_> {
type Error (line 1002) | type Error = Error;
method try_into (line 1004) | fn try_into(self) -> Result<KmerMinHash, Error> {
function default_license (line 537) | fn default_license() -> String {
function default_class (line 541) | fn default_class() -> String {
function default_version (line 545) | fn default_version() -> f64 {
type IterMut (line 817) | pub struct IterMut<'a> {
type Item (line 823) | type Item = &'a mut Sketch;
type IntoIter (line 824) | type IntoIter = IterMut<'a>;
method into_iter (line 826) | fn into_iter(self) -> IterMut<'a> {
type Item (line 832) | type Item = &'a mut Sketch;
method next (line 834) | fn next(&mut self) -> Option<&'a mut Sketch> {
method size_hint (line 843) | fn size_hint(&self) -> (usize, Option<usize>) {
type Iter (line 848) | pub struct Iter<'a> {
type Item (line 854) | type Item = &'a Sketch;
method next (line 856) | fn next(&mut self) -> Option<&'a Sketch> {
method size_hint (line 865) | fn size_hint(&self) -> (usize, Option<usize>) {
method len (line 873) | fn len(&self) -> usize {
method clone (line 879) | fn clone(&self) -> Self {
method to_writer (line 888) | fn to_writer<W>(&self, writer: &mut W) -> Result<(), Error>
method to_writer (line 898) | fn to_writer<W>(&self, writer: &mut W) -> Result<(), Error>
method select (line 908) | fn select(mut self, selection: &Selection) -> Result<Self, Error> {
method default (line 966) | fn default() -> Signature {
method eq (line 981) | fn eq(&self, other: &Signature) -> bool {
function load_sig (line 1043) | fn load_sig() {
function load_signature (line 1060) | fn load_signature() {
function signature_from_computeparams (line 1084) | fn signature_from_computeparams() {
function signature_slow_path (line 1103) | fn signature_slow_path() {
function signature_add_sequence_protein (line 1121) | fn signature_add_sequence_protein() {
function signature_add_protein (line 1139) | fn signature_add_protein() {
function signature_skipm2n3_add_sequence (line 1157) | fn signature_skipm2n3_add_sequence() {
function signature_skipm1n3_add_sequence (line 1178) | fn signature_skipm1n3_add_sequence() {
function signature_skipm2n3_add_sequence_too_small (line 1198) | fn signature_skipm2n3_add_sequence_too_small() {
function signature_skipm1n3_add_sequence_too_small (line 1224) | fn signature_skipm1n3_add_sequence_too_small() {
function signature_add_sequence_cp (line 1249) | fn signature_add_sequence_cp() {
function load_minhash_from_signature (line 1275) | fn load_minhash_from_signature() {
function load_single_sketch_from_signature (line 1291) | fn load_single_sketch_from_signature() {
function get_sketch_multisketch_panic (line 1315) | fn get_sketch_multisketch_panic() {
function load_minhash_multisketch_panic (line 1340) | fn load_minhash_multisketch_panic() {
function selection_with_downsample (line 1364) | fn selection_with_downsample() {
function selection_protein (line 1388) | fn selection_protein() {
function selection_dayhoff (line 1408) | fn selection_dayhoff() {
function selection_hp (line 1429) | fn selection_hp() {
function selection_protein2 (line 1449) | fn selection_protein2() {
function selection_scaled_too_low (line 1469) | fn selection_scaled_too_low() {
function test_readingframe_dna (line 1488) | fn test_readingframe_dna() {
function test_fw_dna (line 1497) | fn test_fw_dna() {
function test_rc_dna (line 1507) | fn test_rc_dna() {
function test_length_dna (line 1517) | fn test_length_dna() {
function test_frame_type_dna (line 1527) | fn test_frame_type_dna() {
function test_fw_protein (line 1537) | fn test_fw_protein() {
function test_rc_protein_panics (line 1547) | fn test_rc_protein_panics() {
function test_length_protein (line 1556) | fn test_length_protein() {
function test_frame_type_protein (line 1565) | fn test_frame_type_protein() {
function test_readingframe_display_protein (line 1574) | fn test_readingframe_display_protein() {
function test_seqtohashes_frames_dna (line 1587) | fn test_seqtohashes_frames_dna() {
function test_seqtohashes_frames_is_protein (line 1605) | fn test_seqtohashes_frames_is_protein() {
function test_readingframe_protein (line 1622) | fn test_readingframe_protein() {
function test_seqtohashes_frames_is_protein_try_access_rc (line 1633) | fn test_seqtohashes_frames_is_protein_try_access_rc() {
function test_seqtohashes_frames_is_protein_dayhoff (line 1651) | fn test_seqtohashes_frames_is_protein_dayhoff() {
function test_seqtohashes_frames_is_protein_hp (line 1669) | fn test_seqtohashes_frames_is_protein_hp() {
function test_seqtohashes_frames_translate_protein (line 1687) | fn test_seqtohashes_frames_translate_protein() {
function test_readingframe_translate (line 1708) | fn test_readingframe_translate() {
function test_readingframe_skipmer (line 1725) | fn test_readingframe_skipmer() {
function test_seqtohashes_frames_skipmer_m1n3 (line 1747) | fn test_seqtohashes_frames_skipmer_m1n3() {
function test_seqtohashes_frames_skipmer_m2n3 (line 1775) | fn test_seqtohashes_frames_skipmer_m2n3() {
function test_seqtohashes_dna (line 1802) | fn test_seqtohashes_dna() {
function test_seqtohashes_dna_2 (line 1839) | fn test_seqtohashes_dna_2() {
function test_seqtohashes_is_protein (line 1878) | fn test_seqtohashes_is_protein() {
function test_seqtohashes_translate (line 1921) | fn test_seqtohashes_translate() {
function test_seqtohashes_skipm1n3 (line 1961) | fn test_seqtohashes_skipm1n3() {
function test_seq2hashes_skipm2n3 (line 1999) | fn test_seq2hashes_skipm2n3() {
function test_seqtohashes_skipm2n3_2 (line 2037) | fn test_seqtohashes_skipm2n3_2() {
FILE: src/core/src/sketch/hyperloglog/estimators.rs
type CounterType (line 6) | pub type CounterType = u8;
type MultiplicityInteger (line 9) | pub trait MultiplicityInteger:
constant ZERO (line 21) | const ZERO: Self;
constant ONE (line 23) | const ONE: Self;
method to_f64 (line 26) | fn to_f64(self) -> f64;
function counts (line 46) | pub fn counts<M: MultiplicityInteger>(registers: &[CounterType], q: usiz...
function mle (line 57) | pub fn mle<M: MultiplicityInteger>(counts: &[M], p: usize, q: usize, rel...
function joint_mle (line 162) | pub fn joint_mle(
function joint_mle_dispatch (line 181) | fn joint_mle_dispatch<M: MultiplicityInteger>(
FILE: src/core/src/sketch/hyperloglog/mod.rs
type HyperLogLog (line 33) | pub struct HyperLogLog {
method with_error_rate (line 41) | pub fn with_error_rate(error_rate: f64, ksize: usize) -> Result<HyperL...
method new (line 46) | pub fn new(p: usize, ksize: usize) -> Result<HyperLogLog, Error> {
method merge (line 62) | pub fn merge(&mut self, other: &HyperLogLog) -> Result<(), Error> {
method add_word (line 71) | pub fn add_word(&mut self, word: &[u8]) {
method add_many (line 76) | pub fn add_many(&mut self, hashes: &[HashIntoType]) -> Result<(), Erro...
method cardinality (line 83) | pub fn cardinality(&self) -> usize {
method union (line 109) | pub fn union(&self, other: &HyperLogLog) -> usize {
method similarity (line 116) | pub fn similarity(&self, other: &HyperLogLog) -> f64 {
method containment (line 123) | pub fn containment(&self, other: &HyperLogLog) -> f64 {
method intersection (line 130) | pub fn intersection(&self, other: &HyperLogLog) -> usize {
method save (line 138) | pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
method save_to_writer (line 145) | pub fn save_to_writer<W>(&self, wtr: &mut W) -> Result<(), Error>
method from_reader (line 159) | pub fn from_reader<R>(rdr: R) -> Result<HyperLogLog, Error>
method from_path (line 188) | pub fn from_path<P: AsRef<Path>>(path: P) -> Result<HyperLogLog, Error> {
method size (line 195) | fn size(&self) -> usize {
method to_vec (line 199) | fn to_vec(&self) -> Vec<u64> {
method ksize (line 203) | fn ksize(&self) -> usize {
method seed (line 207) | fn seed(&self) -> u64 {
method hash_function (line 212) | fn hash_function(&self) -> HashFunctions {
method add_hash (line 217) | fn add_hash(&mut self, hash: HashIntoType) {
method check_compatible (line 227) | fn check_compatible(&self, other: &HyperLogLog) -> Result<(), Error> {
method update (line 243) | fn update(&self, other: &mut HyperLogLog) -> Result<(), Error> {
function hll_add (line 267) | fn hll_add() {
function hll_joint_mle (line 297) | fn hll_joint_mle() {
function save_load_hll (line 388) | fn save_load_hll() {
function test_mle_corner_cases (line 416) | fn test_mle_corner_cases() {
FILE: src/core/src/sketch/minhash.rs
function max_hash_for_scaled (line 24) | pub fn max_hash_for_scaled(scaled: ScaledType) -> u64 {
function scaled_for_max_hash (line 32) | pub fn scaled_for_max_hash(max_hash: u64) -> ScaledType {
type KmerMinHash (line 44) | pub struct KmerMinHash {
method deserialize (line 134) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
method new (line 197) | pub fn new(
method num (line 231) | pub fn num(&self) -> u32 {
method is_protein (line 235) | pub fn is_protein(&self) -> bool {
method max_hash (line 239) | pub fn max_hash(&self) -> u64 {
method scaled (line 243) | pub fn scaled(&self) -> ScaledType {
method clear (line 247) | pub fn clear(&mut self) {
method is_empty (line 254) | pub fn is_empty(&self) -> bool {
method set_hash_function (line 258) | pub fn set_hash_function(&mut self, h: HashFunctions) -> Result<(), Er...
method track_abundance (line 273) | pub fn track_abundance(&self) -> bool {
method enable_abundance (line 277) | pub fn enable_abundance(&mut self) -> Result<(), Error> {
method disable_abundance (line 289) | pub fn disable_abundance(&mut self) {
method reset_md5sum (line 293) | fn reset_md5sum(&self) {
method md5sum (line 300) | pub fn md5sum(&self) -> String {
method add_hash (line 319) | pub fn add_hash(&mut self, hash: u64) {
method add_hash_with_abundance (line 323) | pub fn add_hash_with_abundance(&mut self, hash: u64, abundance: u64) {
method set_hash_with_abundance (line 395) | pub fn set_hash_with_abundance(&mut self, hash: u64, abundance: u64) {
method add_word (line 411) | pub fn add_word(&mut self, word: &[u8]) {
method remove_hash (line 416) | pub fn remove_hash(&mut self, hash: u64) {
method remove_from (line 428) | pub fn remove_from(&mut self, other: &KmerMinHash) -> Result<(), Error> {
method remove_many (line 435) | pub fn remove_many<T: IntoIterator<Item = u64>>(&mut self, hashes: T) ...
method merge (line 442) | pub fn merge(&mut self, other: &KmerMinHash) -> Result<(), Error> {
method add_from (line 528) | pub fn add_from(&mut self, other: &KmerMinHash) -> Result<(), Error> {
method add_many (line 535) | pub fn add_many(&mut self, hashes: &[u64]) -> Result<(), Error> {
method add_many_with_abund (line 542) | pub fn add_many_with_abund(&mut self, hashes: &[(u64, u64)]) -> Result...
method count_common (line 549) | pub fn count_common(&self, other: &KmerMinHash, downsample: bool) -> R...
method intersection (line 570) | pub fn intersection(&self, other: &KmerMinHash) -> Result<(Vec<u64>, u...
method intersection_size (line 603) | pub fn intersection_size(&self, other: &KmerMinHash) -> Result<(u64, u...
method jaccard (line 634) | pub fn jaccard(&self, other: &KmerMinHash) -> Result<f64, Error> {
method angular_similarity (line 645) | pub fn angular_similarity(&self, other: &KmerMinHash) -> Result<f64, E...
method similarity (line 692) | pub fn similarity(
method dayhoff (line 714) | pub fn dayhoff(&self) -> bool {
method hp (line 718) | pub fn hp(&self) -> bool {
method skipm1n3 (line 722) | pub fn skipm1n3(&self) -> bool {
method skipm2n3 (line 726) | pub fn skipm2n3(&self) -> bool {
method mins (line 730) | pub fn mins(&self) -> Vec<u64> {
method iter_mins (line 734) | pub fn iter_mins(&self) -> impl Iterator<Item = &u64> {
method abunds (line 738) | pub fn abunds(&self) -> Option<Vec<u64>> {
method downsample_max_hash (line 743) | pub fn downsample_max_hash(self, max_hash: u64) -> Result<KmerMinHash,...
method sum_abunds (line 753) | pub fn sum_abunds(&self) -> u64 {
method to_vec_abunds (line 761) | pub fn to_vec_abunds(&self) -> Vec<(u64, u64)> {
method as_hll (line 777) | pub fn as_hll(&self) -> HyperLogLog {
method n_unique_kmers (line 790) | pub fn n_unique_kmers(&self) -> u64 {
method downsample_scaled (line 795) | pub fn downsample_scaled(self, scaled: ScaledType) -> Result<KmerMinHa...
method inflate (line 818) | pub fn inflate(&mut self, abunds_from: &KmerMinHash) -> Result<(), Err...
method inflated_abundances (line 849) | pub fn inflated_abundances(&self, abunds_from: &KmerMinHash) -> Result...
method from_reader (line 878) | pub fn from_reader<R>(rdr: R) -> Result<KmerMinHash, Error>
method from (line 1699) | fn from(other: KmerMinHashBTree) -> KmerMinHash {
method from (line 1724) | fn from(other: &KmerMinHashBTree) -> KmerMinHash {
method eq (line 69) | fn eq(&self, other: &KmerMinHash) -> bool {
method clone (line 76) | fn clone(&self) -> Self {
method default (line 91) | fn default() -> KmerMinHash {
method serialize (line 106) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
method to_writer (line 187) | fn to_writer<W>(&self, writer: &mut W) -> Result<(), Error>
method size (line 890) | fn size(&self) -> usize {
method to_vec (line 894) | fn to_vec(&self) -> Vec<u64> {
method ksize (line 898) | fn ksize(&self) -> usize {
method seed (line 902) | fn seed(&self) -> u64 {
method hash_function (line 906) | fn hash_function(&self) -> HashFunctions {
method add_hash (line 910) | fn add_hash(&mut self, hash: u64) {
method check_compatible (line 914) | fn check_compatible(&self, other: &KmerMinHash) -> Result<(), Error> {
type Intersection (line 943) | struct Intersection<T, I: Iterator<Item = T>> {
function new (line 949) | pub fn new(left: I, right: I) -> Self {
type Item (line 958) | type Item = T;
method next (line 960) | fn next(&mut self) -> Option<T> {
type KmerMinHashBTree (line 991) | pub struct KmerMinHashBTree {
method deserialize (line 1087) | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
method new (line 1154) | pub fn new(
method num (line 1185) | pub fn num(&self) -> u32 {
method is_protein (line 1189) | pub fn is_protein(&self) -> bool {
method max_hash (line 1193) | pub fn max_hash(&self) -> u64 {
method scaled (line 1197) | pub fn scaled(&self) -> ScaledType {
method clear (line 1201) | pub fn clear(&mut self) {
method is_empty (line 1209) | pub fn is_empty(&self) -> bool {
method set_hash_function (line 1213) | pub fn set_hash_function(&mut self, h: HashFunctions) -> Result<(), Er...
method track_abundance (line 1228) | pub fn track_abundance(&self) -> bool {
method enable_abundance (line 1232) | pub fn enable_abundance(&mut self) -> Result<(), Error> {
method disable_abundance (line 1244) | pub fn disable_abundance(&mut self) {
method reset_md5sum (line 1248) | fn reset_md5sum(&self) {
method md5sum (line 1255) | pub fn md5sum(&self) -> String {
method add_hash_with_abundance (line 1274) | pub fn add_hash_with_abundance(&mut self, hash: u64, abundance: u64) {
method add_word (line 1330) | pub fn add_word(&mut self, word: &[u8]) {
method remove_hash (line 1335) | pub fn remove_hash(&mut self, hash: u64) {
method remove_many (line 1347) | pub fn remove_many<T: IntoIterator<Item = u64>>(&mut self, hashes: T) ...
method merge (line 1354) | pub fn merge(&mut self, other: &KmerMinHashBTree) -> Result<(), Error> {
method add_from (line 1384) | pub fn add_from(&mut self, other: &KmerMinHashBTree) -> Result<(), Err...
method add_many (line 1391) | pub fn add_many(&mut self, hashes: &[u64]) -> Result<(), Error> {
method add_many_with_abund (line 1398) | pub fn add_many_with_abund(&mut self, hashes: &[(u64, u64)]) -> Result...
method count_common (line 1405) | pub fn count_common(&self, other: &KmerMinHashBTree, downsample: bool)...
method intersection (line 1427) | pub fn intersection(&self, other: &KmerMinHashBTree) -> Result<(Vec<u6...
method intersection_size (line 1459) | pub fn intersection_size(&self, other: &KmerMinHashBTree) -> Result<(u...
method jaccard (line 1490) | pub fn jaccard(&self, other: &KmerMinHashBTree) -> Result<f64, Error> {
method angular_similarity (line 1501) | pub fn angular_similarity(&self, other: &KmerMinHashBTree) -> Result<f...
method similarity (line 1532) | pub fn similarity(
method dayhoff (line 1554) | pub fn dayhoff(&self) -> bool {
method hp (line 1558) | pub fn hp(&self) -> bool {
method hash_function (line 1562) | pub fn hash_function(&self) -> HashFunctions {
method mins (line 1566) | pub fn mins(&self) -> Vec<u64> {
method iter_mins (line 1570) | pub fn iter_mins(&self) -> impl Iterator<Item = &u64> {
method abunds (line 1574) | pub fn abunds(&self) -> Option<Vec<u64>> {
method downsample_max_hash (line 1581) | pub fn downsample_max_hash(self, max_hash: u64) -> Result<KmerMinHashB...
method downsample_scaled (line 1592) | pub fn downsample_scaled(self, scaled: ScaledType) -> Result<KmerMinHa...
method to_vec_abunds (line 1615) | pub fn to_vec_abunds(&self) -> Vec<(u64, u64)> {
method sum_abunds (line 1627) | pub fn sum_abunds(&self) -> u64 {
method from_reader (line 1635) | pub fn from_reader<R>(rdr: R) -> Result<KmerMinHashBTree, Error>
method from (line 1750) | fn from(other: KmerMinHash) -> KmerMinHashBTree {
method eq (line 1019) | fn eq(&self, other: &KmerMinHashBTree) -> bool {
method clone (line 1026) | fn clone(&self) -> Self {
method default (line 1042) | fn default() -> KmerMinHashBTree {
method serialize (line 1058) | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
method to_writer (line 1144) | fn to_writer<W>(&self, writer: &mut W) -> Result<(), Error>
method size (line 1647) | fn size(&self) -> usize {
method to_vec (line 1651) | fn to_vec(&self) -> Vec<u64> {
method ksize (line 1655) | fn ksize(&self) -> usize {
method seed (line 1659) | fn seed(&self) -> u64 {
method hash_function (line 1663) | fn hash_function(&self) -> HashFunctions {
method add_hash (line 1667) | fn add_hash(&mut self, hash: u64) {
method check_compatible (line 1671) | fn check_compatible(&self, other: &KmerMinHashBTree) -> Result<(), Error> {
function intersection (line 1774) | fn intersection<'a>(
function intersection_size (line 1818) | fn intersection_size<'a>(
function test_deserialize_valid (line 1869) | fn test_deserialize_valid() {
function test_deserialize_invalid_molecule (line 1896) | fn test_deserialize_invalid_molecule() {
FILE: src/core/src/sketch/mod.rs
type Sketch (line 17) | pub enum Sketch {
FILE: src/core/src/sketch/nodegraph.rs
type Nodegraph (line 15) | pub struct Nodegraph {
method update (line 33) | fn update(&self, other: &mut Nodegraph) -> Result<(), Error> {
method new (line 67) | pub fn new(tablesizes: &[usize], ksize: usize) -> Nodegraph {
method with_tables (line 81) | pub fn with_tables(tablesize: usize, n_tables: usize, ksize: usize) ->...
method count_kmer (line 102) | pub(crate) fn count_kmer(&mut self, kmer: &[u8]) -> bool {
method count (line 107) | pub fn count(&mut self, hash: HashIntoType) -> bool {
method get (line 126) | pub fn get(&self, hash: HashIntoType) -> usize {
method get_kmer (line 136) | pub(crate) fn get_kmer(&self, kmer: &[u8]) -> usize {
method expected_collisions (line 141) | pub fn expected_collisions(&self) -> f64 {
method tablesize (line 150) | pub fn tablesize(&self) -> usize {
method noccupied (line 154) | pub fn noccupied(&self) -> usize {
method matches (line 158) | pub fn matches(&self, mh: &KmerMinHash) -> usize {
method ntables (line 162) | pub fn ntables(&self) -> usize {
method ksize (line 166) | pub fn ksize(&self) -> usize {
method into_bitsets (line 170) | pub fn into_bitsets(self) -> Vec<FixedBitSet> {
method save (line 175) | pub fn save<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
method save_to_writer (line 182) | pub fn save_to_writer<W>(&self, wtr: &mut W) -> Result<(), Error>
method from_reader (line 222) | pub fn from_reader<R>(rdr: R) -> Result<Nodegraph, Error>
method from_path (line 275) | pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Nodegraph, Error> {
method tablesizes (line 280) | pub fn tablesizes(&self) -> Vec<u64> {
method n_occupied_bins (line 284) | pub fn n_occupied_bins(&self) -> usize {
method unique_kmers (line 288) | pub fn unique_kmers(&self) -> usize {
method similarity (line 292) | pub fn similarity(&self, other: &Nodegraph) -> f64 {
method containment (line 308) | pub fn containment(&self, other: &Nodegraph) -> f64 {
method eq (line 25) | fn eq(&self, other: &Nodegraph) -> bool {
method update (line 49) | fn update(&self, other: &mut Nodegraph) -> Result<(), Error> {
method update (line 58) | fn update(&self, other: &mut Nodegraph) -> Result<(), Error> {
function twobit_repr (line 320) | fn twobit_repr(a: u8) -> HashIntoType {
function twobit_comp (line 330) | fn twobit_comp(a: u8) -> HashIntoType {
function uniqify_rc (line 340) | fn uniqify_rc(f: HashIntoType, r: HashIntoType) -> HashIntoType {
function _hash (line 344) | fn _hash(kmer: &[u8]) -> HashIntoType {
function load_compressed (line 416) | fn load_compressed() {
function count_and_get_nodegraph (line 428) | fn count_and_get_nodegraph() {
function containment (line 438) | fn containment() {
function load_save_nodegraph (line 456) | fn load_save_nodegraph() {
function binary_repr_load (line 484) | fn binary_repr_load() {
function binary_repr_save (line 508) | fn binary_repr_save() {
function update_nodegraph (line 532) | fn update_nodegraph() {
function update_nodegraph_many (line 556) | fn update_nodegraph_many() -> Result<(), Box<dyn std::error::Error>> {
function load_nodegraph (line 593) | fn load_nodegraph() {
FILE: src/core/src/storage/mod.rs
type Storage (line 24) | pub trait Storage {
method save (line 26) | fn save(&self, path: &str, content: &[u8]) -> Result<String>;
method load (line 29) | fn load(&self, path: &str) -> Result<Vec<u8>>;
method args (line 32) | fn args(&self) -> StorageArgs;
method load_sig (line 35) | fn load_sig(&self, path: &str) -> Result<SigStore> {
method spec (line 47) | fn spec(&self) -> String;
method save_sig (line 50) | fn save_sig(&self, path: &str, sig: Signature) -> Result<String> {
method save (line 195) | fn save(&self, path: &str, content: &[u8]) -> Result<String> {
method load (line 199) | fn load(&self, path: &str) -> Result<Vec<u8>> {
method args (line 203) | fn args(&self) -> StorageArgs {
method load_sig (line 207) | fn load_sig(&self, path: &str) -> Result<SigStore> {
method spec (line 213) | fn spec(&self) -> String {
method save (line 239) | fn save(&self, path: &str, content: &[u8]) -> Result<String> {
method load (line 243) | fn load(&self, path: &str) -> Result<Vec<u8>> {
method args (line 247) | fn args(&self) -> StorageArgs {
method load_sig (line 251) | fn load_sig(&self, path: &str) -> Result<SigStore> {
method spec (line 255) | fn spec(&self) -> String {
method save (line 281) | fn save(&self, path: &str, content: &[u8]) -> Result<String> {
method load (line 297) | fn load(&self, path: &str) -> Result<Vec<u8>> {
method args (line 306) | fn args(&self) -> StorageArgs {
method load_sig (line 312) | fn load_sig(&self, path: &str) -> Result<SigStore> {
method spec (line 324) | fn spec(&self) -> String {
method save (line 354) | fn save(&self, _path: &str, _content: &[u8]) -> Result<String> {
method load (line 358) | fn load(&self, path: &str) -> Result<Vec<u8>> {
method args (line 381) | fn args(&self) -> StorageArgs {
method load_sig (line 385) | fn load_sig(&self, path: &str) -> Result<SigStore> {
method spec (line 396) | fn spec(&self) -> String {
method save (line 666) | fn save(&self, _path: &str, _content: &[u8]) -> Result<String> {
method load (line 670) | fn load(&self, path: &str) -> Result<Vec<u8>> {
method args (line 682) | fn args(&self) -> StorageArgs {
method load_sig (line 686) | fn load_sig(&self, path: &str) -> Result<SigStore> {
method save_sig (line 690) | fn save_sig(&self, path: &str, sig: Signature) -> Result<String> {
method spec (line 697) | fn spec(&self) -> String {
type StorageError (line 61) | pub enum StorageError {
type InnerStorage (line 86) | pub struct InnerStorage(Arc<RwLock<dyn Storage + Send + Sync + 'static>>);
method new (line 163) | pub fn new(inner: impl Storage + Send + Sync + 'static) -> InnerStorage {
method from_spec (line 167) | pub fn from_spec(spec: String) -> Result<Self> {
type SigStore (line 89) | pub struct SigStore {
method new_with_storage (line 468) | pub fn new_with_storage(sig: Signature, storage: InnerStorage) -> Self {
method name (line 481) | pub fn name(&self) -> String {
method fmt (line 496) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method data (line 506) | fn data(&self) -> Result<&Signature> {
method save (line 526) | pub fn save(&self, path: &str) -> Result<String> {
method from (line 557) | fn from(other: Signature) -> SigStore {
type Error (line 572) | type Error = crate::Error;
method try_into (line 574) | fn try_into(self) -> std::result::Result<KmerMinHash, Self::Error> {
method similarity (line 581) | fn similarity(&self, other: &SigStore) -> f64 {
method containment (line 596) | fn containment(&self, other: &SigStore) -> f64 {
method from (line 620) | fn from(other: DatasetInfo) -> SigStore {
method eq (line 106) | fn eq(&self, other: &Self) -> bool {
type StorageArgs (line 116) | pub enum StorageArgs {
type FSStorage (line 122) | pub struct FSStorage {
method from (line 219) | fn from(other: &StorageArgs) -> FSStorage {
method new (line 261) | pub fn new(location: &str, subdir: &str) -> FSStorage {
method set_base (line 272) | pub fn set_base(&mut self, location: &str) {
type ZipStorage (line 130) | pub struct ZipStorage {
method from_file (line 402) | pub fn from_file<P: AsRef<Path>>(location: P) -> Result<Self> {
method path (line 429) | pub fn path(&self) -> Option<PathBuf> {
method subdir (line 433) | pub fn subdir(&self) -> Option<String> {
method set_subdir (line 437) | pub fn set_subdir(&mut self, path: String) {
method list_sbts (line 441) | pub fn list_sbts(&self) -> Result<Vec<String>> {
method filenames (line 457) | pub fn filenames(&self) -> Result<Vec<String>> {
type MemStorage (line 147) | pub struct MemStorage {
method new (line 658) | pub fn new() -> Self {
type Metadata (line 158) | pub type Metadata<'a> = BTreeMap<&'a OsStr, &'a piz::read::FileMetadata<...
function lookup (line 329) | fn lookup<'a, P: AsRef<Path>>(
function find_subdirs (line 340) | fn find_subdirs<'a>(archive: &'a piz::ZipArchive<'a>) -> Result<Option<S...
method select (line 487) | fn select(mut self, selection: &Selection) -> Result<Self> {
method from (line 543) | fn from(other: SigStore) -> Signature {
type Target (line 549) | type Target = Signature;
method deref (line 551) | fn deref(&self) -> &Signature {
type DatasetInfo (line 614) | pub struct DatasetInfo {
method similarity (line 632) | fn similarity(&self, other: &Signature) -> f64 {
method containment (line 643) | fn containment(&self, other: &Signature) -> f64 {
FILE: src/core/src/storage/rocksdb.rs
constant HASHES (line 9) | pub(crate) const HASHES: &str = "hashes";
constant COLORS (line 10) | pub(crate) const COLORS: &str = "colors";
constant METADATA (line 11) | pub(crate) const METADATA: &str = "metadata";
constant STORAGE (line 14) | pub(crate) const STORAGE: &str = "storage";
constant ALL_CFS (line 16) | pub(crate) const ALL_CFS: [&str; 3] = [HASHES, METADATA, STORAGE];
type DB (line 18) | pub type DB = rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>;
type RocksDBStorage (line 22) | pub struct RocksDBStorage {
method from_path (line 27) | pub fn from_path(path: &str) -> Self {
method from_db (line 41) | pub fn from_db(db: Arc<DB>) -> Self {
method save (line 47) | fn save(&self, path: &str, content: &[u8]) -> Result<String> {
method load (line 54) | fn load(&self, path: &str) -> Result<Vec<u8>> {
method args (line 60) | fn args(&self) -> StorageArgs {
method spec (line 64) | fn spec(&self) -> String {
function cf_descriptors (line 69) | pub(crate) fn cf_descriptors() -> Vec<ColumnFamilyDescriptor> {
function db_options (line 110) | pub(crate) fn db_options() -> rocksdb::Options {
FILE: src/core/src/wasm.rs
type KmerMinHash (line 13) | pub struct KmerMinHash(_KmerMinHash);
method new_with_scaled (line 24) | pub fn new_with_scaled(
method add_sequence_js (line 57) | pub fn add_sequence_js(&mut self, buf: &str) -> Result<(), JsErrors> {
method to_json (line 63) | pub fn to_json(&mut self) -> Result<String, JsErrors> {
type Signature (line 16) | pub struct Signature(_Signature);
method new_from_params (line 121) | pub fn new_from_params(params: &ComputeParameters) -> Signature {
method add_sequence_js (line 128) | pub fn add_sequence_js(&mut self, buf: &str) -> Result<(), JsErrors> {
method add_from_file (line 135) | pub fn add_from_file(
method to_json (line 158) | pub fn to_json(&mut self) -> Result<String, JsErrors> {
method size (line 164) | pub fn size(&self) -> usize {
type ComputeParameters (line 19) | pub struct ComputeParameters(_ComputeParameters);
method new_with_params (line 73) | pub fn new_with_params() -> ComputeParameters {
method set_ksizes (line 79) | pub fn set_ksizes(&mut self, ksizes: Vec<u32>) {
method set_scaled (line 84) | pub fn set_scaled(&mut self, scaled: ScaledType) {
method set_num (line 89) | pub fn set_num(&mut self, num: u32) {
method set_protein (line 94) | pub fn set_protein(&mut self, is_protein: bool) {
method set_dayhoff (line 99) | pub fn set_dayhoff(&mut self, dayhoff: bool) {
method set_hp (line 104) | pub fn set_hp(&mut self, hp: bool) {
method set_track_abundance (line 109) | pub fn set_track_abundance(&mut self, track: bool) {
method set_seed (line 113) | pub fn set_seed(&mut self, seed: u32) {
type JsErrors (line 170) | pub enum JsErrors {
method into (line 185) | fn into(self) -> JsValue {
function wasm_test (line 197) | fn wasm_test() {
type SyncFile (line 219) | pub struct SyncFile {
method new (line 230) | pub fn new(file: web_sys::File, cb: Option<js_sys::Function>) -> Self {
method size (line 235) | pub fn size(&self) -> u64 {
method set_pos (line 244) | fn set_pos(&mut self, pos: u64) {
method progress (line 255) | pub fn progress(&self) -> f64 {
method read (line 261) | fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
FILE: src/core/tests/minhash.rs
constant EPSILON (line 19) | const EPSILON: f64 = 0.01;
function throws_error (line 22) | fn throws_error() {
function merge (line 32) | fn merge() {
function invalid_dna (line 59) | fn invalid_dna() {
function similarity (line 71) | fn similarity() -> Result<(), Box<dyn std::error::Error>> {
function similarity_2 (line 86) | fn similarity_2() -> Result<(), Box<dyn std::error::Error>> {
function similarity_3 (line 106) | fn similarity_3() -> Result<(), Box<dyn std::error::Error>> {
function angular_similarity_requires_abundance (line 130) | fn angular_similarity_requires_abundance() -> Result<(), Box<dyn std::er...
function angular_similarity_btree_requires_abundance (line 143) | fn angular_similarity_btree_requires_abundance() -> Result<(), Box<dyn s...
function dayhoff (line 156) | fn dayhoff() {
function hp (line 168) | fn hp() {
function max_for_scaled (line 180) | fn max_for_scaled() {
function load_save_minhash_sketches (line 383) | fn load_save_minhash_sketches() {
function load_save_minhash_sketches_abund (line 484) | fn load_save_minhash_sketches_abund() {
function merge_empty_scaled (line 585) | fn merge_empty_scaled() {
function check_errors (line 611) | fn check_errors() {
function test_inflate (line 801) | fn test_inflate() {
function test_inflated_abundances (line 823) | fn test_inflated_abundances() {
function test_inflate_noabund (line 845) | fn test_inflate_noabund() {
function test_inflated_abunds_noabund (line 860) | fn test_inflated_abunds_noabund() {
function test_sum_abunds (line 874) | fn test_sum_abunds() {
function test_sum_abunds_noabund (line 883) | fn test_sum_abunds_noabund() {
function test_n_unique_kmers (line 892) | fn test_n_unique_kmers() {
function test_scaled_downsampling_kmerminhash (line 901) | fn test_scaled_downsampling_kmerminhash() {
function test_scaled_downsampling_kmerminhashbtree (line 918) | fn test_scaled_downsampling_kmerminhashbtree() {
FILE: src/core/tests/node.rs
function pass (line 6) | fn pass() {
FILE: src/core/tests/storage.rs
function zipstorage_load_file (line 9) | fn zipstorage_load_file() -> Result<(), Box<dyn std::error::Error>> {
function zipstorage_load_manifest (line 24) | fn zipstorage_load_manifest() -> Result<(), Box<dyn std::error::Error>> {
function zipstorage_list_sbts (line 36) | fn zipstorage_list_sbts() -> Result<(), Box<dyn std::error::Error>> {
function zipstorage_parallel_access (line 51) | fn zipstorage_parallel_access() -> Result<(), Box<dyn std::error::Error>> {
function innerstorage_save_sig (line 85) | fn innerstorage_save_sig() -> Result<(), Box<dyn std::error::Error>> {
function innerstorage_load (line 108) | fn innerstorage_load() -> Result<(), Box<dyn std::error::Error>> {
function innerstorage_args (line 132) | fn innerstorage_args() -> Result<(), Box<dyn std::error::Error>> {
function innerstorage_from_args (line 150) | fn innerstorage_from_args() -> Result<(), Box<dyn std::error::Error>> {
FILE: src/core/tests/test.rs
function test_murmur (line 2) | fn test_murmur() {
FILE: src/sourmash/__init__.py
function load_signatures (line 61) | def load_signatures(*args, **kwargs):
function load_one_signature (line 82) | def load_one_signature(*args, **kwargs):
function save_signatures (line 98) | def save_signatures(*args, **kwargs):
function load_sbt_index (line 112) | def load_sbt_index(*args, **kwargs):
function search_sbt_index (line 127) | def search_sbt_index(*args, **kwargs):
FILE: src/sourmash/__main__.py
function main (line 8) | def main(arglist=None):
FILE: src/sourmash/cli/__init__.py
class SourmashParser (line 44) | class SourmashParser(ArgumentParser):
method __init__ (line 47) | def __init__(self, citation=True, **kwargs):
method print_citation (line 52) | def print_citation(cls):
method _subparser_from_name (line 61) | def _subparser_from_name(self, name):
method print_help (line 72) | def print_help(self):
method parse_args (line 76) | def parse_args(self, args=None, namespace=None):
function get_parser (line 97) | def get_parser():
function parse_args (line 165) | def parse_args(arglist=None):
FILE: src/sourmash/cli/categorize.py
function subparser (line 6) | def subparser(subparsers):
function main (line 36) | def main(args):
FILE: src/sourmash/cli/compare.py
function subparser (line 39) | def subparser(subparsers):
function main (line 128) | def main(args):
FILE: src/sourmash/cli/compute.py
function ksize_parser (line 36) | def ksize_parser(ksizes):
function subparser (line 47) | def subparser(subparsers):
function main (line 143) | def main(args):
FILE: src/sourmash/cli/gather.py
function subparser (line 74) | def subparser(subparsers):
function main (line 200) | def main(args):
FILE: src/sourmash/cli/import_csv.py
function subparser (line 6) | def subparser(subparsers):
function main (line 16) | def main(args):
FILE: src/sourmash/cli/index.py
function subparser (line 30) | def subparser(subparsers):
function main (line 95) | def main(args):
FILE: src/sourmash/cli/info.py
function subparser (line 10) | def subparser(subparsers):
function info (line 20) | def info(verbose=False):
function main (line 36) | def main(args):
FILE: src/sourmash/cli/lca/__init__.py
function subparser (line 18) | def subparser(subparsers):
FILE: src/sourmash/cli/lca/classify.py
function subparser (line 4) | def subparser(subparsers):
function main (line 47) | def main(args):
FILE: src/sourmash/cli/lca/compare_csv.py
function subparser (line 4) | def subparser(subparsers):
function main (line 38) | def main(args):
FILE: src/sourmash/cli/lca/index.py
function subparser (line 6) | def subparser(subparsers):
function main (line 79) | def main(args):
FILE: src/sourmash/cli/lca/rankinfo.py
function subparser (line 4) | def subparser(subparsers):
function main (line 22) | def main(args):
FILE: src/sourmash/cli/lca/summarize.py
function subparser (line 4) | def subparser(subparsers):
function main (line 50) | def main(args):
FILE: src/sourmash/cli/migrate.py
function subparser (line 4) | def subparser(subparsers):
function main (line 9) | def main(args):
FILE: src/sourmash/cli/multigather.py
function subparser (line 42) | def subparser(subparsers):
function main (line 119) | def main(args):
FILE: src/sourmash/cli/plot.py
function subparser (line 4) | def subparser(subparsers):
function main (line 82) | def main(args):
FILE: src/sourmash/cli/prefetch.py
function subparser (line 12) | def subparser(subparsers):
function main (line 83) | def main(args):
FILE: src/sourmash/cli/sbt_combine.py
function subparser (line 4) | def subparser(subparsers):
function main (line 11) | def main(args):
FILE: src/sourmash/cli/scripts/__init__.py
function __getattr__ (line 25) | def __getattr__(name):
function subparser (line 31) | def subparser(subparsers):
FILE: src/sourmash/cli/search.py
function subparser (line 53) | def subparser(subparsers):
function main (line 143) | def main(args):
FILE: src/sourmash/cli/sig/__init__.py
function subparser (line 35) | def subparser(subparsers):
FILE: src/sourmash/cli/sig/cat.py
function subparser (line 26) | def subparser(subparsers):
function main (line 62) | def main(args):
FILE: src/sourmash/cli/sig/check.py
function subparser (line 27) | def subparser(subparsers):
function main (line 104) | def main(args):
FILE: src/sourmash/cli/sig/collect.py
function subparser (line 25) | def subparser(subparsers):
function main (line 88) | def main(args):
FILE: src/sourmash/cli/sig/describe.py
function subparser (line 33) | def subparser(subparsers):
function main (line 58) | def main(args):
FILE: src/sourmash/cli/sig/downsample.py
function subparser (line 37) | def subparser(subparsers):
function main (line 66) | def main(args):
FILE: src/sourmash/cli/sig/export.py
function subparser (line 19) | def subparser(subparsers):
function main (line 38) | def main(args):
FILE: src/sourmash/cli/sig/extract.py
function subparser (line 48) | def subparser(subparsers):
function main (line 84) | def main(args):
FILE: src/sourmash/cli/sig/fileinfo.py
function subparser (line 17) | def subparser(subparsers):
function main (line 37) | def main(args):
FILE: src/sourmash/cli/sig/filter.py
function subparser (line 27) | def subparser(subparsers):
function main (line 70) | def main(args):
FILE: src/sourmash/cli/sig/flatten.py
function subparser (line 24) | def subparser(subparsers):
function main (line 59) | def main(args):
FILE: src/sourmash/cli/sig/grep.py
function subparser (line 32) | def subparser(subparsers):
function main (line 105) | def main(args):
FILE: src/sourmash/cli/sig/inflate.py
function subparser (line 6) | def subparser(subparsers):
function main (line 28) | def main(args):
FILE: src/sourmash/cli/sig/ingest.py
function subparser (line 16) | def subparser(subparsers):
function main (line 37) | def main(args):
FILE: src/sourmash/cli/sig/intersect.py
function subparser (line 28) | def subparser(subparsers):
function main (line 60) | def main(args):
FILE: src/sourmash/cli/sig/kmers.py
function subparser (line 54) | def subparser(subparsers):
function main (line 96) | def main(args):
FILE: src/sourmash/cli/sig/manifest.py
function subparser (line 20) | def subparser(subparsers):
function main (line 64) | def main(args):
FILE: src/sourmash/cli/sig/merge.py
function subparser (line 30) | def subparser(subparsers):
function main (line 59) | def main(args):
FILE: src/sourmash/cli/sig/overlap.py
function subparser (line 30) | def subparser(subparsers):
function main (line 41) | def main(args):
FILE: src/sourmash/cli/sig/rename.py
function subparser (line 28) | def subparser(subparsers):
function main (line 58) | def main(args):
FILE: src/sourmash/cli/sig/split.py
function subparser (line 42) | def subparser(subparsers):
function main (line 72) | def main(args):
FILE: src/sourmash/cli/sig/subtract.py
function subparser (line 28) | def subparser(subparsers):
function main (line 58) | def main(args):
FILE: src/sourmash/cli/sketch/__init__.py
function subparser (line 20) | def subparser(subparsers):
FILE: src/sourmash/cli/sketch/dna.py
function subparser (line 32) | def subparser(subparsers):
function main (line 103) | def main(args):
FILE: src/sourmash/cli/sketch/fromfile.py
function subparser (line 30) | def subparser(subparsers):
function main (line 90) | def main(args):
FILE: src/sourmash/cli/sketch/protein.py
function subparser (line 33) | def subparser(subparsers):
function main (line 107) | def main(args):
FILE: src/sourmash/cli/sketch/translate.py
function subparser (line 34) | def subparser(subparsers):
function main (line 113) | def main(args):
FILE: src/sourmash/cli/storage/__init__.py
function subparser (line 14) | def subparser(subparsers):
FILE: src/sourmash/cli/storage/convert.py
function subparser (line 4) | def subparser(subparsers):
function main (line 10) | def main(args):
FILE: src/sourmash/cli/tax/__init__.py
function subparser (line 20) | def subparser(subparsers):
FILE: src/sourmash/cli/tax/annotate.py
function subparser (line 21) | def subparser(subparsers):
function main (line 90) | def main(args):
FILE: src/sourmash/cli/tax/genome.py
function subparser (line 46) | def subparser(subparsers):
function main (line 140) | def main(args):
FILE: src/sourmash/cli/tax/grep.py
function subparser (line 23) | def subparser(subparsers):
function main (line 88) | def main(args):
FILE: src/sourmash/cli/tax/metagenome.py
function subparser (line 34) | def subparser(subparsers):
function main (line 151) | def main(args):
FILE: src/sourmash/cli/tax/prepare.py
function subparser (line 19) | def subparser(subparsers):
function main (line 70) | def main(args):
FILE: src/sourmash/cli/tax/summarize.py
function subparser (line 20) | def subparser(subparsers):
function main (line 69) | def main(args):
FILE: src/sourmash/cli/utils.py
function add_moltype_args (line 8) | def add_moltype_args(parser):
function add_construct_moltype_args (line 106) | def add_construct_moltype_args(parser):
function add_ksize_arg (line 111) | def add_ksize_arg(parser, *, default=None):
function add_v5_args (line 128) | def add_v5_args(parser):
function range_limited_float_type (line 147) | def range_limited_float_type(arg):
function add_tax_threshold_arg (line 162) | def add_tax_threshold_arg(parser, containment_default=0.1, ani_default=N...
function add_picklist_args (line 178) | def add_picklist_args(parser):
function add_pattern_args (line 192) | def add_pattern_args(parser):
function opfilter (line 205) | def opfilter(path):
function command_list (line 209) | def command_list(dirpath):
function add_scaled_arg (line 219) | def add_scaled_arg(parser, default=None):
function add_num_arg (line 229) | def add_num_arg(parser, default=0):
function check_rank (line 241) | def check_rank(args):
function add_rank_arg (line 267) | def add_rank_arg(parser):
function check_tax_outputs (line 279) | def check_tax_outputs(
FILE: src/sourmash/cli/watch.py
function subparser (line 6) | def subparser(subparsers):
function main (line 36) | def main(args):
FILE: src/sourmash/command_compute.py
function compute (line 28) | def compute(args):
class _signatures_for_compute_factory (line 140) | class _signatures_for_compute_factory:
method __init__ (line 143) | def __init__(self, args):
method __call__ (line 146) | def __call__(self):
function _compute_individual (line 163) | def _compute_individual(args, signatures_factory):
function _compute_merged (line 292) | def _compute_merged(args, signatures_factory):
function add_seq (line 328) | def add_seq(sigs, seq, input_is_protein, check_sequence):
function set_sig_name (line 336) | def set_sig_name(sigs, filename, name=None):
function save_siglist (line 346) | def save_siglist(siglist, sigfile_name):
function save_sigs_to_location (line 357) | def save_sigs_to_location(siglist, save_sig):
class ComputeParameters (line 365) | class ComputeParameters(RustObject):
method __init__ (line 368) | def __init__(
method from_manifest_row (line 394) | def from_manifest_row(cls, row):
method to_param_str (line 427) | def to_param_str(self):
method __repr__ (line 467) | def __repr__(self):
method __eq__ (line 470) | def __eq__(self, other):
method from_args (line 484) | def from_args(args):
method seed (line 497) | def seed(self):
method seed (line 501) | def seed(self, v):
method ksizes (line 505) | def ksizes(self):
method ksizes (line 514) | def ksizes(self, v):
method protein (line 518) | def protein(self):
method protein (line 522) | def protein(self, v):
method dayhoff (line 526) | def dayhoff(self):
method dayhoff (line 530) | def dayhoff(self, v):
method hp (line 534) | def hp(self):
method hp (line 538) | def hp(self, v):
method dna (line 542) | def dna(self):
method dna (line 546) | def dna(self, v):
method moltype (line 550) | def moltype(self):
method num_hashes (line 565) | def num_hashes(self):
method num_hashes (line 569) | def num_hashes(self, v):
method track_abundance (line 573) | def track_abundance(self):
method track_abundance (line 577) | def track_abundance(self, v):
method scaled (line 581) | def scaled(self):
method scaled (line 585) | def scaled(self, v):
FILE: src/sourmash/command_sketch.py
function _parse_params_str (line 35) | def _parse_params_str(params_str):
class _signatures_for_sketch_factory (line 94) | class _signatures_for_sketch_factory:
method __init__ (line 97) | def __init__(self, params_str_list, default_moltype):
method get_compute_params (line 147) | def get_compute_params(self, *, split_ksizes=False):
method __call__ (line 195) | def __call__(self, *, split_ksizes=False):
function _add_from_file_to_filenames (line 205) | def _add_from_file_to_filenames(args):
function _execute_sketch (line 214) | def _execute_sketch(args, signatures_factory):
function dna (line 250) | def dna(args):
function protein (line 268) | def protein(args):
function translate (line 297) | def translate(args):
function _compute_sigs (line 325) | def _compute_sigs(to_build, output, *, check_sequence=False):
function _output_csv_info (line 381) | def _output_csv_info(filename, sigs_to_build):
function fromfile (line 419) | def fromfile(args):
class _signatures_for_compute_factory (line 655) | class _signatures_for_compute_factory:
method __init__ (line 658) | def __init__(self, args):
method __call__ (line 661) | def __call__(self):
function _compute_individual (line 680) | def _compute_individual(args, signatures_factory):
function _compute_merged (line 809) | def _compute_merged(args, signatures_factory):
function add_seq (line 845) | def add_seq(sigs, seq, input_is_protein, check_sequence):
function set_sig_name (line 853) | def set_sig_name(sigs, filename, name=None):
function save_siglist (line 863) | def save_siglist(siglist, sigfile_name):
function save_sigs_to_location (line 874) | def save_sigs_to_location(siglist, save_sig):
class ComputeParameters (line 882) | class ComputeParameters(RustObject):
method __init__ (line 885) | def __init__(
method from_manifest_row (line 915) | def from_manifest_row(cls, row):
method to_param_str (line 956) | def to_param_str(self):
method __repr__ (line 1000) | def __repr__(self):
method __eq__ (line 1003) | def __eq__(self, other):
method from_args (line 1019) | def from_args(args):
method seed (line 1032) | def seed(self):
method seed (line 1036) | def seed(self, v):
method ksizes (line 1040) | def ksizes(self):
method ksizes (line 1049) | def ksizes(self, v):
method protein (line 1053) | def protein(self):
method protein (line 1057) | def protein(self, v):
method dayhoff (line 1061) | def dayhoff(self):
method dayhoff (line 1065) | def dayhoff(self, v):
method hp (line 1069) | def hp(self):
method hp (line 1073) | def hp(self, v):
method dna (line 1077) | def dna(self):
method dna (line 1081) | def dna(self, v):
method skipm1n3 (line 1085) | def skipm1n3(self):
method skipm1n3 (line 1089) | def skipm1n3(self, v):
method skipm2n3 (line 1093) | def skipm2n3(self):
method skipm2n3 (line 1097) | def skipm2n3(self, v):
method moltype (line 1101) | def moltype(self):
method num_hashes (line 1120) | def num_hashes(self):
method num_hashes (line 1124) | def num_hashes(self, v):
method track_abundance (line 1128) | def track_abundance(self):
method track_abundance (line 1132) | def track_abundance(self, v):
method scaled (line 1136) | def scaled(self):
method scaled (line 1140) | def scaled(self, v):
FILE: src/sourmash/commands.py
class EnumIndexType (line 34) | class EnumIndexType(enum.StrEnum): # used in 'index'
function _get_screen_width (line 40) | def _get_screen_width():
function compare (line 47) | def compare(args):
function plot (line 315) | def plot(args):
function import_csv (line 464) | def import_csv(args):
function sbt_combine (line 495) | def sbt_combine(args):
function index (line 510) | def index(args):
function search (line 659) | def search(args):
function categorize (line 811) | def categorize(args):
function gather (line 889) | def gather(args):
function multigather (line 1180) | def multigather(args):
function watch (line 1456) | def watch(args):
function migrate (line 1553) | def migrate(args):
function prefetch (line 1561) | def prefetch(args):
FILE: src/sourmash/compare.py
function compare_serial (line 14) | def compare_serial(siglist, ignore_abundance, *, downsample=False, retur...
function compare_serial_containment (line 67) | def compare_serial_containment(siglist, *, downsample=False, return_ani=...
function compare_serial_max_containment (line 109) | def compare_serial_max_containment(siglist, *, downsample=False, return_...
function compare_serial_avg_containment (line 150) | def compare_serial_avg_containment(siglist, *, downsample=False, return_...
function similarity_args_unpack (line 190) | def similarity_args_unpack(args, ignore_abundance, *, downsample, return...
function get_similarities_at_index (line 205) | def get_similarities_at_index(
function compare_parallel (line 241) | def compare_parallel(
function compare_all_pairs (line 328) | def compare_all_pairs(
FILE: src/sourmash/distance_utils.py
function check_distance (line 17) | def check_distance(dist):
function check_prob_threshold (line 24) | def check_prob_threshold(val, threshold=1e-3):
function check_jaccard_error (line 36) | def check_jaccard_error(val, threshold=1e-4):
class ANIResult (line 44) | class ANIResult:
method check_dist_and_p_threshold (line 53) | def check_dist_and_p_threshold(self):
method __post_init__ (line 60) | def __post_init__(self):
method ani (line 64) | def ani(self):
class jaccardANIResult (line 71) | class jaccardANIResult(ANIResult):
method __post_init__ (line 77) | def __post_init__(self):
method ani (line 89) | def ani(self):
class ciANIResult (line 97) | class ciANIResult(ANIResult):
method __post_init__ (line 107) | def __post_init__(self):
method ani_low (line 116) | def ani_low(self):
method ani_high (line 122) | def ani_high(self):
function r1_to_q (line 128) | def r1_to_q(k, r1):
function var_n_mutated (line 134) | def var_n_mutated(L, k, r1, *, q=None):
function exp_n_mutated (line 155) | def exp_n_mutated(L, k, r1):
function exp_n_mutated_squared (line 160) | def exp_n_mutated_squared(L, k, p):
function probit (line 164) | def probit(p):
function handle_seqlen_nkmers (line 168) | def handle_seqlen_nkmers(ksize, *, sequence_len_bp=None, n_unique_kmers=...
function set_size_chernoff (line 181) | def set_size_chernoff(set_size, scaled, *, relative_error=0.05):
function set_size_exact_prob (line 196) | def set_size_exact_prob(set_size, scaled, *, relative_error=0.05):
function get_expected_log_probability (line 221) | def get_expected_log_probability(n_unique_kmers, ksize, mutation_rate, s...
function get_exp_probability_nothing_common (line 233) | def get_exp_probability_nothing_common(
function containment_to_distance (line 258) | def containment_to_distance(
function jaccard_to_distance (line 349) | def jaccard_to_distance(
FILE: src/sourmash/exceptions.py
class SourmashError (line 8) | class SourmashError(Exception):
method __init__ (line 11) | def __init__(self, msg):
method __str__ (line 16) | def __str__(self):
class IndexNotSupported (line 23) | class IndexNotSupported(SourmashError):
method __init__ (line 24) | def __init__(self):
class IndexNotLoaded (line 30) | class IndexNotLoaded(SourmashError):
method __init__ (line 31) | def __init__(self, msg):
function _make_error (line 35) | def _make_error(error_name, base=SourmashError, code=None):
function _get_error_base (line 47) | def _get_error_base(error_name):
function _make_exceptions (line 58) | def _make_exceptions():
FILE: src/sourmash/fig.py
function load_matrix_and_labels (line 16) | def load_matrix_and_labels(basefile):
function plot_composite_matrix (line 26) | def plot_composite_matrix(
FILE: src/sourmash/hll.py
class HLL (line 12) | class HLL(RustObject):
method __init__ (line 15) | def __init__(self, error_rate, ksize):
method __len__ (line 18) | def __len__(self):
method cardinality (line 21) | def cardinality(self):
method ksize (line 25) | def ksize(self):
method add_sequence (line 28) | def add_sequence(self, sequence, force=False):
method add_kmer (line 32) | def add_kmer(self, kmer):
method add (line 38) | def add(self, h):
method update (line 43) | def update(self, other):
method similarity (line 53) | def similarity(self, other):
method containment (line 61) | def containment(self, other):
method intersection (line 69) | def intersection(self, other):
method load (line 78) | def load(filename):
method from_buffer (line 83) | def from_buffer(buf):
method save (line 87) | def save(self, filename):
method to_bytes (line 90) | def to_bytes(self, compression=1):
method count (line 100) | def count(self, h):
method get (line 103) | def get(self, h):
method matches (line 106) | def matches(self, mh):
FILE: src/sourmash/index/__init__.py
class Index (line 61) | class Index(ABC):
method __len__ (line 71) | def __len__(self):
method location (line 75) | def location(self):
method signatures (line 80) | def signatures(self):
method signatures_with_location (line 83) | def signatures_with_location(self):
method _signatures_with_internal (line 88) | def _signatures_with_internal(self):
method insert (line 103) | def insert(self, signature):
method save (line 107) | def save(self, path, storage=None, sparseness=0.0, structure_only=False):
method load (line 112) | def load(cls, location, leaf_loader=None, storage=None, print_version_...
method find (line 115) | def find(self, search_fn, query, **kwargs):
method search_abund (line 172) | def search_abund(self, query, *, threshold=None, **kwargs):
method search (line 202) | def search(
method prefetch (line 241) | def prefetch(self, query, threshold_bp, **kwargs):
method best_containment (line 258) | def best_containment(self, query, threshold_bp=None, **kwargs):
method peek (line 272) | def peek(self, query_mh, *, threshold_bp=0):
method consume (line 298) | def consume(self, intersect_mh):
method counter_gather (line 302) | def counter_gather(self, query, threshold_bp, **kwargs):
method select (line 323) | def select(
function select_signature (line 349) | def select_signature(
class LinearIndex (line 397) | class LinearIndex(Index):
method __init__ (line 405) | def __init__(self, _signatures=None, filename=None):
method location (line 412) | def location(self):
method signatures (line 415) | def signatures(self):
method __bool__ (line 418) | def __bool__(self):
method __len__ (line 421) | def __len__(self):
method insert (line 424) | def insert(self, node):
method save (line 427) | def save(self, path):
method load (line 432) | def load(cls, location, filename=None):
method select (line 441) | def select(self, **kwargs):
class LazyLinearIndex (line 456) | class LazyLinearIndex(Index):
method __init__ (line 477) | def __init__(self, db, selection_dict={}):
method signatures (line 481) | def signatures(self):
method signatures_with_location (line 486) | def signatures_with_location(self):
method __bool__ (line 491) | def __bool__(self):
method __len__ (line 498) | def __len__(self):
method insert (line 502) | def insert(self, node):
method save (line 505) | def save(self, path):
method load (line 509) | def load(cls, path):
method select (line 512) | def select(self, **kwargs):
class ZipFileLinearIndex (line 529) | class ZipFileLinearIndex(Index):
method __init__ (line 540) | def __init__(
method _load_manifest (line 569) | def _load_manifest(self):
method __bool__ (line 585) | def __bool__(self):
method __len__ (line 594) | def __len__(self):
method location (line 609) | def location(self):
method insert (line 612) | def insert(self, signature):
method save (line 615) | def save(self, path):
method load (line 619) | def load(cls, location, traverse_yield_all=False, use_manifest=True):
method _signatures_with_internal (line 632) | def _signatures_with_internal(self):
method signatures (line 650) | def signatures(self):
method select (line 694) | def select(self, **kwargs):
class CounterGather (line 735) | class CounterGather:
method __init__ (line 757) | def __init__(self, query):
method add (line 777) | def add(self, ss, *, location=None, require_overlap=True):
method downsample (line 796) | def downsample(self, scaled):
method __len__ (line 802) | def __len__(self):
method signatures (line 805) | def signatures(self):
method union_found (line 810) | def union_found(self):
method peek (line 828) | def peek(self, cur_query_mh, *, threshold_bp=0):
method consume (line 885) | def consume(self, intersect_mh):
class MultiIndex (line 915) | class MultiIndex(Index):
method __init__ (line 940) | def __init__(self, manifest, parent, *, prepend_location=False):
method location (line 952) | def location(self):
method signatures (line 955) | def signatures(self):
method signatures_with_location (line 959) | def signatures_with_location(self):
method _signatures_with_internal (line 968) | def _signatures_with_internal(self):
method __len__ (line 977) | def __len__(self):
method insert (line 983) | def insert(self, *args):
method load (line 987) | def load(cls, index_list, source_list, parent, *, prepend_location=Fal...
method load_from_directory (line 1019) | def load_from_directory(cls, pathname, *, force=False):
method load_from_path (line 1057) | def load_from_path(cls, pathname, force=False):
method load_from_pathlist (line 1085) | def load_from_pathlist(cls, filename):
method save (line 1107) | def save(self, *args):
method select (line 1110) | def select(self, **kwargs):
class StandaloneManifestIndex (line 1119) | class StandaloneManifestIndex(Index):
method __init__ (line 1150) | def __init__(self, manifest, location, *, prefix=None):
method load (line 1159) | def load(cls, location, *, prefix=None):
method location (line 1177) | def location(self):
method signatures_with_location (line 1181) | def signatures_with_location(self):
method signatures (line 1185) | def signatures(self):
method _signatures_with_internal (line 1190) | def _signatures_with_internal(self):
method __len__ (line 1211) | def __len__(self):
method __bool__ (line 1215) | def __bool__(self):
method save (line 1219) | def save(self, *args):
method insert (line 1222) | def insert(self, *args):
method select (line 1225) | def select(self, **kwargs):
function _check_select_parameters (line 1232) | def _check_select_parameters(**kw):
FILE: src/sourmash/index/revindex.py
class RevIndex (line 18) | class RevIndex(RustObject, Index):
method __init__ (line 30) | def __init__(self):
method _ffi_idx_picklist (line 35) | def _ffi_idx_picklist(self):
method manifest (line 41) | def manifest(self):
method _generate_idx_picklist_from_manifest (line 46) | def _generate_idx_picklist_from_manifest(self, mf):
method signatures (line 51) | def signatures(self, *, use_picklist=True):
method signatures_with_location (line 68) | def signatures_with_location(self):
method _signatures_with_internal (line 72) | def _signatures_with_internal(self):
method __len__ (line 78) | def __len__(self):
method scaled (line 83) | def scaled(self):
method save (line 87) | def save(self, path):
method load (line 91) | def load(cls, location):
method search (line 94) | def search(
method best_containment (line 159) | def best_containment(self, query_ss, *, threshold_bp=0, **kwargs):
method peek (line 186) | def peek(self, query_mh, *, threshold_bp=0):
method consume (line 215) | def consume(self, intersect_mh):
method counter_gather (line 221) | def counter_gather(self, query_ss, threshold_bp=0, **kwargs):
method prefetch (line 238) | def prefetch(self, query_ss, threshold_bp=0, **kwargs):
method select (line 264) | def select(
class SearchResult (line 325) | class SearchResult(RustObject):
method __repr__ (line 332) | def __repr__(self):
method __iter__ (line 335) | def __iter__(self):
method __getitem__ (line 338) | def __getitem__(self, i):
method score (line 342) | def score(self):
method signature (line 346) | def signature(self):
method location (line 351) | def location(self):
class MemRevIndex (line 358) | class MemRevIndex(RevIndex):
method __init__ (line 363) | def __init__(self, *, template=None):
method _check_not_init (line 377) | def _check_not_init(self, *, do_raise=True):
method _init_inner (line 385) | def _init_inner(self):
method insert (line 425) | def insert(self, sig):
method search (line 433) | def search(self, *args, **kwargs):
class DiskRevIndex (line 449) | class DiskRevIndex(RevIndex):
method __init__ (line 457) | def __init__(self, path):
method _init_inner (line 473) | def _init_inner(self):
method location (line 477) | def location(self):
method insert (line 480) | def insert(self, *args, **kwargs):
method create_from_sigs (line 484) | def create_from_sigs(self, siglist, path):
class RevIndex_CounterGather (line 503) | class RevIndex_CounterGather:
method __init__ (line 512) | def __init__(self, query, db, threshold_bp, *, allow_insert=False):
method __len__ (line 526) | def __len__(self):
method scaled (line 530) | def scaled(self):
method add (line 533) | def add(self, match_ss, *, location=None, require_overlap=True):
method peek (line 553) | def peek(self, query_mh, *, threshold_bp=0):
method consume (line 574) | def consume(self, intersect_mh):
method union_found (line 587) | def union_found(self):
method signatures (line 591) | def signatures(self):
class RevIndex_CounterGather_Colors (line 598) | class RevIndex_CounterGather_Colors(RustObject):
method __init__ (line 605) | def __init__(self, objptr, query_ss, db):
method scaled (line 628) | def scaled(self):
method add (line 631) | def add(self, match_ss, *, location=None, require_overlap=True):
method peek (line 634) | def peek(self, query_mh, *, threshold_bp=0):
method consume (line 659) | def consume(self, intersect_mh):
method union_found (line 664) | def union_found(self):
method __len__ (line 668) | def __len__(self):
method signatures (line 672) | def signatures(self):
class RevIndex_DatasetPicklist (line 685) | class RevIndex_DatasetPicklist(RustObject):
method __init__ (line 693) | def __init__(self, idxs):
method from_manifest (line 703) | def from_manifest(cls, mf):
FILE: src/sourmash/index/sqlite_index.py
function convert_hash_to (line 102) | def convert_hash_to(x):
function convert_hash_from (line 106) | def convert_hash_from(x):
function load_sqlite_index (line 110) | def load_sqlite_index(filename, *, request_manifest=False):
class SqliteIndex (line 188) | class SqliteIndex(Index):
method __init__ (line 194) | def __init__(self, dbfile, *, sqlite_manifest=None, conn=None):
method _open (line 223) | def _open(cls, dbfile, *, empty_ok=True):
method load (line 243) | def load(self, dbfile):
method create (line 248) | def create(cls, dbfile, *, append=False):
method _create_tables (line 257) | def _create_tables(cls, c, *, ignore_exists=False):
method cursor (line 300) | def cursor(self):
method close (line 303) | def close(self):
method commit (line 306) | def commit(self):
method __len__ (line 309) | def __len__(self):
method insert (line 312) | def insert(self, ss, *, cursor=None, commit=True):
method location (line 363) | def location(self):
method signatures (line 366) | def signatures(self):
method signatures_with_location (line 371) | def signatures_with_location(self):
method save (line 378) | def save(self, *args, **kwargs):
method find (line 381) | def find(self, search_fn, query, **kwargs):
method _select (line 431) | def _select(self, *, num=0, track_abundance=False, **kwargs):
method select (line 450) | def select(self, *args, **kwargs):
method _load_sketch_size (line 460) | def _load_sketch_size(self, c1, sketch_id, max_hash):
method _load_sketch (line 478) | def _load_sketch(self, c, sketch_id, *, match_scaled=None):
method _load_sketches (line 541) | def _load_sketches(self, c):
method _get_matching_sketches (line 576) | def _get_matching_sketches(self, c, hashes, max_hash):
class SqliteCollectionManifest (line 625) | class SqliteCollectionManifest(BaseCollectionManifest):
method __init__ (line 641) | def __init__(self, conn, *, selection_dict=None, managed_by_index=False):
method create (line 659) | def create(cls, filename):
method create_or_open (line 667) | def create_or_open(cls, filename):
method load_from_manifest (line 678) | def load_from_manifest(cls, manifest, *, dbfile=":memory:", append=Fal...
method create_manifest (line 685) | def create_manifest(cls, locations_iter, *, include_signature=False):
method _create_tables (line 702) | def _create_tables(cls, cursor):
method add_row (line 728) | def add_row(self, row):
method _insert_row (line 732) | def _insert_row(self, cursor, row, *, call_is_from_index=False):
method __bool__ (line 756) | def __bool__(self):
method __eq__ (line 767) | def __eq__(self, other):
method __len__ (line 777) | def __len__(self):
method __iadd__ (line 788) | def __iadd__(self, other):
method __add__ (line 794) | def __add__(self, other):
method close (line 800) | def close(self):
method _make_select (line 803) | def _make_select(self):
method select_to_manifest (line 836) | def select_to_manifest(self, **kwargs):
method rows (line 861) | def rows(self):
method filter_rows (line 912) | def filter_rows(self, row_filter_fn):
method filter_on_columns (line 925) | def filter_on_columns(self, col_filter_fn, col_names):
method locations (line 934) | def locations(self):
method __contains__ (line 961) | def __contains__(self, ss):
method picklist (line 975) | def picklist(self):
method to_picklist (line 981) | def to_picklist(self):
method _create_manifest_from_rows (line 988) | def _create_manifest_from_rows(
class LCA_SqliteDatabase (line 1017) | class LCA_SqliteDatabase(SqliteIndex):
method __init__ (line 1024) | def __init__(self, dbfile, *, lineage_db=None, sqlite_manifest=None):
method load (line 1051) | def load(cls, filename):
method create (line 1070) | def create(cls, filename, idx, lineage_db):
method _build_index (line 1088) | def _build_index(self):
method insert (line 1135) | def insert(self, *args, **kwargs):
method select (line 1139) | def select(self, *args, **kwargs):
method downsample_scaled (line 1148) | def downsample_scaled(self, scaled):
method get_lineage_assignments (line 1157) | def get_lineage_assignments(self, hashval, *, min_num=None):
method idx_to_ident (line 1174) | def idx_to_ident(self):
method hashval_to_idx (line 1183) | def hashval_to_idx(self):
method hashvals (line 1188) | def hashvals(self):
method get_identifiers_for_hashval (line 1192) | def get_identifiers_for_hashval(self, hashval):
class _SqliteIndexHashvalToIndex (line 1199) | class _SqliteIndexHashvalToIndex:
method __init__ (line 1205) | def __init__(self, sqlidx):
method __iter__ (line 1208) | def __iter__(self):
method get (line 1215) | def get(self, key, dv=None):
method __getitem__ (line 1227) | def __getitem__(self, key):
FILE: src/sourmash/lca/__main__.py
function main (line 29) | def main(arglist=None):
FILE: src/sourmash/lca/command_classify.py
function classify_signature (line 18) | def classify_signature(query_sig, dblist, threshold, majority):
function classify (line 80) | def classify(args):
FILE: src/sourmash/lca/command_compare_csv.py
function compare_csv (line 15) | def compare_csv(args):
FILE: src/sourmash/lca/command_index.py
function load_taxonomy_assignments (line 19) | def load_taxonomy_assignments(
function generate_report (line 130) | def generate_report(
function index (line 166) | def index(args):
FILE: src/sourmash/lca/command_rankinfo.py
function make_lca_counts (line 13) | def make_lca_counts(dblist, min_num=0):
function rankinfo_main (line 44) | def rankinfo_main(args):
FILE: src/sourmash/lca/command_summarize.py
function summarize (line 20) | def summarize(hashvals, dblist, threshold, ignore_abundance):
function load_singletons_and_count (line 61) | def load_singletons_and_count(filenames, ksize, scaled, ignore_abundance):
function count_signature (line 91) | def count_signature(sig, scaled, hashvals):
function output_results (line 104) | def output_results(lineage_counts, total_counts, filename=None, sig=None):
function output_csv (line 124) | def output_csv(lineage_counts, total_counts, csv_fp, filename, sig, writ...
function summarize_main (line 142) | def summarize_main(args):
FILE: src/sourmash/lca/lca_db.py
function cached_property (line 16) | def cached_property(fun):
class LCA_Database (line 33) | class LCA_Database(Index):
method __init__ (line 69) | def __init__(self, ksize, scaled, moltype="DNA"):
method location (line 86) | def location(self):
method __len__ (line 93) | def __len__(self):
method _invalidate_cache (line 100) | def _invalidate_cache(self):
method _get_ident_index (line 108) | def _get_ident_index(self, ident, fail_on_duplicate=False):
method _get_lineage_id (line 125) | def _get_lineage_id(self, lineage):
method insert (line 145) | def insert(self, sig, ident=None, lineage=None):
method __repr__ (line 207) | def __repr__(self):
method signatures (line 212) | def signatures(self):
method _signatures_with_internal (line 228) | def _signatures_with_internal(self):
method select (line 237) | def select(
method load (line 298) | def load(cls, db_name):
method save (line 415) | def save(self, db_name, *, format="json"):
method save_to_json (line 422) | def save_to_json(self, db_name):
method save_to_sql (line 469) | def save_to_sql(self, dbname):
method downsample_scaled (line 495) | def downsample_scaled(self, scaled):
method hashvals (line 522) | def hashvals(self):
method get_lineage_assignments (line 526) | def get_lineage_assignments(self, hashval, min_num=None):
method get_identifiers_for_hashval (line 546) | def get_identifiers_for_hashval(self, hashval):
method _signatures (line 556) | def _signatures(self):
method find (line 621) | def find(self, search_fn, query, **kwargs):
method _lid_to_idx (line 694) | def _lid_to_idx(self):
method _idx_to_ident (line 705) | def _idx_to_ident(self):
function load_single_database (line 717) | def load_single_database(filename, verbose=False):
function load_databases (line 723) | def load_databases(filenames, scaled=None, verbose=True):
FILE: src/sourmash/lca/lca_utils.py
function check_files_exist (line 38) | def check_files_exist(*files):
function taxlist (line 58) | def taxlist(include_strain=True):
function zip_lineage (line 76) | def zip_lineage(lineage, include_strain=True, truncate_empty=False):
function display_lineage (line 119) | def display_lineage(lineage, include_strain=True, truncate_empty=True):
function filter_null (line 128) | def filter_null(x):
function build_tree (line 137) | def build_tree(assignments, initial=None):
function find_lca (line 165) | def find_lca(tree):
function gather_assignments (line 186) | def gather_assignments(hashvals, dblist):
function count_lca_for_assignments (line 202) | def count_lca_for_assignments(assignments, hashval_counts=None):
function is_lineage_match (line 228) | def is_lineage_match(lin_a, lin_b, rank):
function pop_to_rank (line 243) | def pop_to_rank(lin, rank):
function make_lineage (line 265) | def make_lineage(lineage):
FILE: src/sourmash/logging.py
function set_quiet (line 8) | def set_quiet(val, print_debug=False):
function print_results (line 14) | def print_results(s, *args, **kwargs):
function notify (line 22) | def notify(s, *args, **kwargs):
function debug (line 33) | def debug(s, *args, **kwargs):
function debug_literal (line 44) | def debug_literal(s, *args, **kwargs):
function error (line 55) | def error(s, *args, **kwargs):
function test_notify (line 63) | def test_notify():
function test_notify_flush (line 79) | def test_notify_flush():
function test_notify_end (line 95) | def test_notify_end():
function test_notify_quiet (line 111) | def test_notify_quiet():
function test_error (line 127) | def test_error():
function test_error_flush (line 143) | def test_error_flush():
function test_error_quiet (line 159) | def test_error_quiet():
FILE: src/sourmash/manifest.py
class BaseCollectionManifest (line 15) | class BaseCollectionManifest:
method load_from_manifest (line 47) | def load_from_manifest(cls, manifest, **kwargs):
method load_from_filename (line 51) | def load_from_filename(cls, filename):
method load_from_csv (line 67) | def load_from_csv(cls, fp):
method load_from_sql (line 103) | def load_from_sql(cls, filename):
method write_to_filename (line 112) | def write_to_filename(self, filename, *, database_format="csv", ok_if_...
method write_csv_header (line 130) | def write_csv_header(cls, fp):
method write_to_csv (line 136) | def write_to_csv(self, fp, write_header=False):
method make_manifest_row (line 150) | def make_manifest_row(cls, ss, location, *, include_signature=True):
method create_manifest (line 175) | def create_manifest(cls, locations_iter, *, include_signature=True):
method __add__ (line 193) | def __add__(self, other):
method __bool__ (line 197) | def __bool__(self):
method __len__ (line 201) | def __len__(self):
method __eq__ (line 205) | def __eq__(self, other):
method select_to_manifest (line 209) | def select_to_manifest(self, **kwargs):
method filter_rows (line 213) | def filter_rows(self, row_filter_fn):
method filter_on_columns (line 217) | def filter_on_columns(self, col_filter_fn, col_names):
method locations (line 221) | def locations(self):
method __contains__ (line 225) | def __contains__(self, ss):
method to_picklist (line 229) | def to_picklist(self):
method _check_row_values (line 232) | def _check_row_values(self):
class CollectionManifest (line 244) | class CollectionManifest(BaseCollectionManifest):
method __init__ (line 249) | def __init__(self, rows=[]):
method load_from_manifest (line 257) | def load_from_manifest(cls, manifest, **kwargs):
method _from_rust (line 262) | def _from_rust(value):
method add_row (line 301) | def add_row(self, row):
method _add_rows (line 304) | def _add_rows(self, rows):
method __iadd__ (line 312) | def __iadd__(self, other):
method __add__ (line 318) | def __add__(self, other):
method __bool__ (line 323) | def __bool__(self):
method __len__ (line 326) | def __len__(self):
method __eq__ (line 329) | def __eq__(self, other):
method _select (line 342) | def _select(
method select_to_manifest (line 387) | def select_to_manifest(self, **kwargs):
method filter_rows (line 392) | def filter_rows(self, row_filter_fn):
method filter_on_columns (line 398) | def filter_on_columns(self, col_filter_fn, col_names):
method locations (line 407) | def locations(self):
method __contains__ (line 418) | def __contains__(self, ss):
method to_picklist (line 423) | def to_picklist(self):
FILE: src/sourmash/minhash.py
function get_minhash_default_seed (line 38) | def get_minhash_default_seed():
function get_minhash_max_hash (line 48) | def get_minhash_max_hash():
function _get_max_hash_for_scaled (line 53) | def _get_max_hash_for_scaled(scaled):
function _get_scaled_for_max_hash (line 63) | def _get_scaled_for_max_hash(max_hash):
function to_bytes (line 70) | def to_bytes(s):
function hash_murmur (line 88) | def hash_murmur(kmer, seed=MINHASH_DEFAULT_SEED):
function translate_codon (line 96) | def translate_codon(codon):
function flatten_and_downsample_scaled (line 104) | def flatten_and_downsample_scaled(mh, *scaled_vals):
function flatten_and_downsample_num (line 116) | def flatten_and_downsample_num(mh, *num_vals):
function flatten_and_intersect_scaled (line 128) | def flatten_and_intersect_scaled(mh1, mh2):
class _HashesWrapper (line 137) | class _HashesWrapper(Mapping):
method __init__ (line 140) | def __init__(self, h):
method __getitem__ (line 143) | def __getitem__(self, key):
method __repr__ (line 146) | def __repr__(self):
method __len__ (line 149) | def __len__(self):
method __iter__ (line 152) | def __iter__(self):
method __eq__ (line 155) | def __eq__(self, other):
method __setitem__ (line 158) | def __setitem__(self, k, v):
class MinHash (line 162) | class MinHash(RustObject):
method __init__ (line 191) | def __init__(
method __copy__ (line 267) | def __copy__(self):
method __getstate__ (line 286) | def __getstate__(self):
method __setstate__ (line 313) | def __setstate__(self, tup):
method __eq__ (line 355) | def __eq__(self, other):
method copy_and_clear (line 359) | def copy_and_clear(self):
method add_sequence (line 375) | def add_sequence(self, sequence, force=False):
method seq_to_hashes (line 379) | def seq_to_hashes(
method kmers_and_hashes (line 419) | def kmers_and_hashes(self, sequence, *, force=False, is_protein=False):
method add_kmer (line 488) | def add_kmer(self, kmer):
method add_many (line 498) | def add_many(self, hashes):
method remove_many (line 509) | def remove_many(self, hashes):
method __len__ (line 520) | def __len__(self):
method get_mins (line 530) | def get_mins(self, with_abundance=False):
method get_hashes (line 545) | def get_hashes(self):
method hashes (line 550) | def hashes(self):
method seed (line 574) | def seed(self):
method num (line 578) | def num(self):
method scaled (line 582) | def scaled(self):
method is_dna (line 589) | def is_dna(self):
method is_protein (line 595) | def is_protein(self):
method dayhoff (line 599) | def dayhoff(self):
method hp (line 603) | def hp(self):
method skipm1n3 (line 607) | def skipm1n3(self):
method skipm2n3 (line 611) | def skipm2n3(self):
method ksize (line 615) | def ksize(self):
method max_hash (line 629) | def max_hash(self):
method _max_hash (line 634) | def _max_hash(self):
method track_abundance (line 638) | def track_abundance(self):
method track_abundance (line 642) | def track_abundance(self, b):
method add_hash (line 655) | def add_hash(self, h):
method add_hash_with_abundance (line 659) | def add_hash_with_abundance(self, h, a):
method clear (line 669) | def clear(self):
method count_common (line 673) | def count_common(self, other, downsample=False):
method intersection_and_union_size (line 685) | def intersection_and_union_size(self, other):
method downsample (line 700) | def downsample(self, *, num=None, scaled=None):
method flatten (line 759) | def flatten(self):
method jaccard (line 780) | def jaccard(self, other, downsample=False):
method jaccard_ani (line 789) | def jaccard_ani(
method similarity (line 827) | def similarity(self, other, ignore_abundance=False, downsample=False):
method angular_similarity (line 848) | def angular_similarity(self, other, downsample=False):
method is_compatible (line 860) | def is_compatible(self, other):
method contained_by (line 863) | def contained_by(self, other, downsample=False):
method contained_by_weighted (line 887) | def contained_by_weighted(self, other):
method containment_ani (line 907) | def containment_ani(
method max_containment (line 945) | def max_containment(self, other, downsample=False):
method max_containment_ani (line 971) | def max_containment_ani(
method avg_containment (line 1010) | def avg_containment(self, other, *, downsample=False):
method avg_containment_ani (line 1025) | def avg_containment_ani(self, other, *, downsample=False, prob_thresho...
method __add__ (line 1042) | def __add__(self, other):
method __iadd__ (line 1058) | def __iadd__(self, other):
method merge (line 1064) | def merge(self, other):
method intersection (line 1069) | def intersection(self, other):
method set_abundances (line 1080) | def set_abundances(self, values, clear=True):
method add_protein (line 1106) | def add_protein(self, sequence):
method moltype (line 1111) | def moltype(self): # TODO: test in minhash tests
method to_mutable (line 1125) | def to_mutable(self):
method to_frozen (line 1129) | def to_frozen(self):
method into_frozen (line 1135) | def into_frozen(self):
method inflate (line 1139) | def inflate(self, from_mh):
method sum_abundances (line 1162) | def sum_abundances(self):
method mean_abundance (line 1168) | def mean_abundance(self):
method median_abundance (line 1174) | def median_abundance(self):
method std_abundance (line 1180) | def std_abundance(self):
method unique_dataset_hashes (line 1186) | def unique_dataset_hashes(self):
method size_is_accurate (line 1197) | def size_is_accurate(self, relative_error=0.20, confidence=0.95):
class FrozenMinHash (line 1220) | class FrozenMinHash(MinHash):
method add_sequence (line 1221) | def add_sequence(self, *args, **kwargs):
method add_kmer (line 1224) | def add_kmer(self, *args, **kwargs):
method add_many (line 1227) | def add_many(self, *args, **kwargs):
method remove_many (line 1230) | def remove_many(self, *args, **kwargs):
method add_hash (line 1233) | def add_hash(self, *args, **kwargs):
method add_hash_with_abundance (line 1236) | def add_hash_with_abundance(self, *args, **kwargs):
method clear (line 1239) | def clear(self, *args, **kwargs):
method set_abundances (line 1242) | def set_abundances(self, *args, **kwargs):
method add_protein (line 1245) | def add_protein(self, *args, **kwargs):
method downsample (line 1248) | def downsample(self, *, num=None, scaled=None):
method flatten (line 1258) | def flatten(self):
method __iadd__ (line 1265) | def __iadd__(self, *args, **kwargs):
method merge (line 1268) | def merge(self, *args, **kwargs):
method to_mutable (line 1271) | def to_mutable(self):
method to_frozen (line 1279) | def to_frozen(self):
method into_frozen (line 1283) | def into_frozen(self):
method __setstate__ (line 1287) | def __setstate__(self, tup):
method __copy__ (line 1329) | def __copy__(self):
FILE: src/sourmash/nodegraph.py
class Nodegraph (line 13) | class Nodegraph(RustObject):
method __init__ (line 16) | def __init__(self, ksize, starting_size, n_tables):
method load (line 20) | def load(filename):
method from_buffer (line 25) | def from_buffer(buf):
method save (line 29) | def save(self, filename):
method to_bytes (line 32) | def to_bytes(self, compression=1):
method update (line 42) | def update(self, other):
method count (line 52) | def count(self, h):
method get (line 57) | def get(self, h):
method n_occupied (line 62) | def n_occupied(self):
method ksize (line 65) | def ksize(self):
method hashsizes (line 68) | def hashsizes(self):
method expected_collisions (line 78) | def expected_collisions(self):
method matches (line 81) | def matches(self, mh):
method to_khmer_nodegraph (line 90) | def to_khmer_nodegraph(self):
function extract_nodegraph_info (line 105) | def extract_nodegraph_info(filename):
function calc_expected_collisions (line 146) | def calc_expected_collisions(graph, force=False, max_false_pos=0.2):
FILE: src/sourmash/np_utils.py
function to_memmap (line 4) | def to_memmap(array):
FILE: src/sourmash/picklist.py
function combine_ident_md5 (line 35) | def combine_ident_md5(x):
class PickStyle (line 49) | class PickStyle(Enum):
class SignaturePicklist (line 54) | class SignaturePicklist:
method __init__ (line 92) | def __init__(
method from_picklist_args (line 127) | def from_picklist_args(cls, argstr):
method _get_sig_attribute (line 152) | def _get_sig_attribute(self, ss):
method _get_value_for_manifest_row (line 168) | def _get_value_for_manifest_row(self, row):
method _get_value_for_csv_row (line 191) | def _get_value_for_csv_row(self, row):
method init (line 209) | def init(self, values=[]):
method load (line 216) | def load(self, *, allow_empty=False):
method add (line 261) | def add(self, value):
method __contains__ (line 265) | def __contains__(self, ss):
method matches_manifest_row (line 287) | def matches_manifest_row(self, row):
method matched_csv_row (line 302) | def matched_csv_row(self, row):
method filter (line 314) | def filter(self, it):
function passes_all_picklists (line 321) | def passes_all_picklists(ss, picklists):
FILE: src/sourmash/plugins.py
function get_load_from_functions (line 45) | def get_load_from_functions():
function get_save_to_functions (line 68) | def get_save_to_functions():
class CommandLinePlugin (line 91) | class CommandLinePlugin:
method __init__ (line 101) | def __init__(self, parser):
method main (line 109) | def main(self, args):
function get_cli_script_plugins (line 113) | def get_cli_script_plugins():
function get_cli_scripts_descriptions (line 143) | def get_cli_scripts_descriptions():
function add_cli_scripts (line 159) | def add_cli_scripts(parser):
function list_all_plugins (line 188) | def list_all_plugins():
FILE: src/sourmash/save_load.py
function load_file_as_index (line 52) | def load_file_as_index(filename, *, yield_all_files=False):
function SaveSignaturesToLocation (line 70) | def SaveSignaturesToLocation(location):
function _load_database (line 95) | def _load_database(filename, traverse_yield_all, *, cache_size=None):
function add_loader (line 141) | def add_loader(name, priority):
function _load_stdin (line 152) | def _load_stdin(filename, **kwargs):
function _load_standalone_manifest (line 165) | def _load_standalone_manifest(filename, **kwargs):
function _multiindex_load_from_pathlist (line 177) | def _multiindex_load_from_pathlist(filename, **kwargs):
function _multiindex_load_from_path (line 185) | def _multiindex_load_from_path(filename, **kwargs):
function _load_sbt (line 194) | def _load_sbt(filename, **kwargs):
function _load_revindex (line 207) | def _load_revindex(filename, **kwargs):
function _load_sqlite_db (line 214) | def _load_sqlite_db(filename, **kwargs):
function _load_disk_revindex (line 219) | def _load_disk_revindex(filename, **kwargs):
function _load_zipfile (line 224) | def _load_zipfile(filename, **kwargs):
function _error_on_fastaq (line 242) | def _error_on_fastaq(filename, **kwargs):
class Base_SaveSignaturesToLocation (line 262) | class Base_SaveSignaturesToLocation:
method __init__ (line 265) | def __init__(self, location):
method matches (line 270) | def matches(cls, location):
method __repr__ (line 274) | def __repr__(self):
method __len__ (line 277) | def __len__(self):
method open (line 280) | def open(self):
method close (line 283) | def close(self):
method __enter__ (line 286) | def __enter__(self):
method __exit__ (line 291) | def __exit__(self, type, value, traceback):
method add (line 295) | def add(self, ss):
method add_many (line 298) | def add_many(self, sslist):
function _get_signatures_from_rust (line 303) | def _get_signatures_from_rust(siglist):
class SaveSignatures_NoOutput (line 313) | class SaveSignatures_NoOutput(Base_SaveSignaturesToLocation):
method __repr__ (line 316) | def __repr__(self):
method matches (line 320) | def matches(cls, location):
method open (line 323) | def open(self):
method close (line 326) | def close(self):
class SaveSignatures_Directory (line 330) | class SaveSignatures_Directory(Base_SaveSignaturesToLocation):
method __init__ (line 333) | def __init__(self, location):
method __repr__ (line 336) | def __repr__(self):
method matches (line 340) | def matches(cls, location):
method close (line 345) | def close(self):
method open (line 348) | def open(self):
method add (line 357) | def add(self, ss):
class SaveSignatures_SqliteIndex (line 375) | class SaveSignatures_SqliteIndex(Base_SaveSignaturesToLocation):
method __init__ (line 378) | def __init__(self, location):
method matches (line 385) | def matches(cls, location):
method __repr__ (line 390) | def __repr__(self):
method close (line 393) | def close(self):
method open (line 398) | def open(self):
method add (line 402) | def add(self, add_sig):
class SaveSignatures_SigFile (line 412) | class SaveSignatures_SigFile(Base_SaveSignaturesToLocation):
method __init__ (line 415) | def __init__(self, location):
method matches (line 423) | def matches(cls, location):
method __repr__ (line 427) | def __repr__(self):
method open (line 430) | def open(self):
method close (line 433) | def close(self):
method add (line 449) | def add(self, ss):
class SaveSignatures_ZipFile (line 454) | class SaveSignatures_ZipFile(Base_SaveSignaturesToLocation):
method __init__ (line 457) | def __init__(self, location):
method matches (line 462) | def matches(cls, location):
method __repr__ (line 467) | def __repr__(self):
method close (line 470) | def close(self):
method open (line 484) | def open(self):
method _exists (line 522) | def _exists(self, name):
method add (line 529) | def add(self, add_sig):
FILE: src/sourmash/sbt.py
class GraphFactory (line 43) | class GraphFactory:
method __init__ (line 56) | def __init__(self, ksize, starting_size, n_tables):
method __call__ (line 61) | def __call__(self):
method init_args (line 64) | def init_args(self):
class _NodesCache (line 68) | class _NodesCache(Cache):
method __init__ (line 76) | def __init__(self, maxsize, getsizeof=None):
method __getitem__ (line 80) | def __getitem__(self, key, cache_getitem=Cache.__getitem__):
method __setitem__ (line 85) | def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
method __delitem__ (line 89) | def __delitem__(self, key, cache_delitem=Cache.__delitem__):
method popitem (line 93) | def popitem(self):
class SBT (line 118) | class SBT(Index):
method __init__ (line 146) | def __init__(self, factory, *, d=2, storage=None, cache_size=None):
method location (line 162) | def location(self):
method signatures (line 165) | def signatures(self):
method _signatures_with_internal (line 191) | def _signatures_with_internal(self):
method select (line 200) | def select(
method new_node_pos (line 293) | def new_node_pos(self, node):
method insert (line 325) | def insert(self, signature):
method add_node (line 332) | def add_node(self, node):
method _find_nodes (line 383) | def _find_nodes(self, search_fn, *args, **kwargs):
method find (line 434) | def find(self, search_fn, query, **kwargs):
method _rebuild_node (line 545) | def _rebuild_node(self, pos=0):
method parent (line 571) | def parent(self, pos):
method children (line 596) | def children(self, pos):
method child (line 612) | def child(self, parent, pos):
method save (line 637) | def save(self, path, storage=None, sparseness=0.0, structure_only=False):
method load (line 825) | def load(
method _load_v1 (line 952) | def _load_v1(
method _load_v2 (line 992) | def _load_v2(
method _load_v3 (line 1035) | def _load_v3(
method _load_v4 (line 1090) | def _load_v4(
method _load_v5 (line 1134) | def _load_v5(
method _load_v6 (line 1185) | def _load_v6(
method _fill_min_n_below (line 1235) | def _fill_min_n_below(self):
method _fill_internal (line 1262) | def _fill_internal(self):
method _fill_up (line 1272) | def _fill_up(self, search_fn, *args, **kwargs):
method __len__ (line 1312) | def __len__(self):
method print_dot (line 1315) | def print_dot(self):
method print (line 1335) | def print(self):
method __iter__ (line 1349) | def __iter__(self):
method _parents (line 1355) | def _parents(self, pos=0):
method leaves (line 1364) | def leaves(self, with_pos=False, unload_data=True):
method combine (line 1373) | def combine(self, other):
class Node (line 1411) | class Node:
method __init__ (line 1414) | def __init__(self, factory, name=None, path=None, storage=None):
method __str__ (line 1422) | def __str__(self):
method save (line 1425) | def save(self, path):
method data (line 1430) | def data(self):
method data (line 1440) | def data(self, new_data):
method unload (line 1443) | def unload(self):
method load (line 1450) | def load(info, storage=None):
method update (line 1457) | def update(self, parent):
class Leaf (line 1469) | class Leaf:
method __init__ (line 1470) | def __init__(self, metadata, data=None, name=None, storage=None, path=...
method __str__ (line 1482) | def __str__(self):
method make_manifest_row (line 1485) | def make_manifest_row(self, location):
method data (line 1489) | def data(self):
method data (line 1496) | def data(self, new_data):
method unload (line 1499) | def unload(self):
method save (line 1505) | def save(self, path):
method update (line 1509) | def update(self, parent):
method load (line 1513) | def load(cls, info, storage=None):
function filter_distance (line 1519) | def filter_distance(filter_a, filter_b, n=1000):
function convert_cmd (line 1556) | def convert_cmd(name, backend):
FILE: src/sourmash/sbt_storage.py
class Storage (line 18) | class Storage(ABC):
method save (line 20) | def save(self, path, content, *, overwrite=False):
method load (line 24) | def load(self, path):
method list_sbts (line 27) | def list_sbts(self):
method init_args (line 30) | def init_args(self):
method __enter__ (line 33) | def __enter__(self):
method __exit__ (line 36) | def __exit__(self, type, value, traceback):
method close (line 39) | def close(self):
method can_open (line 42) | def can_open(self, location):
class FSStorage (line 46) | class FSStorage(Storage):
method __init__ (line 47) | def __init__(self, location, subdir, make_dirs=True):
method init_args (line 56) | def init_args(self):
method save (line 59) | def save(self, path, content, overwrite=False):
method load (line 91) | def load(self, path):
class ZipStorage (line 96) | class ZipStorage(RustObject, Storage):
method __init__ (line 99) | def __init__(self, path, *, mode="r"):
method can_open (line 108) | def can_open(location):
method path (line 112) | def path(self):
method subdir (line 118) | def subdir(self):
method subdir (line 124) | def subdir(self, value):
method _filenames (line 130) | def _filenames(self):
method save (line 145) | def save(self, path, content, *, overwrite=False, compress=False):
method load (line 152) | def load(self, path):
method list_sbts (line 171) | def list_sbts(self):
method init_args (line 186) | def init_args(self):
method flush (line 189) | def flush(self):
method close (line 193) | def close(self):
method can_open (line 198) | def can_open(location):
class _RwZipStorage (line 202) | class _RwZipStorage(Storage):
method __init__ (line 203) | def __init__(self, path):
method _filenames (line 232) | def _filenames(self):
method _content_matches (line 235) | def _content_matches(self, zf, path, content):
method _generate_filename (line 242) | def _generate_filename(self, zf, path, content):
method _write_to_zf (line 267) | def _write_to_zf(self, zf, path, content, *, compress=False):
method save (line 282) | def save(self, path, content, *, overwrite=False, compress=False):
method _load_from_zf (line 311) | def _load_from_zf(self, zf, path):
method load (line 320) | def load(self, path):
method close (line 329) | def close(self):
method flush (line 341) | def flush(self, *, keep_closed=False):
method list_sbts (line 411) | def list_sbts(self):
method __del__ (line 414) | def __del__(self):
class IPFSStorage (line 418) | class IPFSStorage(Storage):
method __init__ (line 419) | def __init__(self, pin_on_add=True, **kwargs):
method save (line 426) | def save(self, path, content, *, overwrite=False):
method load (line 441) | def load(self, path):
method init_args (line 444) | def init_args(self):
method __exit__ (line 447) | def __exit__(self, type, value, traceback):
class RedisStorage (line 457) | class RedisStorage(Storage):
method __init__ (line 458) | def __init__(self, **kwargs):
method save (line 464) | def save(self, path, content, *, overwrite=False):
method load (line 470) | def load(self, path):
method init_args (line 473) | def init_args(self):
method __exit__ (line 477) | def __exit__(self, type, value, traceback):
FILE: src/sourmash/sbtmh.py
function load_sbt_index (line 8) | def load_sbt_index(filename, *, print_version_warning=True, cache_size=N...
function create_sbt_index (line 18) | def create_sbt_index(bloom_filter_size=1e5, n_children=2):
function search_sbt_index (line 25) | def search_sbt_index(tree, query, threshold):
class SigLeaf (line 39) | class SigLeaf(Leaf):
method __str__ (line 40) | def __str__(self):
method make_manifest_row (line 43) | def make_manifest_row(self, loc):
method save (line 49) | def save(self, path):
method update (line 58) | def update(self, parent):
method data (line 70) | def data(self):
method data (line 77) | def data(self, new_data):
FILE: src/sourmash/search.py
function calc_threshold_from_bp (line 15) | def calc_threshold_from_bp(threshold_bp, scaled, query_size):
class SearchType (line 40) | class SearchType(Enum):
function make_jaccard_search_query (line 46) | def make_jaccard_search_query(
function make_containment_query (line 70) | def make_containment_query(query_mh, threshold_bp, *, best_only=True):
class JaccardSearch (line 90) | class JaccardSearch:
method __init__ (line 95) | def __init__(self, search_type, threshold=None):
method check_is_compatible (line 115) | def check_is_compatible(self, sig):
method passes (line 127) | def passes(self, score):
method collect (line 139) | def collect(self, score, match_sig):
method score_jaccard (line 143) | def score_jaccard(self, query_size, shared_size, subject_size, total_s...
method score_containment (line 149) | def score_containment(self, query_size, shared_size, subject_size, tot...
method score_max_containment (line 155) | def score_max_containment(self, query_size, shared_size, subject_size,...
class JaccardSearchBestOnly (line 163) | class JaccardSearchBestOnly(JaccardSearch):
method collect (line 166) | def collect(self, score, match):
class BaseResult (line 173) | class BaseResult:
method init_result (line 193) | def init_result(self):
method build_fracminhashcomparison (line 197) | def build_fracminhashcomparison(self):
method build_numminhashcomparison (line 212) | def build_numminhashcomparison(self, cmp_num=None):
method get_cmpinfo (line 221) | def get_cmpinfo(self):
method pass_threshold (line 247) | def pass_threshold(self):
method shorten_md5 (line 250) | def shorten_md5(self, md5):
method to_write (line 253) | def to_write(self, columns=[]):
method init_dictwriter (line 261) | def init_dictwriter(self, csv_handle):
method prep_result (line 267) | def prep_result(self):
method write (line 271) | def write(self, w):
method resultdict (line 277) | def resultdict(self):
class SearchResult (line 284) | class SearchResult(BaseResult):
method init_sigcomparison (line 309) | def init_sigcomparison(self):
method __post_init__ (line 317) | def __post_init__(self):
method check_similarity (line 327) | def check_similarity(self):
method estimate_search_ani (line 334) | def estimate_search_ani(self):
class PrefetchResult (line 361) | class PrefetchResult(BaseResult):
method init_sigcomparison (line 402) | def init_sigcomparison(self):
method estimate_containment_ani (line 419) | def estimate_containment_ani(self):
method handle_ani_ci (line 429) | def handle_ani_ci(self):
method build_prefetch_result (line 435) | def build_prefetch_result(self):
method __post_init__ (line 449) | def __post_init__(self):
method prep_prefetch_result (line 453) | def prep_prefetch_result(self):
method prep_result (line 461) | def prep_result(self):
method prefetchresultdict (line 466) | def prefetchresultdict(self):
class GatherResult (line 473) | class GatherResult(PrefetchResult):
method init_gathersketchcomparison (line 526) | def init_gathersketchcomparison(self):
method check_gatherresult_input (line 532) | def check_gatherresult_input(self):
method build_gather_result (line 553) | def build_gather_result(self):
method __post_init__ (line 625) | def __post_init__(self):
method prep_gather_result (line 635) | def prep_gather_result(self):
method prep_result (line 640) | def prep_result(self):
method gatherresultdict (line 645) | def gatherresultdict(self):
method prefetchresultdict (line 651) | def prefetchresultdict(self):
function format_bp (line 667) | def format_bp(bp):
function search_databases_with_flat_query (line 681) | def search_databases_with_flat_query(query, databases, **kwargs):
function search_databases_with_abund_query (line 724) | def search_databases_with_abund_query(query, databases, **kwargs):
function _find_best (line 755) | def _find_best(counters, query, threshold_bp):
class GatherDatabases (line 782) | class GatherDatabases:
method __init__ (line 785) | def __init__(
method _update_scaled (line 847) | def _update_scaled(self, scaled):
method scaled (line 871) | def scaled(self):
method __iter__ (line 874) | def __iter__(self):
method __next__ (line 877) | def __next__(self):
function prefetch_database (line 957) | def prefetch_database(query, database, threshold_bp, *, estimate_ani_ci=...
FILE: src/sourmash/sig/__main__.py
function _check_abundance_compatibility (line 82) | def _check_abundance_compatibility(sig1, sig2):
function _extend_signatures_with_from_file (line 89) | def _extend_signatures_with_from_file(args, *, target_attr="signatures"):
function _set_num_scaled (line 99) | def _set_num_scaled(mh, num, scaled):
function cat (line 114) | def cat(args):
function split (line 166) | def split(args):
function describe (line 250) | def describe(args):
function manifest (line 347) | def manifest(args):
function overlap (line 389) | def overlap(args):
function merge (line 505) | def merge(args):
function intersect (line 572) | def intersect(args):
function inflate (line 641) | def inflate(args):
function subtract (line 689) | def subtract(args):
function rename (line 761) | def rename(args):
function extract (line 799) | def extract(args):
function filter (line 876) | def filter(args):
function flatten (line 927) | def flatten(args):
function downsample (line 972) | def downsample(args):
function ingest (line 1048) | def ingest(args):
function export (line 1105) | def export(args):
function kmers (line 1133) | def kmers(args):
function _summarize_manifest (line 1356) | def _summarize_manifest(manifest):
function fileinfo (line 1389) | def fileinfo(args):
function check (line 1458) | def check(args):
function collect (line 1603) | def collect(args):
function main (line 1724) | def main(arglist=None):
FILE: src/sourmash/sig/grep.py
function main (line 14) | def main(args):
FILE: src/sourmash/signature.py
class SigInput (line 22) | class SigInput(Enum):
class SourmashSignature (line 29) | class SourmashSignature(RustObject):
method __init__ (line 34) | def __init__(self, minhash, name="", filename=""):
method minhash (line 45) | def minhash(self):
method minhash (line 49) | def minhash(self, value):
method __hash__ (line 53) | def __hash__(self):
method __str__ (line 56) | def __str__(self):
method __repr__ (line 59) | def __repr__(self):
method md5sum (line 79) | def md5sum(self):
method __eq__ (line 83) | def __eq__(self, other):
method _name (line 87) | def _name(self):
method _name (line 91) | def _name(self, value):
method name (line 95) | def name(self):
method name (line 99) | def name(self, value):
method __ne__ (line 102) | def __ne__(self, other):
method filename (line 106) | def filename(self):
method filename (line 110) | def filename(self, value):
method license (line 114) | def license(self):
method _display_name (line 117) | def _display_name(self, max_length=0):
method display (line 133) | def display(self, location=None):
method similarity (line 151) | def similarity(self, other, ignore_abundance=False, downsample=False):
method jaccard (line 157) | def jaccard(self, other, downsample=False):
method jaccard_ani (line 163) | def jaccard_ani(
method angular_similarity (line 181) | def angular_similarity(self, other, downsample=False):
method contained_by (line 185) | def contained_by(self, other, downsample=False):
method contained_by_weighted (line 189) | def contained_by_weighted(self, other):
method containment_ani (line 193) | def containment_ani(
method max_containment (line 211) | def max_containment(self, other, downsample=False):
method max_containment_ani (line 215) | def max_containment_ani(
method avg_containment (line 233) | def avg_containment(self, other, downsample=False):
method avg_containment_ani (line 240) | def avg_containment_ani(self, other, *, downsample=False):
method add_sequence (line 247) | def add_sequence(self, sequence, force=False):
method add_protein (line 250) | def add_protein(self, sequence):
method from_params (line 254) | def from_params(params):
method __len__ (line 258) | def __len__(self):
method __getstate__ (line 261) | def __getstate__(self): # enable pickling
method __setstate__ (line 268) | def __setstate__(self, tup):
method __reduce__ (line 279) | def __reduce__(self):
method __copy__ (line 285) | def __copy__(self):
method to_frozen (line 295) | def to_frozen(self):
method to_mutable (line 301) | def to_mutable(self):
method into_frozen (line 305) | def into_frozen(self):
class FrozenSourmashSignature (line 312) | class FrozenSourmashSignature(SourmashSignature):
method minhash (line 316) | def minhash(self, value):
method _name (line 320) | def _name(self, value):
method name (line 324) | def name(self, value):
method filename (line 328) | def filename(self, value):
method add_sequence (line 331) | def add_sequence(self, sequence, force=False):
method add_protein (line 334) | def add_protein(self, sequence):
method __copy__ (line 337) | def __copy__(self):
method to_frozen (line 342) | def to_frozen(self):
method to_mutable (line 346) | def to_mutable(self):
method into_frozen (line 353) | def into_frozen(self):
method update (line 358) | def update(self):
function _detect_input_type (line 376) | def _detect_input_type(data):
function load_signatures_from_json (line 409) | def load_signatures_from_json(
function load_one_signature_from_json (line 499) | def load_one_signature_from_json(
function save_signatures_to_json (line 519) | def save_signatures_to_json(siglist, fp=None, compression=0):
FILE: src/sourmash/sketchcomparison.py
class BaseMinHashComparison (line 12) | class BaseMinHashComparison:
method downsample_and_handle_ignore_abundance (line 20) | def downsample_and_handle_ignore_abundance(self, cmp_num=None, cmp_sca...
method check_compatibility_and_downsample (line 39) | def check_compatibility_and_downsample(self, cmp_num=None, cmp_scaled=...
method intersect_mh (line 55) | def intersect_mh(self):
method jaccard (line 60) | def jaccard(self):
method estimate_jaccard_ani (line 63) | def estimate_jaccard_ani(self, jaccard=None):
method angular_similarity (line 72) | def angular_similarity(self):
method cosine_similarity (line 77) | def cosine_similarity(self):
class NumMinHashComparison (line 82) | class NumMinHashComparison(BaseMinHashComparison):
method __post_init__ (line 87) | def __post_init__(self):
method size_may_be_inaccurate (line 94) | def size_may_be_inaccurate(self):
class FracMinHashComparison (line 99) | class FracMinHashComparison(BaseMinHashComparison):
method __post_init__ (line 108) | def __post_init__(self):
method pass_threshold (line 117) | def pass_threshold(self):
method size_may_be_inaccurate (line 121) | def size_may_be_inaccurate(self):
method total_unique_intersect_hashes (line 129) | def total_unique_intersect_hashes(self):
method mh1_containment_in_mh2 (line 140) | def mh1_containment_in_mh2(self):
method estimate_ani_from_mh1_containment_in_mh2 (line 143) | def estimate_ani_from_mh1_containment_in_mh2(self, containment=None):
method mh2_containment_in_mh1 (line 162) | def mh2_containment_in_mh1(self):
method estimate_ani_from_mh2_containment_in_mh1 (line 165) | def estimate_ani_from_mh2_containment_in_mh1(self, containment=None):
method max_containment (line 181) | def max_containment(self):
method estimate_max_containment_ani (line 184) | def estimate_max_containment_ani(self, max_containment=None):
method avg_containment (line 201) | def avg_containment(self):
method avg_containment_ani (line 205) | def avg_containment_ani(self):
method estimate_all_containment_ani (line 222) | def estimate_all_containment_ani(self):
method weighted_intersection (line 242) | def weighted_intersection(self, from_mh=None, from_abundD={}):
FILE: src/sourmash/sourmash_args.py
function check_scaled_bounds (line 61) | def check_scaled_bounds(arg):
function check_num_bounds (line 73) | def check_num_bounds(arg):
function get_moltype (line 85) | def get_moltype(sig, require=False):
function calculate_moltype (line 95) | def calculate_moltype(args, default=None):
function load_picklist (line 127) | def load_picklist(args):
function report_picklist (line 157) | def report_picklist(args, picklist):
function load_include_exclude_db_patterns (line 176) | def load_include_exclude_db_patterns(args):
function apply_picklist_and_pattern (line 207) | def apply_picklist_and_pattern(db, picklist, pattern):
function load_query_signature (line 225) | def load_query_signature(filename, ksize, select_moltype, select_md5=None):
function _check_suffix (line 276) | def _check_suffix(filename, endings):
function traverse_find_sigs (line 283) | def traverse_find_sigs(filenames, yield_all_files=False):
function load_dbs_and_sigs (line 306) | def load_dbs_and_sigs(
function load_pathlist_from_file (line 388) | def load_pathlist_from_file(filename):
class FileOutput (line 410) | class FileOutput:
method __init__ (line 432) | def __init__(self, filename, mode="wt", *, newline=None, encoding="utf...
method open (line 439) | def open(self):
method close (line 447) | def close(self):
method __enter__ (line 451) | def __enter__(self):
method __exit__ (line 454) | def __exit__(self, type, value, traceback):
class FileOutputCSV (line 462) | class FileOutputCSV(FileOutput):
method __init__ (line 484) | def __init__(self, filename):
method open (line 488) | def open(self):
class _DictReader_with_version (line 498) | class _DictReader_with_version:
method __init__ (line 507) | def __init__(self, textfp, *, delimiter=","):
method __iter__ (line 531) | def __iter__(self):
function FileInputCSV (line 536) | def FileInputCSV(
class SignatureLoadingProgress (line 609) | class SignatureLoadingProgress:
method __init__ (line 621) | def __init__(self, reporting_interval=10):
method __len__ (line 626) | def __len__(self):
method short_notify (line 629) | def short_notify(self, msg_template, *args, **kwargs):
method notify (line 645) | def notify(self, location):
method start_file (line 650) | def start_file(self, location, loader):
function load_many_signatures (line 678) | def load_many_signatures(
function get_manifest (line 735) | def get_manifest(idx, *, require=True, rebuild=False):
function load_file_as_signatures (line 773) | def load_file_as_signatures(
function load_one_signature (line 825) | def load_one_signature(
FILE: src/sourmash/sqlite_utils.py
function open_sqlite_db (line 10) | def open_sqlite_db(filename):
function add_sourmash_internal (line 49) | def add_sourmash_internal(cursor, use_type, version):
function get_sourmash_internal (line 80) | def get_sourmash_internal(cursor):
FILE: src/sourmash/tax/__main__.py
function make_outfile (line 57) | def make_outfile(base, output_type, *, output_dir=""):
function metagenome (line 73) | def metagenome(args):
function genome (line 323) | def genome(args):
function annotate (line 486) | def annotate(args):
function prepare (line 600) | def prepare(args):
function grep (line 628) | def grep(args):
function summarize (line 684) | def summarize(args):
function main (line 752) | def main(arglist=None):
FILE: src/sourmash/tax/tax_utils.py
class LineagePair (line 84) | class LineagePair(NamedTuple):
class BaseLineageInfo (line 91) | class BaseLineageInfo:
method __post_init__ (line 117) | def __post_init__(self):
method __eq__ (line 129) | def __eq__(self, other):
method taxlist (line 137) | def taxlist(self):
method ascending_taxlist (line 141) | def ascending_taxlist(self):
method lowest_rank (line 145) | def lowest_rank(self):
method rank_index (line 150) | def rank_index(self, rank):
method name_at_rank (line 154) | def name_at_rank(self, rank):
method filled_lineage (line 163) | def filled_lineage(self):
method lowest_lineage_name (line 172) | def lowest_lineage_name(self):
method lowest_lineage_taxid (line 179) | def lowest_lineage_taxid(self):
method _init_empty (line 185) | def _init_empty(self):
method _init_from_lineage_tuples (line 194) | def _init_from_lineage_tuples(self):
method _init_from_lineage_str (line 220) | def _init_from_lineage_str(self):
method zip_lineage (line 236) | def zip_lineage(self, truncate_empty=False):
method zip_taxid (line 250) | def zip_taxid(self, truncate_empty=False):
method display_lineage (line 263) | def display_lineage(self, truncate_empty=True, null_as_unclassified=Fa...
method display_taxid (line 271) | def display_taxid(self, truncate_empty=True, sep=";"):
method check_rank_availability (line 275) | def check_rank_availability(self, rank):
method rank_is_filled (line 280) | def rank_is_filled(self, rank, other=None):
method is_compatible (line 289) | def is_compatible(self, other):
method is_lineage_match (line 294) | def is_lineage_match(self, other, rank):
method pop_to_rank (line 312) | def pop_to_rank(self, rank):
method lineage_at_rank (line 325) | def lineage_at_rank(self, rank):
method find_lca (line 335) | def find_lca(self, other):
class RankLineageInfo (line 347) | class RankLineageInfo(BaseLineageInfo):
method __post_init__ (line 370) | def __post_init__(self):
method _init_from_lineage_dict (line 384) | def _init_from_lineage_dict(self):
class ICTVRankLineageInfo (line 435) | class ICTVRankLineageInfo(RankLineageInfo):
method __post_init__ (line 461) | def __post_init__(self):
method _init_from_lineage_dict (line 473) | def _init_from_lineage_dict(self):
class LINLineageInfo (line 508) | class LINLineageInfo(BaseLineageInfo):
method __post_init__ (line 534) | def __post_init__(self):
method __eq__ (line 544) | def __eq__(self, other):
method _init_ranks_from_n_lin_positions (line 556) | def _init_ranks_from_n_lin_positions(self):
method _init_empty (line 560) | def _init_empty(self):
method _init_from_lineage_str (line 575) | def _init_from_lineage_str(self):
method _init_from_lineage_tuples (line 605) | def _init_from_lineage_tuples(self):
method is_compatible (line 625) | def is_compatible(self, other):
class LineageTree (line 642) | class LineageTree:
method __post_init__ (line 651) | def __post_init__(self):
method add_lineage (line 655) | def add_lineage(self, lineage):
method add_lineages (line 669) | def add_lineages(self, lineages):
method find_lca (line 679) | def find_lca(self):
method ordered_paths (line 698) | def ordered_paths(self, include_internal=False):
function get_ident (line 726) | def get_ident(ident, *, keep_full_identifiers=False, keep_identifier_ver...
function ascending_taxlist (line 737) | def ascending_taxlist(include_strain=True):
function collect_gather_csvs (line 755) | def collect_gather_csvs(cmdline_gather_input, *, from_file=None):
function read_lingroups (line 777) | def read_lingroups(lingroup_csv):
function parse_lingroups (line 801) | def parse_lingroups(lingroupD):
function load_gather_results (line 815) | def load_gather_results(
function check_and_load_gather_csvs (line 891) | def check_and_load_gather_csvs(
function report_missing_and_skipped_identities (line 960) | def report_missing_and_skipped_identities(gather_results):
function aggregate_by_lineage_at_rank (line 988) | def aggregate_by_lineage_at_rank(
function format_for_krona (line 1027) | def format_for_krona(
function write_krona (line 1088) | def write_krona(header, krona_results, out_fp, *, sep="\t"):
function write_output (line 1101) | def write_output(header, results, out_fp, *, sep=",", write_header=True):
function write_bioboxes (line 1113) | def write_bioboxes(header_lines, results, out_fp, *, sep="\t"):
function write_summary (line 1129) | def write_summary(
function write_human_summary (line 1157) | def write_human_summary(
function write_lineage_sample_frac (line 1203) | def write_lineage_sample_frac(sample_names, lineage_dict, out_fp, *, sep...
class LineageDB (line 1242) | class LineageDB(abc.Mapping):
method __init__ (line 1245) | def __init__(self, assign_d, avail_ranks):
method __getitem__ (line 1249) | def __getitem__(self, ident):
method __iter__ (line 1253) | def __iter__(self):
method __len__ (line 1257) | def __len__(self):
method __bool__ (line 1261) | def __bool__(self):
method load (line 1266) | def load(
method load_from_gather_with_lineages (line 1412) | def load_from_gather_with_lineages(
class LineageDB_Sqlite (line 1487) | class LineageDB_Sqlite(abc.Mapping):
method __init__ (line 1505) | def __init__(self, conn, *, table_name=None):
method load (line 1536) | def load(cls, location):
method _make_tup (line 1567) | def _make_tup(self, row):
method __getitem__ (line 1572) | def __getitem__(self, ident):
method __bool__ (line 1592) | def __bool__(self):
method __len__ (line 1596) | def __len__(self):
method __iter__ (line 1603) | def __iter__(self):
method items (line 1612) | def items(self):
class MultiLineageDB (line 1624) | class MultiLineageDB(abc.Mapping):
method __init__ (line 1630) | def __init__(self):
method available_ranks (line 1634) | def available_ranks(self):
method add (line 1642) | def add(self, db):
method __iter__ (line 1646) | def __iter__(self):
method items (line 1655) | def items(self):
method shadowed_identifiers (line 1664) | def shadowed_identifiers(self):
method __getitem__ (line 1675) | def __getitem__(self, ident):
method __len__ (line 1684) | def __len__(self):
method __bool__ (line 1690) | def __bool__(self):
method save (line 1694) | def save(self, filename_or_fp, file_format):
method _save_sqlite (line 1725) | def _save_sqlite(self, filename, *, conn=None):
method _save_csv (line 1781) | def _save_csv(self, fp):
method load (line 1801) | def load(cls, locations, **kwargs):
function filter_row (line 1842) | def filter_row(row, dataclass_type):
class GatherRow (line 1857) | class GatherRow:
class QueryInfo (line 1895) | class QueryInfo:
method __post_init__ (line 1907) | def __post_init__(self):
method total_weighted_bp (line 1918) | def total_weighted_bp(self):
class BaseTaxResult (line 1923) | class BaseTaxResult:
method get_ident (line 1938) | def get_ident(self, id_col=None):
method get_match_lineage (line 1954) | def get_match_lineage(
class AnnotateTaxResult (line 1978) | class AnnotateTaxResult(BaseTaxResult):
method __post_init__ (line 1985) | def __post_init__(self):
method row_with_lineages (line 1994) | def row_with_lineages(self):
class TaxResult (line 2002) | class TaxResult(BaseTaxResult):
method __post_init__ (line 2032) | def __post_init__(self):
class SummarizedGatherResult (line 2058) | class SummarizedGatherResult:
method __post_init__ (line 2073) | def __post_init__(self):
method check_values (line 2076) | def check_values(self):
method set_query_ani (line 2089) | def set_query_ani(self, query_info):
method as_lineage_dict (line 2098) | def as_lineage_dict(self, query_info, ranks):
method as_summary_dict (line 2111) | def as_summary_dict(self, query_info, limit_float=False, lingroups=None):
method as_human_friendly_dict (line 2139) | def as_human_friendly_dict(self, query_info):
method as_kreport_dict (line 2149) | def as_kreport_dict(self, query_info, *, use_abund=True):
method as_lingroup_dict (line 2188) | def as_lingroup_dict(self, query_info, lg_name):
method as_cami_bioboxes (line 2202) | def as_cami_bioboxes(self):
class ClassificationResult (line 2227) | class ClassificationResult(SummarizedGatherResult):
method __post_init__ (line 2241) | def __post_init__(self):
method set_status (line 2246) | def set_status(self, query_info, containment_threshold=None, ani_thres...
method build_krona_result (line 2263) | def build_krona_result(self, rank=None):
class QueryTaxResult (line 2283) | class QueryTaxResult:
method __post_init__ (line 2298) | def __post_init__(self):
method _init_taxresult_vars (line 2304) | def _init_taxresult_vars(self):
method _init_summarization_vars (line 2313) | def _init_summarization_vars(self):
method _init_summarization_results (line 2320) | def _init_summarization_results(self):
method _init_classification_results (line 2326) | def _init_classification_results(self):
method is_compatible (line 2334) | def is_compatible(self, taxresult):
method ascending_ranks (line 2342) | def ascending_ranks(self):
method add_taxresult (line 2348) | def add_taxresult(self, taxresult):
method summarize_up_ranks (line 2369) | def summarize_up_ranks(self, single_rank=None, force_resummarize=False):
method build_summarized_result (line 2421) | def build_summarized_result(self, single_rank=None, force_resummarize=...
method build_classification_result (line 2490) | def build_classification_result(
method make_krona_header (line 2577) | def make_krona_header(self, min_rank):
method check_classification (line 2587) | def check_classification(self):
method check_summarization (line 2591) | def check_summarization(self):
method make_human_summary (line 2595) | def make_human_summary(self, display_rank, classification=False):
method make_full_summary (line 2609) | def make_full_summary(
method make_kreport_results (line 2687) | def make_kreport_results(self, *, use_abund=True):
method make_lingroup_results (line 2773) | def make_lingroup_results(
method make_cami_bioboxes (line 2819) | def make_cami_bioboxes(self):
FILE: src/sourmash/utils.py
class RustObject (line 9) | class RustObject:
method __init__ (line 14) | def __init__(self):
method _from_objptr (line 18) | def _from_objptr(cls, ptr, shared=False):
method _methodcall (line 24) | def _methodcall(self, func, *args):
method _get_objptr (line 27) | def _get_objptr(self):
method __del__ (line 32) | def __del__(self):
function decode_str (line 41) | def decode_str(s):
function encode_str (line 52) | def encode_str(s):
function rustcall (line 65) | def rustcall(func, *args):
FILE: tests/conftest.py
function cli_v4_and_v5 (line 18) | def cli_v4_and_v5(request):
function cli_v4_only (line 24) | def cli_v4_only(request):
function cli_v5_only (line 30) | def cli_v5_only(request):
function runtmp (line 35) | def runtmp():
function runtmp_session (line 41) | def runtmp_session():
function run (line 47) | def run():
function track_abundance (line 52) | def track_abundance(request):
function dayhoff (line 57) | def dayhoff(request):
function hp (line 62) | def hp(request):
function keep_identifiers (line 67) | def keep_identifiers(request):
function keep_versions (line 72) | def keep_versions(request):
function n_children (line 77) | def n_children(request):
function linear_gather (line 82) | def linear_gather(request):
function prefetch_gather (line 87) | def prefetch_gather(request):
function disk_index_type (line 92) | def disk_index_type(request):
function use_manifest (line 97) | def use_manifest(request):
function lca_db_format (line 102) | def lca_db_format(request):
function manifest_db_format (line 107) | def manifest_db_format(request):
function sig_save_extension (line 112) | def sig_save_extension(request):
function sig_save_extension_abund (line 117) | def sig_save_extension_abund(request):
function abspath_or_relpath (line 124) | def abspath_or_relpath(request):
function abspath_relpath_v4 (line 132) | def abspath_relpath_v4(request):
function pytest_collection_modifyitems (line 138) | def pytest_collection_modifyitems(items, config):
function pytest_addoption (line 156) | def pytest_addoption(parser):
function pytest_runtest_setup (line 169) | def pytest_runtest_setup(item):
FILE: tests/sourmash_tst_utils.py
function scriptpath (line 32) | def scriptpath(scriptname="sourmash"):
function _runscript (line 50) | def _runscript(scriptname):
function runscript (line 78) | def runscript(scriptname, args, **kwargs):
function get_test_data (line 141) | def get_test_data(filename):
class TempDirectory (line 148) | class TempDirectory:
method __init__ (line 149) | def __init__(self):
method __enter__ (line 152) | def __enter__(self):
method __exit__ (line 155) | def __exit__(self, exc_type, exc_value, traceback):
class SourmashCommandFailed (line 165) | class SourmashCommandFailed(Exception):
method __init__ (line 166) | def __init__(self, msg):
class RunnerContext (line 171) | class RunnerContext:
method __init__ (line 182) | def __init__(self, location):
method run_sourmash (line 187) | def run_sourmash(self, *args, **kwargs):
method run (line 220) | def run(self, scriptname, *args, **kwargs):
method output (line 228) | def output(self, path):
method __str__ (line 231) | def __str__(self):
function in_tempdir (line 250) | def in_tempdir(fn):
function in_thisdir (line 260) | def in_thisdir(fn):
FILE: tests/test__minhash_hypothesis.py
function test_set_abundance_num_hypothesis (line 16) | def test_set_abundance_num_hypothesis(hashes, abundances, sketch_size):
function test_set_abundance_scaled_hypothesis (line 36) | def test_set_abundance_scaled_hypothesis(hashes, abundances, scaled):
FILE: tests/test_api.py
function test_sourmash_signature_api (line 9) | def test_sourmash_signature_api(c):
function test_load_index_0_no_file (line 24) | def test_load_index_0_no_file(c):
function test_load_index_1 (line 30) | def test_load_index_1():
function test_load_index_2 (line 38) | def test_load_index_2():
function test_load_index_3 (line 46) | def test_load_index_3():
function test_load_index_4 (line 54) | def test_load_index_4():
function test_load_index_4_b (line 62) | def test_load_index_4_b():
function test_load_fasta_as_signature (line 70) | def test_load_fasta_as_signature():
function test_load_and_search_sbt_api (line 85) | def test_load_and_search_sbt_api():
FILE: tests/test_bugs.py
function test_bug_803 (line 5) | def test_bug_803(c):
FILE: tests/test_cmd_index.py
function _index_filename (line 16) | def _index_filename(prefix, index_type):
function test_index_signatures (line 27) | def test_index_signatures(runtmp, disk_index_type):
function test_search_metagenome (line 53) | def test_search_metagenome(runtmp, disk_index_type):
function test_search_metagenome_index_downsample_fail (line 82) | def test_search_metagenome_index_downsample_fail(runtmp, disk_index_type):
function test_search_metagenome_downsample_containment (line 116) | def test_search_metagenome_downsample_containment(runtmp, disk_index_type):
function test_search_metagenome_downsample_index (line 152) | def test_search_metagenome_downsample_index(runtmp, disk_index_type):
function test_gather (line 201) | def test_gather(runtmp, linear_gather, prefetch_gather, disk_index_type):
function test_gather_metagenome (line 240) | def test_gather_metagenome(runtmp, disk_index_type):
function test_gather_metagenome_num_results (line 274) | def test_gather_metagenome_num_results(runtmp, disk_index_type):
function test_gather_metagenome_threshold_bp (line 309) | def test_gather_metagenome_threshold_bp(
function test_gather_metagenome_threshold_bp_low (line 350) | def test_gather_metagenome_threshold_bp_low(
function test_gather_metagenome_threshold_bp_too_high (line 385) | def test_gather_metagenome_threshold_bp_too_high(
function test_gather_metagenome_abund (line 420) | def test_gather_metagenome_abund(runtmp, disk_index_type):
function test_gather_metagenome_downsample (line 444) | def test_gather_metagenome_downsample(
function test_gather_save_matches (line 492) | def test_gather_save_matches(runtmp, linear_gather, prefetch_gather, dis...
function test_gather_save_matches_and_save_prefetch (line 528) | def test_gather_save_matches_and_save_prefetch(runtmp, linear_gather, di...
function test_gather_metagenome_picklist (line 572) | def test_gather_metagenome_picklist(runtmp, disk_index_type):
function test_index_best_containment_threshold_1 (line 612) | def test_index_best_containment_threshold_1(runtmp, disk_index_type):
function test_index_best_containment_threshold_5 (line 668) | def test_index_best_containment_threshold_5(runtmp, disk_index_type):
function test_gather_single_return (line 709) | def test_gather_single_return(runtmp, disk_index_type):
function test_sbt_jaccard_ordering (line 739) | def test_sbt_jaccard_ordering(runtmp, disk_index_type):
function test_index_protein (line 793) | def test_index_protein(runtmp, disk_index_type):
function test_index_protein_search_no_threshold (line 846) | def test_index_protein_search_no_threshold(runtmp, disk_index_type):
function test_index_protein_command_search (line 881) | def test_index_protein_command_search(runtmp, disk_index_type):
function test_index_hp_command_index (line 900) | def test_index_hp_command_index(runtmp, disk_index_type):
function test_index_hp_command_search (line 952) | def test_index_hp_command_search(runtmp, disk_index_type):
function test_index_dayhoff_command_index (line 970) | def test_index_dayhoff_command_index(runtmp, disk_index_type):
function test_index_dayhoff_command_search (line 1022) | def test_index_dayhoff_command_search(runtmp, disk_index_type):
function test_index_skipm1n3_command_search (line 1040) | def test_index_skipm1n3_command_search(runtmp, disk_index_type):
function test_index_skipm2n3_command_search (line 1088) | def test_index_skipm2n3_command_search(runtmp, disk_index_type):
FILE: tests/test_cmd_signature.py
function _write_file (line 29) | def _write_file(runtmp, basename, lines, *, gz=False):
function test_run_sourmash_signature_cmd (line 41) | def test_run_sourmash_signature_cmd():
function test_run_sourmash_sig_cmd (line 48) | def test_run_sourmash_sig_cmd():
function test_run_cat_via_parse_args (line 55) | def test_run_cat_via_parse_args():
function test_sig_merge_1_use_full_signature_in_cmd (line 66) | def test_sig_merge_1_use_full_signature_in_cmd(runtmp):
function test_sig_merge_1_fromfile_picklist (line 88) | def test_sig_merge_1_fromfile_picklist(runtmp):
function test_sig_merge_1_fromfile_picklist_gz (line 121) | def test_sig_merge_1_fromfile_picklist_gz(runtmp):
function test_sig_merge_1 (line 158) | def test_sig_merge_1(c):
function test_sig_merge_1_multisig (line 179) | def test_sig_merge_1_multisig(c):
function test_sig_merge_1_name (line 199) | def test_sig_merge_1_name(c):
function test_sig_merge_1_ksize_moltype (line 230) | def test_sig_merge_1_ksize_moltype(c):
function test_sig_merge_1_ksize_moltype_fail (line 251) | def test_sig_merge_1_ksize_moltype_fail(c):
function test_sig_merge_2 (line 264) | def test_sig_merge_2(c):
function test_sig_merge_3_abund_ab_ok (line 281) | def test_sig_merge_3_abund_ab_ok(c):
function test_sig_merge_3_abund_ab (line 292) | def test_sig_merge_3_abund_ab(c):
function test_sig_merge_3_abund_ba (line 308) | def test_sig_merge_3_abund_ba(c):
function test_sig_filter_1 (line 324) | def test_sig_filter_1(c):
function test_sig_filter_2 (line 348) | def test_sig_filter_2(c):
function test_sig_filter_3 (line 367) | def test_sig_filter_3(c):
function test_sig_filter_3_ksize_select (line 386) | def test_sig_filter_3_ksize_select(c):
function test_sig_merge_flatten (line 405) | def test_sig_merge_flatten(c):
function test_sig_merge_flatten_2 (line 427) | def test_sig_merge_flatten_2(c):
function test_sig_intersect_0 (line 448) | def test_sig_intersect_0(runtmp):
function test_sig_intersect_1 (line 459) | def test_sig_intersect_1(runtmp):
function test_sig_intersect_1_rename (line 481) | def test_sig_intersect_1_rename(runtmp):
function test_sig_intersect_1_fromfile_picklist (line 502) | def test_sig_intersect_1_fromfile_picklist(runtmp):
function test_sig_intersect_2 (line 536) | def test_sig_intersect_2(c):
function test_sig_intersect_3 (line 558) | def test_sig_intersect_3(c):
function test_sig_intersect_4 (line 590) | def test_sig_intersect_4(c):
function test_sig_intersect_5 (line 622) | def test_sig_intersect_5(c):
function test_sig_intersect_6_ksize_fail (line 633) | def test_sig_intersect_6_ksize_fail(c):
function test_sig_intersect_6_ksize_succeed (line 644) | def test_sig_intersect_6_ksize_succeed(c):
function test_sig_intersect_7 (line 656) | def test_sig_intersect_7(c):
function test_sig_intersect_8_multisig (line 675) | def test_sig_intersect_8_multisig(c):
function test_sig_inflate_1 (line 688) | def test_sig_inflate_1(runtmp):
function test_sig_inflate_2 (line 708) | def test_sig_inflate_2(runtmp):
function test_sig_inflate_3 (line 739) | def test_sig_inflate_3(runtmp):
function test_sig_inflate_4_picklist (line 750) | def test_sig_inflate_4_picklist(runtmp):
function test_sig_inflate_5_bad_moltype (line 791) | def test_sig_inflate_5_bad_moltype(runtmp):
function test_sig_subtract_1 (line 802) | def test_sig_subtract_1(runtmp):
function test_sig_subtract_1_name (line 822) | def test_sig_subtract_1_name(runtmp):
function test_sig_subtract_1_sigzip (line 842) | def test_sig_subtract_1_sigzip(runtmp):
function test_sig_subtract_1_sigzip (line 864) | def test_sig_subtract_1_sigzip(runtmp):
function test_sig_subtract_1_abund (line 886) | def test_sig_subtract_1_abund(runtmp):
function test_sig_subtract_1_abund_is_flat (line 919) | def test_sig_subtract_1_abund_is_flat(runtmp):
function test_sig_subtract_1_flatten (line 931) | def test_sig_subtract_1_flatten(runtmp):
function test_sig_subtract_1_multisig (line 953) | def test_sig_subtract_1_multisig(runtmp):
function test_sig_subtract_2 (line 968) | def test_sig_subtract_2(runtmp):
function test_sig_subtract_3 (line 978) | def test_sig_subtract_3(runtmp):
function test_sig_subtract_4_ksize_fail (line 988) | def test_sig_subtract_4_ksize_fail(runtmp):
function test_sig_subtract_4_ksize_succeed (line 998) | def test_sig_subtract_4_ksize_succeed(runtmp):
function test_sig_subtract_5_bad_moltype (line 1008) | def test_sig_subtract_5_bad_moltype(runtmp):
function test_sig_rename_1 (line 1019) | def test_sig_rename_1(runtmp):
function test_sig_rename_1_fromfile_picklist (line 1040) | def test_sig_rename_1_fromfile_picklist(runtmp):
function test_sig_rename_1_multisig (line 1074) | def test_sig_rename_1_multisig(c):
function test_sig_rename_1_multisig_ksize (line 1092) | def test_sig_rename_1_multisig_ksize(c):
function test_sig_rename_2_output_to_same (line 1110) | def test_sig_rename_2_output_to_same(c):
function test_sig_rename_3_file_dne (line 1125) | def test_sig_rename_3_file_dne(c):
function test_sig_rename_3_file_dne_force (line 1134) | def test_sig_rename_3_file_dne_force(c):
function test_sig_rename_4_pattern_include (line 1142) | def test_sig_rename_4_pattern_include(runtmp):
function test_sig_rename_4_pattern_exclude (line 1156) | def test_sig_rename_4_pattern_exclude(runtmp):
function test_sig_cat_1 (line 1171) | def test_sig_cat_1(c):
function test_sig_cat_1_no_unique (line 1186) | def test_sig_cat_1_no_unique(c):
function test_sig_cat_1_unique (line 1205) | def test_sig_cat_1_unique(c):
function test_sig_cat_2 (line 1226) | def test_sig_cat_2(c):
function test_sig_cat_2_out (line 1246) | def test_sig_cat_2_out(c):
function test_sig_cat_2_out_inplace (line 1266) | def test_sig_cat_2_out_inplace(c):
function test_sig_cat_3_filelist (line 1291) | def test_sig_cat_3_filelist(c):
function test_sig_cat_4_filelist_with_dbs (line 1330) | def test_sig_cat_4_filelist_with_dbs(c):
function test_sig_cat_5_from_file (line 1369) | def test_sig_cat_5_from_file(c):
function test_sig_cat_5_from_file_picklist (line 1407) | def test_sig_cat_5_from_file_picklist(runtmp):
function test_sig_cat_6_pattern_include (line 1455) | def test_sig_cat_6_pattern_include(runtmp):
function test_sig_cat_6_pattern_exclude (line 1468) | def test_sig_cat_6_pattern_exclude(runtmp):
function test_sig_cat_6_pattern_exclude_no_manifest (line 1481) | def test_sig_cat_6_pattern_exclude_no_manifest(runtmp):
function test_sig_split_1 (line 1491) | def test_sig_split_1(runtmp):
function test_sig_split_1_fromfile_picklist (line 1507) | def test_sig_split_1_fromfile_picklist(runtmp):
function test_sig_split_1_overwrite (line 1535) | def test_sig_split_1_overwrite(c):
function test_sig_split_2 (line 1551) | def test_sig_split_2(c):
function test_sig_split_2_outdir (line 1572) | def test_sig_split_2_outdir(c):
function test_sig_split_2_output_dir (line 1594) | def test_sig_split_2_output_dir(c):
function test_sig_split_3_multisig (line 1616) | def test_sig_split_3_multisig(c):
function test_sig_split_3_multisig_sig_gz (line 1634) | def test_sig_split_3_multisig_sig_gz(runtmp):
function test_sig_split_3_multisig_zip (line 1654) | def test_sig_split_3_multisig_zip(runtmp):
function test_sig_split_4_sbt_prot (line 1675) | def test_sig_split_4_sbt_prot(c):
function test_sig_split_4_lca_prot (line 1695) | def test_sig_split_4_lca_prot(c):
function test_sig_split_5_no_exist (line 1718) | def test_sig_split_5_no_exist(c):
function test_sig_split_6_numsigs (line 1724) | def test_sig_split_6_numsigs(runtmp):
function test_sig_extract_1 (line 1744) | def test_sig_extract_1(runtmp):
function test_sig_extract_1_from_file (line 1760) | def test_sig_extract_1_from_file(runtmp):
function test_sig_extract_2 (line 1778) | def test_sig_extract_2(runtmp):
function test_sig_extract_2_zipfile (line 1798) | def test_sig_extract_2_zipfile(runtmp):
function test_sig_extract_3 (line 1819) | def test_sig_extract_3(runtmp):
function test_sig_extract_4 (line 1828) | def test_sig_extract_4(runtmp):
function test_sig_extract_5 (line 1848) | def test_sig_extract_5(runtmp):
function test_sig_extract_5_to_zip (line 1857) | def test_sig_extract_5_to_zip(runtmp):
function test_sig_extract_6 (line 1871) | def test_sig_extract_6(runtmp):
function test_sig_extract_7 (line 1888) | def test_sig_extract_7(runtmp):
function test_sig_extract_7_no_ksize (line 1904) | def test_sig_extract_7_no_ksize(runtmp):
function test_sig_extract_8_empty_picklist_fail (line 1920) | def test_sig_extract_8_empty_picklist_fail(runtmp):
function test_sig_extract_8_nofile_picklist_fail (line 1941) | def test_sig_extract_8_nofile_picklist_fail(runtmp):
function test_sig_extract_8_picklist_md5 (line 1959) | def test_sig_extract_8_picklist_md5(runtmp):
function test_sig_extract_8_picklist_md5_zipfile (line 2000) | def test_sig_extract_8_picklist_md5_zipfile(runtmp):
function test_sig_extract_8_picklist_md5_lca_fail (line 2042) | def test_sig_extract_8_picklist_md5_lca_fail(runtmp):
function test_sig_extract_8_picklist_md5_include (line 2084) | def test_sig_extract_8_picklist_md5_include(runtmp):
function test_sig_extract_8_picklist_md5_exclude (line 2125) | def test_sig_extract_8_picklist_md5_exclude(runtmp):
function test_sig_extract_8_picklist_md5_require_all (line 2166) | def test_sig_extract_8_picklist_md5_require_all(runtmp):
function test_sig_extract_8_picklist_name (line 2228) | def test_sig_extract_8_picklist_name(runtmp):
function test_sig_extract_8_picklist_name_exclude (line 2261) | def test_sig_extract_8_picklist_name_exclude(runtmp):
function test_sig_extract_8_picklist_ident (line 2294) | def test_sig_extract_8_picklist_ident(runtmp):
function test_sig_extract_8_picklist_ident_exclude (line 2327) | def test_sig_extract_8_picklist_ident_exclude(runtmp):
function test_sig_extract_8_picklist_ident_dot (line 2360) | def test_sig_extract_8_picklist_ident_dot(runtmp):
function test_sig_extract_8_picklist_ident_dot_exclude (line 2393) | def test_sig_extract_8_picklist_ident_dot_exclude(runtmp):
function test_sig_extract_8_picklist_md5_short (line 2426) | def test_sig_extract_8_picklist_md5_short(runtmp):
function test_sig_extract_8_picklist_md5_short_exclude (line 2459) | def test_sig_extract_8_picklist_md5_short_exclude(runtmp):
function test_sig_extract_8_picklist_md5_short_alias (line 2492) | def test_sig_extract_8_picklist_md5_short_alias(runtmp):
function test_sig_extract_8_picklist_md5_short_alias_exclude (line 2525) | def test_sig_extract_8_picklist_md5_short_alias_exclude(runtmp):
function test_sig_extract_8_picklist_md5_short_alia
Copy disabled (too large)
Download .json
Condensed preview — 707 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (11,692K chars).
[
{
"path": ".cargo/config.toml",
"chars": 170,
"preview": "[target.x86_64-unknown-linux-musl]\nrustflags = [\"-C\", \"target-feature=-crt-static\"]\n\n[target.aarch64-unknown-linux-musl]"
},
{
"path": ".envrc",
"chars": 83,
"preview": "#use flake\n\nPATH=~/.pixi/bin:$PATH\n\nwatch_file pixi.lock\neval \"$(pixi shell-hook)\"\n"
},
{
"path": ".git-blame-ignore-revs",
"chars": 70,
"preview": "# Pre-commit updates (#2427)\nfee62922d8857ce93f1d4e90fd7240629d606997\n"
},
{
"path": ".git_archival.txt",
"chars": 23,
"preview": "ref-names: $Format:%D$\n"
},
{
"path": ".gitattributes",
"chars": 282,
"preview": ".git_archival.txt export-subst\ntests/test-data/*.sig linguist-detectable=false\ntests/test-data/*/*.sig linguist-detec"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 675,
"preview": "Please replace this text with:\n\n* a brief description of your changes in this PR\n* which issues this fixes in the issue "
},
{
"path": ".github/dependabot.yml",
"chars": 824,
"preview": "version: 2\nupdates:\n- package-ecosystem: pip\n directory: \"/\"\n schedule:\n interval: weekly\n open-pull-requests-limi"
},
{
"path": ".github/workflows/asv.yml",
"chars": 763,
"preview": "name: asv benchmarks\n\npermissions:\n contents: read\n\non:\n push:\n branches: [latest]\n pull_request:\n merge_group:\n "
},
{
"path": ".github/workflows/build_wheel.yml",
"chars": 2607,
"preview": "name: cibuildwheel\npermissions:\n contents: write\n\non:\n push:\n branches: [latest]\n tags: v*\n pull_request:\n mer"
},
{
"path": ".github/workflows/build_wheel_all_archs.yml",
"chars": 2090,
"preview": "name: maturin wheels\npermissions:\n contents: write\n\non:\n pull_request: # use for testing modifications to this "
},
{
"path": ".github/workflows/codspeed.yml",
"chars": 998,
"preview": "name: codspeed-benchmarks\n\npermissions:\n contents: read\n\non:\n # Run on pushes to the main branch\n push:\n branches:"
},
{
"path": ".github/workflows/dev_envs.yml",
"chars": 1880,
"preview": "name: \"Dev env instructions\"\non:\n pull_request:\n merge_group:\n push:\n branches: [latest]\nconcurrency:\n group: ${{"
},
{
"path": ".github/workflows/draft-pdf.yml",
"chars": 689,
"preview": "on: [push]\n\npermissions:\n contents: read\n\njobs:\n paper:\n runs-on: ubuntu-latest\n name: Paper Draft\n steps:\n "
},
{
"path": ".github/workflows/hypothesis.yml",
"chars": 811,
"preview": "name: Hypothesis tests\n\npermissions:\n contents: read\n\non:\n push:\n branches: [latest]\n pull_request:\n merge_group:"
},
{
"path": ".github/workflows/metadata.yml",
"chars": 531,
"preview": "name: Metadata checks \n\npermissions:\n contents: read\n\non:\n push:\n branches: [latest]\n pull_request:\n merge_group:"
},
{
"path": ".github/workflows/python.yml",
"chars": 2210,
"preview": "# note: to invalidate caches, adjust the pip-v? number below.\nname: Python tests\n\non:\n push:\n branches: [latest]\n p"
},
{
"path": ".github/workflows/rust.yml",
"chars": 9289,
"preview": "name: Rust checks\n\non:\n push:\n branches: [latest]\n tags:\n - 'r*'\n pull_request:\n merge_group:\n schedule:\n"
},
{
"path": ".gitignore",
"chars": 369,
"preview": "*~\n*.fa\n*.fastq.gz\n*.abundtrim\n*.keep\n*.pyc\n*.sig\n*.png\n*.labels.txt\ndistances\n*.npy\ndist\nbuild\nsourmash.egg-info\n.ipynb"
},
{
"path": ".pre-commit-config.yaml",
"chars": 713,
"preview": "repos:\n - repo: https://github.com/pre-commit/pre-commit-hooks\n rev: v6.0.0\n hooks:\n - id: check-ast\n -"
},
{
"path": ".readthedocs.yml",
"chars": 463,
"preview": "# .readthedocs.yml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html fo"
},
{
"path": ".sonarcloud.properties",
"chars": 1,
"preview": "\n"
},
{
"path": ".zenodo.json",
"chars": 2175,
"preview": "{\"creators\": [{\"name\": \"Luiz Irber\", \"orcid\": \"0000-0003-4371-9659\"}, {\"name\": \"N. Tessa Pierce-Ward\", \"orcid\": \"0000-00"
},
{
"path": "CITATION.cff",
"chars": 6478,
"preview": "cff-version: \"1.2.0\"\nauthors:\n- family-names: Irber\n given-names: Luiz\n orcid: \"https://orcid.org/0000-0003-4371-9659\""
},
{
"path": "CODE_OF_CONDUCT.rst",
"chars": 1663,
"preview": "Contributor Code of Conduct\n===========================\n\nAs contributors and maintainers of this project, we pledge to r"
},
{
"path": "CONTRIBUTING.md",
"chars": 349,
"preview": "We welcome contributions! We use\n[GitHub Flow style development](https://guides.github.com/introduction/flow/).\nPlease "
},
{
"path": "Cargo.toml",
"chars": 116,
"preview": "[workspace]\nmembers = [\n \"src/core\",\n]\ndefault-members = [\"src/core\"]\nresolver = \"2\"\n\n[profile.test]\nopt-level = 1\n"
},
{
"path": "LICENSE",
"chars": 1889,
"preview": "=======\nLicense\n=======\n\nFiles: *\nCopyright: 2016, The Regents of the University of California.\nLicense: BSD-3-Clause\n R"
},
{
"path": "MANIFEST.in",
"chars": 238,
"preview": "include LICENSE Makefile README.md requirements.txt\ninclude Cargo.toml\ninclude include/sourmash.h\nprune .eggs\nglobal-exc"
},
{
"path": "Makefile",
"chars": 1490,
"preview": "PYTHON ?= python\n\nall: build\n\n.PHONY:\n\nbuild: .PHONY\n\t$(PYTHON) -m pip install -e .\n\nclean:\n\t$(PYTHON) -m pip uninstall "
},
{
"path": "README.md",
"chars": 6262,
"preview": "# sourmash\n\nQuickly search, compare, and analyze genomic and metagenomic data sets.\n\n[)\n\nThe code in here is run by "
},
{
"path": "benchmarks/__init__.py",
"chars": 1,
"preview": "\n"
},
{
"path": "benchmarks/benchmarks.py",
"chars": 6360,
"preview": "import random\nfrom tempfile import NamedTemporaryFile\n\nfrom sourmash.sbt_storage import ZipStorage\nfrom sourmash.minhash"
},
{
"path": "binder/README.md",
"chars": 78,
"preview": "# binder directory\n\nConfiguration files for [mybinder](https://mybinder.org).\n"
},
{
"path": "binder/environment.yml",
"chars": 191,
"preview": "channels:\n - conda-forge\n - bioconda\n - defaults\ndependencies:\n - python>=3.11\n - sourmash>=4.8.11\n - screed\n - m"
},
{
"path": "codecov.yml",
"chars": 311,
"preview": "# config file for codecov, https://app.codecov.io/gh/sourmash-bio/sourmash/\n\n# use path fixing to properly report code c"
},
{
"path": "codemeta.json",
"chars": 516,
"preview": "{\n \"@context\": \"https://raw.githubusercontent.com/mbjones/codemeta/master/codemeta.jsonld\",\n \"@type\": \"Code\",\n \"autho"
},
{
"path": "data/README.md",
"chars": 316,
"preview": "# The data subdir\n\nData files for various and sundry purposes.\n\nThe following files are used by the doctests in doc/ & m"
},
{
"path": "default.nix",
"chars": 259,
"preview": "(import\n (\n fetchTarball {\n url = \"https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0"
},
{
"path": "deny.toml",
"chars": 1024,
"preview": "all-features = true\nfeature-depth = 1\n\n[advisories]\ndb-path = \"~/.cargo/advisory-db\"\ndb-urls = [\"https://github.com/rust"
},
{
"path": "dev.yml",
"chars": 243,
"preview": "name: sourmash_dev\nchannels:\n - conda-forge\ndependencies:\n - clangdev >=16.0.6,<16.1\n - cxx-compiler >=1.7.0,<1.8\n -"
},
{
"path": "doc/Makefile",
"chars": 8085,
"preview": "# Makefile for Sphinx documentation\n#\n\nall: html\n\n# You can set these variables from the command line.\nSPHINXOPTS =\nS"
},
{
"path": "doc/README.md",
"chars": 547,
"preview": "# Documentation on the docs\n\nWe use\n[MyST](https://myst-parser.readthedocs.io/en/latest/sphinx/intro.html)\nto generate S"
},
{
"path": "doc/_static/custom.css",
"chars": 163,
"preview": "div.sphinxsidebar ul {\n list-style-type: disc;\n list-style: disc;\n margin-left: 10px;\n}\n\ndiv.sphinxsidebar ul l"
},
{
"path": "doc/_static/ecoli-cmp.Rmd",
"chars": 1206,
"preview": "---\ntitle: \"Working with matrix output by sourmash compare\"\noutput: html_document\n---\n\n```{r setup, include=FALSE}\nknitr"
},
{
"path": "doc/_static/ecoli-cmp.html",
"chars": 1360669,
"preview": "<!DOCTYPE html>\n\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n\n<meta charset=\"utf-8\" />\n<meta http-equiv=\"Content"
},
{
"path": "doc/_static/ecoli.cmp.csv",
"chars": 51527,
"preview": "\"NZ_JHDG01000001.1 Escherichia coli 1-176-05_S3_C1 e117605S3C1.contig.0_1, whole genome shotgun sequence\",\"NZ_JSMW010000"
},
{
"path": "doc/_templates/.empty",
"chars": 0,
"preview": ""
},
{
"path": "doc/api-example.md",
"chars": 27720,
"preview": "# `sourmash` Python API examples\n\nAll of sourmash's functionality is available via its [Python API](api.md). Below are b"
},
{
"path": "doc/api.md",
"chars": 757,
"preview": "# `sourmash` Python API\n\nThe primary programmatic way of interacting with `sourmash` is via\nits Python API.\n\n**Please al"
},
{
"path": "doc/cite.md",
"chars": 283,
"preview": "# How to cite sourmash\n\nThe primary citation for the sourmash software is:\n\nIrber et al., (2024). sourmash v4: A multito"
},
{
"path": "doc/classifying-signatures.md",
"chars": 33103,
"preview": "# Classifying signatures: `search`, `gather`, and `lca` methods.\n\nsourmash provides several different techniques for doi"
},
{
"path": "doc/command-line.md",
"chars": 114121,
"preview": "# Using sourmash from the command line\n\n```{contents} Contents\n:depth: 3\n```\n\nFrom the command line, sourmash can be use"
},
{
"path": "doc/conf.py",
"chars": 10484,
"preview": "#!/usr/bin/env python3\n#\n# sourmash documentation build configuration file, created by\n# sphinx-quickstart on Sat Jun 4"
},
{
"path": "doc/databases-advanced.md",
"chars": 12581,
"preview": "# sourmash databases - advanced usage information.\n\ntl;dr use `zip` files for heterogeneous collections of sourmash\nsket"
},
{
"path": "doc/databases-md/gtdb220.md",
"chars": 4386,
"preview": "<!-- automatically generated by code in https://github.com/sourmash-bio/2025-sourmash-databases-doc-template/ -->\n<!-- t"
},
{
"path": "doc/databases-md/gtdb226.md",
"chars": 7198,
"preview": "<!-- automatically generated by code in https://github.com/sourmash-bio/2025-sourmash-databases-doc-template/ -->\n<!-- t"
},
{
"path": "doc/databases-md/ncbi_euks_2025_01.md",
"chars": 7822,
"preview": "<!-- automatically generated by code in https://github.com/sourmash-bio/2025-sourmash-databases-doc-template/ -->\n<!-- t"
},
{
"path": "doc/databases-md/ncbi_viruses_2025_01.md",
"chars": 3439,
"preview": "<!-- automatically generated by code in https://github.com/sourmash-bio/2025-sourmash-databases-doc-template/ -->\n<!-- t"
},
{
"path": "doc/databases.md",
"chars": 1213,
"preview": "# Prepared databases\n\n```{contents}\n```\n\n## Modern databases\n\nWe provide a number of pre-built collections and indexed d"
},
{
"path": "doc/dev_plugins.md",
"chars": 3907,
"preview": "# sourmash plugins via Python entry points\n\nAs of version 4.7.0, sourmash has experimental support for Python\nplugins to"
},
{
"path": "doc/developer.md",
"chars": 11391,
"preview": "```{contents} Contents\n:depth: 3\n```\n\n# Developer information\n\n## Development environment\n\nYou can get the latest develo"
},
{
"path": "doc/faq.md",
"chars": 16532,
"preview": "# Frequently Asked Questions (FAQ)\n\n```{contents} Contents\n:depth: 3\n```\n\n## How is sourmash different from mash?\n\n[mash"
},
{
"path": "doc/funding.md",
"chars": 623,
"preview": "# Funding\n\nSourmash development was initiated under award GBMF4551 from the Gordon\nand Betty Moore Foundation to C. Titu"
},
{
"path": "doc/howto-rocksdb.md",
"chars": 3887,
"preview": "# A quickstart guide to using RocksDB indexing\n\nThis quickstart shows how to index the GTDB species representatives data"
},
{
"path": "doc/index.md",
"chars": 6347,
"preview": "# Welcome to sourmash!\n\nsourmash is a command-line tool and Python/Rust library for\n**metagenome analysis** and **genome"
},
{
"path": "doc/kmers-and-minhash.ipynb",
"chars": 80952,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# An introduction to k-mers for gen"
},
{
"path": "doc/legacy-databases.md",
"chars": 22006,
"preview": "# Legacy Databases - 2024 and before\n\n## Types of databases\n\nFor each k-mer size, three types of databases may be availa"
},
{
"path": "doc/more-info.md",
"chars": 5839,
"preview": "# Additional information on sourmash\n\n## Computational requirements\n\nRead more about the [computational requirements, he"
},
{
"path": "doc/other-languages.md",
"chars": 1405,
"preview": "# Using `sourmash` output with R and other languages\n\nMost of the sourmash shell commands output CSV files upon request;"
},
{
"path": "doc/plotting-compare.ipynb",
"chars": 107966,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Building plots from `sourmash com"
},
{
"path": "doc/podar-lineage.csv",
"chars": 9707,
"preview": "accession,taxid,superkingdom,phylum,class,order,family,genus,species,strain\r\nAE000782,224325,Archaea,Euryarchaeota,Archa"
},
{
"path": "doc/publications.md",
"chars": 2817,
"preview": "# Publications\n\nBelow are publications from the sourmash team.\n\n## sourmash fundamentals\n\n[Lightweight compositional ana"
},
{
"path": "doc/release-notes/releases.md",
"chars": 244,
"preview": "# sourmash release notes\n\nPlease see the\n[github releases page](https://github.com/sourmash-bio/sourmash/releases)\nfor d"
},
{
"path": "doc/release-notes/sourmash-2.0.md",
"chars": 2870,
"preview": "# sourmash v2.0 release notes\n\nWe are pleased to announce release 2.0 of sourmash! This release is\nthe first full relea"
},
{
"path": "doc/release-notes/sourmash-3.0.md",
"chars": 2311,
"preview": "# sourmash v3.0 release notes\n\nWe are pleased to announce release 3.0 of sourmash! This release includes internal chang"
},
{
"path": "doc/release-notes/sourmash-4.0.md",
"chars": 3769,
"preview": "# sourmash v4.0 release notes\n\n```{contents}\n :depth: 2\n```\n\nWe are pleased to announce release 4.0 of sourmash! This "
},
{
"path": "doc/release-notes/sourmash-5.0.md",
"chars": 1624,
"preview": "# sourmash v5.0 _draft_ release notes\n\n```{contents}\n :depth: 2\n```\n\nDraft text: We are pleased to announce release 5."
},
{
"path": "doc/release.md",
"chars": 10448,
"preview": "# Releasing a new version of sourmash\n\nThese are adapted from the khmer release docs, originally written by\nMichael Crus"
},
{
"path": "doc/requirements.md",
"chars": 761,
"preview": "# Computational requirements\n\nsourmash has no particular memory requirements; it will need to hold\nthe largest single se"
},
{
"path": "doc/runtime.txt",
"chars": 5,
"preview": "3.11\n"
},
{
"path": "doc/sidebar.md",
"chars": 1904,
"preview": "## Tutorials and examples\n\nThese tutorials are command line tutorials that should work on Mac OS\nX and Linux. They requi"
},
{
"path": "doc/sourmash-collections.ipynb",
"chars": 90073,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# sourmash: working with private co"
},
{
"path": "doc/sourmash-examples.ipynb",
"chars": 33432,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Some sourmash command line exampl"
},
{
"path": "doc/sourmash-internals.md",
"chars": 37783,
"preview": "# A guide to the internal design and structure of sourmash\n\n```{contents} Contents\n:depth: 3\n```\n\nsourmash was created i"
},
{
"path": "doc/sourmash-sketch.md",
"chars": 19781,
"preview": "# `sourmash sketch` documentation\n\n```{contents} Contents\n:depth: 3\n```\n\nMost of the commands in sourmash work with **si"
},
{
"path": "doc/storage.md",
"chars": 1895,
"preview": "# Storing SBTs\n\nWe support different storage options for the internal SBT data.\n\n\n## Available storages\n\n### FSStorage\n\n"
},
{
"path": "doc/support.md",
"chars": 13280,
"preview": "# Support, Versioning, and Migration\n\n```{contents}\n :depth: 3\n```\n\n## Asking questions and filing bugs\n\nWe do our bes"
},
{
"path": "doc/toc.md",
"chars": 685,
"preview": "# Full table of contents\n\n```{toctree}\n---\nmaxdepth: 2\n---\n\napi-example.md\napi.md\ncite.md\nclassifying-signatures.md\ncomm"
},
{
"path": "doc/tutorial-basic.md",
"chars": 9111,
"preview": "# The first sourmash tutorial - making signatures, comparing, and searching\n\nYou'll need about 5 GB of free disk space, "
},
{
"path": "doc/tutorial-install.md",
"chars": 1026,
"preview": "# Installing sourmash\n\nThis tutorial should run without modification on Linux or Mac OS X,\nunder [Miniforge](https://git"
},
{
"path": "doc/tutorial-lemonade.md",
"chars": 21146,
"preview": "# Analyzing the genomic and taxonomic composition of an environmental genome using GTDB and sample-specific MAGs with so"
},
{
"path": "doc/tutorial-lin-taxonomy.md",
"chars": 24261,
"preview": "# Analyzing Metagenome Composition using the LIN taxonomic framework \n\nTessa Pierce Ward\n\nMarch 2023\n\nrequires sourmash"
},
{
"path": "doc/tutorial-long.md",
"chars": 23290,
"preview": "# Quick Insights from Sequencing Data with sourmash\n\nNote: this tutorial was developed for and first presented at\n[ANGUS"
},
{
"path": "doc/tutorials-lca.md",
"chars": 6627,
"preview": "# Using sourmash LCA to do taxonomic classification\n\nThe `sourmash lca` sub-commands do k-mer classification using an\n\"l"
},
{
"path": "doc/tutorials.md",
"chars": 2034,
"preview": "# sourmash tutorials and notebooks\n\n## The first three tutorials!\n\nThese tutorials are command line tutorials that shoul"
},
{
"path": "doc/using-LCA-database-API.ipynb",
"chars": 23882,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"markdown\",\n \"metadata\": {},\n \"source\": [\n \"# Using the `LCA_Database` API\"\n "
},
{
"path": "doc/using-sourmash-a-guide.md",
"chars": 9514,
"preview": "# Using sourmash: a practical guide\n\n```{contents}\n :depth: 2\n```\n\nSo! You've installed sourmash, run a few of the tut"
},
{
"path": "flake.nix",
"chars": 4647,
"preview": "{\n\n inputs = {\n nixpkgs.url = \"github:NixOS/nixpkgs/nixpkgs-unstable\";\n utils.url = \"github:numtide/flake-utils\";"
},
{
"path": "include/sourmash.h",
"chars": 21242,
"preview": "/* c bindings to the sourmash library */\n\n#ifndef SOURMASH_H_INCLUDED\n#define SOURMASH_H_INCLUDED\n\n#include <stdarg.h>\n#"
},
{
"path": "matplotlibrc",
"chars": 14,
"preview": "backend : Agg\n"
},
{
"path": "paper.bib",
"chars": 3564,
"preview": "@article{Ondov:2015,\n title={Fast genome and metagenome distance estimation using MinHash},\n author={Ondov, Brian D an"
},
{
"path": "paper.md",
"chars": 6507,
"preview": "---\ntitle: 'sourmash v4: A multitool to quickly search, compare, and analyze genomic\nand metagenomic data sets'\ntags:\n "
},
{
"path": "pyproject.toml",
"chars": 12164,
"preview": "[build-system]\nrequires = [\n \"maturin>=1,<1.14.0\",\n \"cffi\",\n]\nbuild-backend = 'maturin'\n\n[project]\nname = \"sourmas"
},
{
"path": "requirements.txt",
"chars": 10,
"preview": "-e .[all]\n"
},
{
"path": "shell.nix",
"chars": 257,
"preview": "(import\n (\n fetchTarball {\n url = \"https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0"
},
{
"path": "src/core/CHANGELOG.md",
"chars": 20911,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "src/core/Cargo.toml",
"chars": 3196,
"preview": "[package]\nname = \"sourmash\"\nversion = \"0.22.0\"\nauthors = [\"Luiz Irber <luiz@sourmash.bio>\", \"N. Tessa Pierce-Ward <tessa"
},
{
"path": "src/core/README.md",
"chars": 1552,
"preview": "<meta charset=\"utf-8\"/>\n\n# sourmash\n\n🦀\n[](https://crates.io/crates/sour"
},
{
"path": "src/core/benches/compute.rs",
"chars": 4963,
"preview": "use codspeed_criterion_compat::{Criterion, criterion_group, criterion_main};\n\nuse std::fs::File;\nuse std::io::{Cursor, R"
},
{
"path": "src/core/benches/gather.rs",
"chars": 2426,
"preview": "use std::fs::File;\nuse std::io::BufReader;\nuse std::path::PathBuf;\n\nuse sourmash::collection::Collection;\nuse sourmash::"
},
{
"path": "src/core/benches/minhash.rs",
"chars": 3006,
"preview": "use std::fs::File;\nuse std::io::BufReader;\nuse std::path::PathBuf;\n\nuse sourmash::signature::{Signature, SigsTrait};\nuse"
},
{
"path": "src/core/benches/nodegraph.rs",
"chars": 1499,
"preview": "use std::fs::File;\nuse std::io::{BufWriter, Cursor, Read};\n\nuse sourmash::sketch::nodegraph::Nodegraph;\n\nuse codspeed_cr"
},
{
"path": "src/core/build.rs",
"chars": 2173,
"preview": "use std::env;\n\nfn main() {\n let crate_dir = env::var(\"CARGO_MANIFEST_DIR\").unwrap();\n copy_c_bindings(&crate_dir);"
},
{
"path": "src/core/cbindgen.toml",
"chars": 350,
"preview": "header = \"/* c bindings to the sourmash library */\"\ninclude_guard = \"SOURMASH_H_INCLUDED\"\nlanguage = \"C\"\nstyle = \"type\"\n"
},
{
"path": "src/core/examples/generate_mqfs.rs",
"chars": 2648,
"preview": "use std::collections::HashMap;\nuse std::fs::File;\nuse std::io::BufReader;\nuse std::path::PathBuf;\nuse std::result::Resul"
},
{
"path": "src/core/src/ani_utils.rs",
"chars": 11510,
"preview": "// Streamlined set of utils for containment --> ANI estimation\n// Equations based off of: https://github.com/KoslickiLab"
},
{
"path": "src/core/src/cmd.rs",
"chars": 7021,
"preview": "use getset::{CopyGetters, Getters, Setters};\nuse typed_builder::TypedBuilder;\n\nuse crate::encodings::HashFunctions;\nuse "
},
{
"path": "src/core/src/collection.rs",
"chars": 21614,
"preview": "use std::ops::{Deref, DerefMut};\n\nuse camino::Utf8Path as Path;\nuse camino::Utf8PathBuf as PathBuf;\n\nuse crate::encoding"
},
{
"path": "src/core/src/encodings.rs",
"chars": 19480,
"preview": "use serde::{Deserialize, Serialize};\nuse std::collections::HashMap;\nuse std::hash::{BuildHasher, BuildHasherDefault, Has"
},
{
"path": "src/core/src/errors.rs",
"chars": 7614,
"preview": "use thiserror::Error;\n\n#[derive(Debug, Error)]\n#[non_exhaustive]\npub enum SourmashError {\n /// Raised for internal er"
},
{
"path": "src/core/src/ffi/cmd/compute.rs",
"chars": 5820,
"preview": "use std::slice;\n\nuse crate::ScaledType;\nuse crate::cmd::ComputeParameters;\n\nuse crate::ffi::utils::ForeignObject;\n\npub s"
},
{
"path": "src/core/src/ffi/cmd/mod.rs",
"chars": 17,
"preview": "pub mod compute;\n"
},
{
"path": "src/core/src/ffi/hyperloglog.rs",
"chars": 5696,
"preview": "use std::ffi::CStr;\nuse std::os::raw::c_char;\nuse std::slice;\n\nuse crate::prelude::*;\nuse crate::signature::SigsTrait;\nu"
},
{
"path": "src/core/src/ffi/index/mod.rs",
"chars": 1176,
"preview": "#[cfg(all(feature = \"branchwater\", not(target_arch = \"wasm32\")))]\npub mod revindex;\n\nuse crate::signature::Signature;\n\nu"
},
{
"path": "src/core/src/ffi/index/revindex.rs",
"chars": 18585,
"preview": "use std::ffi::CStr;\nuse std::os::raw::c_char;\nuse std::slice;\n\nuse crate::collection::{Collection, CollectionSet};\nuse c"
},
{
"path": "src/core/src/ffi/manifest.rs",
"chars": 2448,
"preview": "use crate::manifest::{Manifest, Record};\n\nuse crate::ffi::utils::{ForeignObject, SourmashStr};\n\npub struct SourmashManif"
},
{
"path": "src/core/src/ffi/minhash.rs",
"chars": 13831,
"preview": "use std::ffi::CStr;\nuse std::os::raw::c_char;\nuse std::slice;\n\nuse crate::encodings::{aa_to_dayhoff, aa_to_hp, translate"
},
{
"path": "src/core/src/ffi/mod.rs",
"chars": 2323,
"preview": "//! # Foreign Function Interface for calling sourmash from a C API\n//!\n//! Primary client for now is the Python version,"
},
{
"path": "src/core/src/ffi/nodegraph.rs",
"chars": 6605,
"preview": "use std::ffi::CStr;\nuse std::os::raw::c_char;\nuse std::slice;\n\nuse crate::prelude::*;\nuse crate::sketch::nodegraph::Node"
},
{
"path": "src/core/src/ffi/signature.rs",
"chars": 9670,
"preview": "use std::convert::TryInto;\nuse std::ffi::CStr;\nuse std::io;\nuse std::os::raw::c_char;\nuse std::slice;\n\nuse crate::errors"
},
{
"path": "src/core/src/ffi/storage.rs",
"chars": 3516,
"preview": "use std::os::raw::c_char;\nuse std::slice;\nuse std::sync::Arc;\n\nuse crate::ffi::utils::{ForeignObject, SourmashStr};\nuse "
},
{
"path": "src/core/src/ffi/utils.rs",
"chars": 8596,
"preview": "use std::borrow::Cow;\nuse std::cell::RefCell;\nuse std::ffi::CStr;\nuse std::mem;\nuse std::os::raw::c_char;\nuse std::panic"
},
{
"path": "src/core/src/index/linear.rs",
"chars": 12094,
"preview": "use std::collections::HashSet;\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse camino::Utf8PathBuf as PathBuf;\nuse "
},
{
"path": "src/core/src/index/mod.rs",
"chars": 14591,
"preview": "//! # Indexing structures for fast similarity search\n//!\n//! An index organizes signatures to allow for fast similarity "
},
{
"path": "src/core/src/index/revindex/disk_revindex.rs",
"chars": 22865,
"preview": "use std::cmp::max;\nuse std::collections::HashSet;\nuse std::hash::{BuildHasher, BuildHasherDefault};\nuse std::path::Path;"
},
{
"path": "src/core/src/index/revindex/mem_revindex.rs",
"chars": 33324,
"preview": "use std::sync::atomic::{AtomicUsize, Ordering};\n\nuse camino::Utf8Path as Path;\nuse camino::Utf8PathBuf as PathBuf;\nuse l"
},
{
"path": "src/core/src/index/revindex/mod.rs",
"chars": 44180,
"preview": "/// Reverse index data structures.\npub mod disk_revindex;\npub mod mem_revindex;\n\nuse std::collections::{HashMap, HashSet"
},
{
"path": "src/core/src/index/search.rs",
"chars": 856,
"preview": "use crate::index::Comparable;\n\npub fn search_minhashes<L>(node: &dyn Comparable<L>, query: &L, threshold: f64) -> bool {"
},
{
"path": "src/core/src/lib.rs",
"chars": 2230,
"preview": "//! # Compute, compare and search signatures for nucleotide (DNA/RNA) and protein sequences.\n//!\n//! sourmash is a comma"
},
{
"path": "src/core/src/manifest.rs",
"chars": 19765,
"preview": "use std::collections::HashSet;\nuse std::fs::File;\nuse std::hash::{Hash, Hasher};\nuse std::io::{BufRead, BufReader, Read,"
},
{
"path": "src/core/src/prelude.rs",
"chars": 737,
"preview": "use std::io::Write;\n\nuse crate::Result;\n\npub use crate::selection::{Select, Selection};\npub use crate::signature::Signat"
},
{
"path": "src/core/src/selection.rs",
"chars": 3047,
"preview": "use getset::{CopyGetters, Getters, Setters};\nuse typed_builder::TypedBuilder;\n\nuse crate::encodings::HashFunctions;\nuse "
},
{
"path": "src/core/src/signature.rs",
"chars": 65615,
"preview": "//! # Compressed representations of genomic data\n//!\n//! A signature is a collection of sketches for a genomic dataset.\n"
},
{
"path": "src/core/src/sketch/hyperloglog/estimators.rs",
"chars": 7121,
"preview": "use core::{\n cmp,\n ops::{Add, AddAssign, Shl, Sub, SubAssign},\n};\n\npub type CounterType = u8;\n\n/// Trait for types"
},
{
"path": "src/core/src/sketch/hyperloglog/mod.rs",
"chars": 14759,
"preview": "/*\nBased on the HyperLogLog implementations in khmer\n https://github.com/dib-lab/khmer/blob/fb65d21eaedf0d397d49ae3debc"
},
{
"path": "src/core/src/sketch/minhash.rs",
"chars": 56988,
"preview": "use std::cmp::Ordering;\nuse std::collections::{BTreeMap, BTreeSet};\nuse std::f64::consts::PI;\nuse std::fmt::Write;\nuse s"
},
{
"path": "src/core/src/sketch/mod.rs",
"chars": 482,
"preview": "pub mod hyperloglog;\npub mod minhash;\n\npub mod nodegraph;\n\nuse serde::{Deserialize, Serialize};\n\nuse crate::sketch::hype"
},
{
"path": "src/core/src/sketch/nodegraph.rs",
"chars": 32873,
"preview": "use std::fs::File;\nuse std::io;\nuse std::path::Path;\nuse std::slice;\n\nuse byteorder::{BigEndian, ByteOrder, LittleEndian"
},
{
"path": "src/core/src/storage/mod.rs",
"chars": 19397,
"preview": "use std::collections::{BTreeMap, HashMap};\nuse std::ffi::OsStr;\nuse std::fs::{DirBuilder, File};\nuse std::io::{BufReader"
},
{
"path": "src/core/src/storage/rocksdb.rs",
"chars": 4163,
"preview": "use std::sync::Arc;\n\nuse rocksdb::{ColumnFamilyDescriptor, Options};\n\nuse crate::Result;\nuse crate::storage::{Storage, S"
},
{
"path": "src/core/src/wasm.rs",
"chars": 7899,
"preview": "use needletail::parse_fastx_reader;\nuse wasm_bindgen::prelude::*;\n\nuse crate::ScaledType;\nuse crate::cmd::ComputeParamet"
},
{
"path": "src/core/tests/dedicated_worker.rs",
"chars": 169,
"preview": "#![cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))]\n\nuse wasm_bindgen_test::wasm_bindgen_test_configure;\n\nwasm_b"
},
{
"path": "src/core/tests/finch.rs",
"chars": 1,
"preview": "\n"
},
{
"path": "src/core/tests/minhash.rs",
"chars": 31223,
"preview": "use std::fs::File;\nuse std::io::BufReader;\nuse std::path::PathBuf;\n\nuse proptest::collection::vec;\nuse proptest::num::u6"
},
{
"path": "src/core/tests/node.rs",
"chars": 145,
"preview": "#![cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))]\n\nuse wasm_bindgen_test::*;\n\n#[wasm_bindgen_test]\nfn pass() {"
},
{
"path": "src/core/tests/service_worker.rs",
"chars": 167,
"preview": "#![cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))]\n\nuse wasm_bindgen_test::wasm_bindgen_test_configure;\n\nwasm_b"
},
{
"path": "src/core/tests/shared_worker.rs",
"chars": 166,
"preview": "#![cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))]\n\nuse wasm_bindgen_test::wasm_bindgen_test_configure;\n\nwasm_b"
},
{
"path": "src/core/tests/storage.rs",
"chars": 4992,
"preview": "use std::path::PathBuf;\n\nuse tempfile::TempDir;\n\nuse sourmash::signature::Signature;\nuse sourmash::storage::{FSStorage, "
},
{
"path": "src/core/tests/test.rs",
"chars": 101,
"preview": "#[test]\nfn test_murmur() {\n assert_eq!(sourmash::_hash_murmur(b\"ACG\", 42), 1731421407650554201)\n}\n"
},
{
"path": "src/core/tests/web.rs",
"chars": 160,
"preview": "#![cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))]\n\nuse wasm_bindgen_test::wasm_bindgen_test_configure;\n\nwasm_b"
},
{
"path": "src/sourmash/__init__.py",
"chars": 4251,
"preview": "\"\"\"A library for creating k-mer sketches from biological sequences, comparing\nthem to each other, and working with the r"
},
{
"path": "src/sourmash/__main__.py",
"chars": 572,
"preview": "\"\"\"\nThe main entry point for sourmash, defined in pyproject.toml.\n\nCan also be executed as 'python -m sourmash'.\n\"\"\"\n\n\nd"
},
{
"path": "src/sourmash/cli/.gitignore",
"chars": 13,
"preview": "__pycache__/\n"
},
{
"path": "src/sourmash/cli/__init__.py",
"chars": 5626,
"preview": "\"\"\"Define the top-level command line interface for sourmash\n\nThis module handles user input when sourmash is invoked fro"
},
{
"path": "src/sourmash/cli/categorize.py",
"chars": 1184,
"preview": "\"'sourmash categorize' - query an SBT for bes match, with many signatures.\"\n\nfrom sourmash.cli.utils import add_ksize_ar"
},
{
"path": "src/sourmash/cli/compare.py",
"chars": 4088,
"preview": "\"\"\"create a similarity matrix comparing many samples\"\"\"\n\nusage = \"\"\"\n\nThe `compare` subcommand compares one or more sign"
},
{
"path": "src/sourmash/cli/compute.py",
"chars": 4874,
"preview": "\"\"\"compute sequence signatures for inputs\"\"\"\n\nusage = \"\"\"\n\n** WARNING: the sourmash compute command is DEPRECATED as of "
},
{
"path": "src/sourmash/cli/gather.py",
"chars": 6570,
"preview": "\"\"\"search a metagenome signature against dbs\"\"\"\n\nusage = \"\"\"\n\nThe `gather` subcommand selects the best reference genomes"
},
{
"path": "src/sourmash/cli/import_csv.py",
"chars": 667,
"preview": "\"\"\"'sourmash import_csv' description goes here\"\"\"\n\nfrom sourmash.logging import notify\n\n\ndef subparser(subparsers):\n "
},
{
"path": "src/sourmash/cli/index.py",
"chars": 2756,
"preview": "\"\"\"index signatures for rapid search\"\"\"\n\nusage = \"\"\"\n\n sourmash index -k 31 dbname *.sig -F dbtype\n\nCreate an on-disk "
},
{
"path": "src/sourmash/cli/info.py",
"chars": 926,
"preview": "\"\"\"display sourmash version and other information\"\"\"\n\nimport os\nimport screed\nimport sourmash\nfrom sourmash.logging impo"
},
{
"path": "src/sourmash/cli/lca/__init__.py",
"chars": 1186,
"preview": "\"\"\"Define the command line interface for sourmash lca\n\nThe top level CLI is defined in ../__init__.py. This module defin"
},
{
"path": "src/sourmash/cli/lca/classify.py",
"chars": 1414,
"preview": "\"\"\"classify genomes\"\"\"\n\n\ndef subparser(subparsers):\n subparser = subparsers.add_parser(\"classify\")\n subparser.add_"
},
{
"path": "src/sourmash/cli/lca/compare_csv.py",
"chars": 1442,
"preview": "\"\"\"compare spreadsheets\"\"\"\n\n\ndef subparser(subparsers):\n # Dirty hack to simultaneously support new and previous inte"
},
{
"path": "src/sourmash/cli/lca/index.py",
"chars": 2602,
"preview": "\"\"\"create LCA database\"\"\"\n\nfrom sourmash.cli.utils import add_ksize_arg, add_moltype_args, add_picklist_args\n\n\ndef subpa"
},
{
"path": "src/sourmash/cli/lca/rankinfo.py",
"chars": 722,
"preview": "\"\"\"database rank info\"\"\"\n\n\ndef subparser(subparsers):\n subparser = subparsers.add_parser(\"rankinfo\")\n subparser.ad"
},
{
"path": "src/sourmash/cli/lca/summarize.py",
"chars": 1470,
"preview": "\"\"\"summarize mixture\"\"\"\n\n\ndef subparser(subparsers):\n subparser = subparsers.add_parser(\"summarize\")\n subparser.ad"
},
{
"path": "src/sourmash/cli/migrate.py",
"chars": 299,
"preview": "\"'sourmash migrate' - migrate an SBT database to the latest version.\"\n\n\ndef subparser(subparsers):\n subparser = subpa"
},
{
"path": "src/sourmash/cli/multigather.py",
"chars": 3705,
"preview": "\"'sourmash multigather' - gather many signatures against multiple databases.\"\n\nusage = \"\"\"\n\nThe `multigather` subcommand"
},
{
"path": "src/sourmash/cli/plot.py",
"chars": 2427,
"preview": "\"\"\"plot distance matrix made by 'compare'\"\"\"\n\n\ndef subparser(subparsers):\n subparser = subparsers.add_parser(\"plot\")\n"
},
{
"path": "src/sourmash/cli/prefetch.py",
"chars": 2510,
"preview": "\"\"\"search a signature against dbs, find all overlaps\"\"\"\n\nfrom sourmash.cli.utils import (\n add_ksize_arg,\n add_mol"
},
{
"path": "src/sourmash/cli/sbt_combine.py",
"chars": 453,
"preview": "\"\"\"combine multiple Sequence Bloom Trees\"\"\"\n\n\ndef subparser(subparsers):\n subparser = subparsers.add_parser(\"sbt_comb"
},
{
"path": "src/sourmash/cli/scripts/__init__.py",
"chars": 1706,
"preview": "\"\"\"Provide a mechanism to add CLI plugins to sourmash.\n\nSee https://sourmash.readthedocs.io/en/latest/dev_plugins.html f"
},
{
"path": "src/sourmash/cli/search.py",
"chars": 4483,
"preview": "\"\"\"search a signature against other signatures\"\"\"\n\nusage = \"\"\"\n\nThe `search` subcommand searches a collection of signatu"
},
{
"path": "src/sourmash/cli/sig/__init__.py",
"chars": 1613,
"preview": "\"\"\"Define the command line interface for sourmash sig\n\nThe top level CLI is defined in ../__init__.py. This module defin"
},
{
"path": "src/sourmash/cli/sig/cat.py",
"chars": 1674,
"preview": "\"\"\"concatenate signature files\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature cat` - concatenate multiple signatures together\n"
},
{
"path": "src/sourmash/cli/sig/check.py",
"chars": 3207,
"preview": "\"\"\"check signature collections against a picklist\"\"\"\n\nusage = \"\"\"\n\n sourmash sig check <filenames> --picklist ... -o "
},
{
"path": "src/sourmash/cli/sig/collect.py",
"chars": 2688,
"preview": "\"\"\"collect manifest information across many files\"\"\"\n\nusage = \"\"\"\n\n sourmash sig collect <filenames> -o all.sqlmf\n\nTh"
},
{
"path": "src/sourmash/cli/sig/describe.py",
"chars": 1595,
"preview": "\"\"\"show details of signature\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature describe` - display detailed information about sig"
},
{
"path": "src/sourmash/cli/sig/downsample.py",
"chars": 1984,
"preview": "\"\"\"downsample one or more signatures\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature downsample` - decrease the size of a signa"
},
{
"path": "src/sourmash/cli/sig/export.py",
"chars": 1025,
"preview": "\"\"\"export a signature, e.g. to mash\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature export` - export signatures to mash.\n\nExpor"
},
{
"path": "src/sourmash/cli/sig/extract.py",
"chars": 2541,
"preview": "\"\"\"extract one or more signatures\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature extract` - extract signatures from a collecti"
},
{
"path": "src/sourmash/cli/sig/fileinfo.py",
"chars": 1173,
"preview": "\"\"\"provide summary information on the given file\"\"\"\n\nusage = \"\"\"\n\n sourmash sig fileinfo <filename>\n\nThis will provid"
},
{
"path": "src/sourmash/cli/sig/filter.py",
"chars": 1911,
"preview": "\"\"\"filter k-mers on abundance\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature filter` - remove hashes based on abundance\n\nFilte"
},
{
"path": "src/sourmash/cli/sig/flatten.py",
"chars": 1687,
"preview": "\"\"\"remove abundances\"\"\"\n\nusage = \"\"\"\n\n### `sourmash signature flatten` - remove abundance information from signatures\n\nF"
},
{
"path": "src/sourmash/cli/sig/grep.py",
"chars": 3400,
"preview": "\"\"\"extract one or more signatures by substr/regex match\"\"\"\n\nusage = \"\"\"\n sourmash sig grep <pattern> <filename> [... "
},
{
"path": "src/sourmash/cli/sig/inflate.py",
"chars": 925,
"preview": "\"\"\"borrow abundances from one signature => one or more other signatures\"\"\"\n\nfrom sourmash.cli.utils import add_moltype_a"
},
{
"path": "src/sourmash/cli/sig/ingest.py",
"chars": 1320,
"preview": "\"\"\"ingest/import a mash or other signature\"\"\"\n\nusage = \"\"\"\n\n sourmash sig ingest --csv <input filename> [ <more inputs"
}
]
// ... and 507 more files (download for full content)
About this extraction
This page contains the full source code of the dib-lab/sourmash GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 707 files (10.9 MB), approximately 2.9M tokens, and a symbol index with 4731 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.