Skip to main content

No project description provided

Project description

Finch

CI DOI

Finch is an implementation of min-wise independent permutation locality sensitive hashing ("MinHashing") for genomic data. This repository provides a library and command-line interface that reimplements much of One Codex's existing internal clustering/sequence search tool (and adds new features/extensions!) in Rust.

Getting Started

Installation

You may build Finch from source, which requires Rust >= 1.49. Rust's Cargo package manager (see rustup for Cargo installation instructions) can automatically build and install Finch with cargo install finch_cli. If you require python bindings, you must take extra steps (see python support). Alternatively, download a prebuilt binary or install from PyPi pip install finch-sketch.

Development

To build wheels locally, run:

uv venv --python 3.11
source .venv/bin/activate
uv build

# or, using maturin by itself:

maturin build --features python --release --strip^

Building binary wheels and pushing to PyPI

There is a Github Workflow that will build Python wheels for macOS (x86 and ARM) and Ubuntu (x86). To run, create a new release.

Example Usage

To get started, we first compute sketches for several FASTA or FASTQ files. These sketches are compact, sampled representations of the underlying genomic data, and what allow finch to rapidly estimate distances between datasets. Sketching files uses the finch sketch command:

finch sketch example.fastq example2.fastq

The resulting sketch files (example.fastq.sk and example2.fastq.sk) can then be used with other finch commands (as well as with other MinHash implementations1). Note that all of Finch's commands can take either sketches or raw sequence files. If passed the latter, finch will sketch the files on the fly. Sketches generated on the fly are not saved, however, so you should call finch sketch if you plan to use the sketch multiple times.

Once sketched, multiple sequencing runs can be compared to determine how similar they are:

finch dist example.fastq.sk example2.fastq.sk

This will print results (in JSON) with some key distance statistics, including containment and jaccard similarity scores and a mashDistance distance estimate:

[
  {
    "commonHashes": 30,
    "containment": 0.03,
    "jaccard": 0.015228426395939087,
    "mashDistance": 0.1669789474914277,
    "query": "example2.fastq",
    "reference": "example1.fastq",
    "totalHashes": 1000
  }
]

In this case, these files have an estimated distance of ~0.17 and a containment of 0.03 (i.e., the two FASTQs share 3% of their min-mers). Note that re-computing the sketches with a larger --n-hashes parameter can provide additional resolution for highly similar datasets.

Next, we may want to find the nearest genomes to our example FASTQ across all of RefSeq. To do this, we simply pass our example query file as the first argument and a sketch file containing all the genomes in RefSeq as the second argument (see the Example Data section for pre-computed RefSeq databases that work with finch):

finch dist ./example.fastq.sk ./refseq_sketches_21_1000.sk --max-dist 0.2

Here, we also set a maximum distance of 0.2 in order to filter out less closely related genomes (a distance of 0 would be an identical genome). Setting a maximum ensures that the only relevant results are returned -- omitting this parameter would return distances to all of the genomes in RefSeq.

Note: Each of these commands is detailed further below, and more information is also available by passing the --help flag to each command, e.g., finch dist --help.

Design goals

We have 3 primary design goals with Finch:

  1. Support for tracking k-mer/minmer counts;

  2. Improved error filtering for use with raw sequence data (i.e., FASTQs); and

  3. Improved performance.

Support for counts

Finch is one of the first MinHash implementations to support tracking the abundances of each unique k-mer/minmer. This allows useful quick interpretations of data (e.g. visualizing sequencing depth with finch hist) in addition to laying the support for more advanced filtering (implemented here) and count-aware distance measures (a future area for investigation and study). Because Finch also supports the new Mash JSON compatibility format, we're able to save this count information for downstream processing and comparisons.

:warning:  Note that although Finch supports the common JSON interchange format, there may still be incompatibilites due to incompaible hashing seed values (Finch uses a seed of 0, while Mash uses 42; see this issue for more discussion).

Filtering

A key design goal for Finch was the ability to accurately – and stably – sketch variable depth sequencing of bacterial isolates (i.e., to not require a high quality assembly). While Mash includes the ability to specify a fixed absolute cutoff (or use a Bloom filter to filter out unique minmers in a sample), in practice this filtering mechanism performs poorly across varied sequencing depths, genome sizes, and sequencing error profiles. The Finch filtering approach implemented here extends several of the ideas in the original Mash paper, as well as prior work on clustering clinical C. diff isolates.

Finch includes two classes of automated filtering (on by default for FASTQs) to address this challenge:

  1. Adapative, count-based filtering: Our default implementation "over-sketches" an input file (i.e., includes n fold more minmers than specified by the user) and dynamically determines an appropriate count-based filtering cutoff that removes low abundance k-mers (which predominantly consist of random errors). As a fallback, this implementation never excludes more than an upper bound proportion of minmers that may be reasonably assumed to be erroneous (k times a specified --err-filter error rate, for a default of 21%).

  2. Strandedness filtering: We also apply a "strandedness filter" to remove k-mers that are overwhelmingly found in one orientation; in practice these are often seqeuencing adapters or other artifacts that are not representative of the underlying sample (and may erroneously reduce the similarity between two sketches).

In practice, these optimizations dramatically increase the stability and accuracy of distance estimates between variable depth isolates and finished assemblies. The below graph shows the distance between a high quality bacterial assembly and sketches of FASTQ files representing various sequencing depths across 3 filter strategies: no filtering (cutoff=0), "naïve" filtering (cutoff=1), and Finch's adapative, variable-cutoff filtering. We use the containment measure, with results closer to 100% being better:

Accuracy versus sequencing depth for different filtering schemes

Notably, this strategy performs well across sequencing depths, while fixed cutoffs of 0 and 1 never achieve the near-100% expected containment (and the former fails catastrophically at even modest depths). It is also robust to repeated errors (i.e., error k-mers/minmers with a count >= 2), which can begin to pose a problem at sequencing depths as low a 10-20X.

Speed/performance

In addition to some of the memory safety guarentees that Rust enables, we also see considerable speed gains over existing implementations. Ideally, hashing should be the rate-limiting step in MinHashing. Profiling indicates finch spends about a third of its time in murmurhash3_x64_128 so we should be within an order of magnitude of this theoretical limit.

Mash Mash (filtered) Sourmash Finch Finch (filtered)
Time 238s 276s 518s 99s 104s
Max Memory (Mb) 1.2 501.1 13.9 21.8 60.0

Note: Benchmarks run on an Early 2015 Macbook Pro. Benchmark is sketching a 4.8Gb FASTQ file (SRR5132341.fastq) with a sketch size of n=10,000. Finch filtered results use the default options, while Mash uses -b 500Mb to allocate a 500Mb Bloom filter. Benchmarks used the following commits for Mash (23776db) and sourmash (5da5ee7)

Usage

Finch supports four primary operations, with many of these operations taking similar parameters.

Shared Parameters

Finch can take many parameters to control how sketching is performed (and these options are also available for the dist, hist, and info commands).

  • -n <N> / --n-hashes <N> controls the overall size of the sketch (higher values give better resolution in comparisons). Default 1000.
  • -k <K> / --kmer-length <K> sets the size of the kmers to be hashed (higher values make comparisons much more taxonomically specific). Default 21.
  • --seed <S> sets the seed for hashing. This should only be changed if directly exporting sketches for comparison with other versions of the Mash algorithm that use a non-zero default seed. Default 0.

After sketching, filtering is performed and can be controlled through several options:

  • -f / --filter / --no-filter determines whether filtering is applied or not (if not specified, filtering is performed for FASTQ files and not performed for FASTA files by default)
  • --min-abun-filter <MIN> / --max-abun-filter <MAX> sets absolute minimum and maximum abundances (inclusive) that all kmers must be present at. The minimum filter will override any adaptive error filter guessing (below).
  • --err-filter <ERR_VALUE> is the default adaptive filtering scheme. Conceptually ERR_VALUE should be approximately the error rate of the sequencer or higher. Note that high error rate sequencing data (i.e. long read sequencing) does poorly with MinHashing in general.
  • --strand-filter <V> sets the strand filter cutoff.

Note that if there aren't enough kmers left from the oversketch to satisfy the sketch size, sketching will fail. There are two options that may help:

  • --oversketch <N> can be used to increase the size of the oversketch (normally 200x) and increase the likelihood that the filtered version will be big enough.
  • --no-strict will allow Finch to proceed with a sketch smaller than the specified size. Use with caution.

finch sketch

finch sketch will read through a FASTA or FASTQ file and generate a "sketch" that can be used for further .

If the file being read is a sketch and the filtering flag is set (-f/--filter), the abundance filters will be re-applied to the sketch to allow post-sketch filtering. The strand filters can only be applied to raw FAST(A/Q) files though, as the strand-level data is lost when sketches are saved.

By default sketch generates .sk suffixed files next to the FAST(A/Q) files it sketches. This can be overridden by passing either -O (capital O) to write to standard out or -o <file> (lowercase o) to write to a file. To read from standard input, use a filename of -; this allows streaming of files into finch, e.g. cat testfile.fq | finch sketch -o testfile.sk -.

Sketches should be compatible with the original Mash implementation if you edit their src/mash/hash.h and set the hash value to 0 or if you manually override Finch's seed value by setting --seed 42.

finch dist

finch dist will calculate Jaccard distances between different sketches. If the files listed are FASTA/Q instead of sketches, Finch will automatically sketch them into memory using the same command-line parameters as in sketch or, for files after the first, the parameters used to sketch the first file.

Distances and containments will only be computed from one or more queries to a collection of references; by default the first sketch in the list will be used as the query and all other sketches will be used as references. This behavior can be manually overriden and other sketches can be used as references by passing --queries <sketch_1>,<sketch_2. Additionally, passing the --pairwise option will calculate the distances between all sketches and each other.

Due to different counting algoritms and stopping criteria, distances may be slightly different from the calculation in the original Mash program and older version of finch. Passing the -old-dist flag will revert to the older version of Finch's calculation; support for Mash's exact distance calculation has been dropped as of version 0.3.

finch hist

finch hist will output a histogram in JSON format for each sketch provided. The histogram is a list of the number of minmers at each depth, e.g. {"sketch_name": [1, 0, 1]} for a sketch with two minmers, one with a depth of 1 (first position) and one with a depth of 3 (third position).

:warning:   You can use the following command with Matplotlib to get a quick histogram: finch hist test.fastq.sk | python -c 'import json; import matplotlib.pyplot as plt; import sys; v = json.loads(sys.stdin.read()).values()[0]; plt.plot(range(1, len(v)+1), v); plt.show()'. Note that the finch hist JSON output is likely to change in a future version to, e.g., a more compact {count: value} format or similar.

finch info

finch info will output a formatted list of % GC, coverage, etc for each sketch provided.

:warning:  Note that the values returned from this are approximate and the algoritms used to calculate are still rough and liable to change.

Example Data

We've sketched the NCBI RefSeq collection (as of March 27, 2017 using this script) and made tarballs with individual sketches for each bacterial and viral genome available. Links: k=21 and n=1,000, k=31 and n=1,000, k=21 and n=10,000, and k=31 and n=10,000.

References & Notes

There are several other implementations of the Mash algorithm which should be compatible/comparable with this one, notably:

  • Mash - First implementation and theoretical paper
  • SourMash - Newer implementation in Python; provides a number of experimental features

Notes:

Python Support

You can install Finch using Pip:

pip install finch-sketch

You can compile Finch into a python library with:

pip install maturin
cd lib
maturin build --features=python --release --strip
# or maturin develop, etc
# to cross-compile linux wheels:
cp ../README.md .
# and edit the `readme` key of Cargo.toml
docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin:main build --features=python --release --strip --interpreter=python3.10 --compatibility=manylinux2010

Then, e.g. to calculate the similarities between two E. coli:

from finch import sketch_file

sketch_one = sketch_file('WIS_EcoB_v2.fas')
sketch_two = sketch_file('WIS_Eco10798_DRAFTv1.fas')
cont, jacc = sketch_one.compare(sketch_two)

Cap'n Proto

There is a finch.capnp in src/serialization file and the output of the MinHash schema (https://github.com/marbl/Mash/blob/54e6d66b7720035a2605a02892cad027ef3231ef/src/mash/capnp/MinHash.capnp)

Both are generated after installing capnp and cargo install capnpc with the following command:

capnp compile -orust:finch-lib/src/serialization/ --src-prefix=finch-lib/src/serialization/ finch-lib/src/serialization/finch.capnp
capnp compile -orust:finch-lib/src/serialization/ --src-prefix=finch-lib/src/serialization/ finch-lib/src/serialization/mash.capnp

and then search and replace for the crate:: path to fix it crate::serialization::.

Contributions

Problems or suggestions for improvement can be reported through GitHub issues. We are happy to accept and/or mentor any additions or fixes (which are best submitted as pull requests). For our code of conduct, please see CODE_OF_CONDUCT.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

finch_sketch-0.6.3.tar.gz (56.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

finch_sketch-0.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (870.1 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

finch_sketch-0.6.3-cp313-cp313-macosx_11_0_arm64.whl (684.7 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

finch_sketch-0.6.3-cp313-cp313-macosx_10_12_x86_64.whl (769.1 kB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

finch_sketch-0.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (871.1 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

finch_sketch-0.6.3-cp312-cp312-macosx_11_0_arm64.whl (684.9 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

finch_sketch-0.6.3-cp312-cp312-macosx_10_12_x86_64.whl (770.1 kB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

finch_sketch-0.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (876.4 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

finch_sketch-0.6.3-cp311-cp311-macosx_11_0_arm64.whl (692.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

finch_sketch-0.6.3-cp311-cp311-macosx_10_12_x86_64.whl (770.9 kB view details)

Uploaded CPython 3.11macOS 10.12+ x86-64

File details

Details for the file finch_sketch-0.6.3.tar.gz.

File metadata

  • Download URL: finch_sketch-0.6.3.tar.gz
  • Upload date:
  • Size: 56.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for finch_sketch-0.6.3.tar.gz
Algorithm Hash digest
SHA256 a680232b5cec7870e4a934d90d12b5d271568ad26bb02201a49ff6bf6dd0f840
MD5 e8ce8d450c8fb5e4a6264aaf7e412d5c
BLAKE2b-256 9cdf56856edd5eb0ddadad4eba15c9b28f6cc3b50434df998c4ce808d8ed7adf

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 9904887399fd9bbf0eaa9e21c6649906eaccfdd06528346de7caf1a2db3f1a8f
MD5 96d6d6f9a98e2abf4a1d3ebec8d2c839
BLAKE2b-256 1f3dd4c99c2d5157e42f90624fda7cba740b6278e369402c45e640affabb769a

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8ae71feca9b9b6a3730e9efc91827126aed10d00b6b0daeaa09e9948368f94f5
MD5 7f8b370f8afc24543c78150a24af4555
BLAKE2b-256 66c94074d505a69aad1537c9b51ec050eb8e13882d0b44c6d40e4a12f8d8ba4b

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 98bcdc8aa0f11ac919ea52e6471957e33c26d1d1705eb0ce140ee75f50883f81
MD5 620154a242d1a83d8f7aa6dfb71eea90
BLAKE2b-256 98d34f684c029b339b10834458bb768ec547dfc33662df542b84f41be16634b9

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fb36a47018dcf10631e829a90b3aae19aece3a4e403b621af0d5656086542b78
MD5 d096ed2aeadd915b39cedae0d81a7024
BLAKE2b-256 b7473739032d03b6bed9e245f6b4c2796164d6d6429943392622dabc9d37cf3c

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e916262021810f6f9bc80dd88680075184dab39dc75771cef5a153390f94a32f
MD5 7f09405031d58429861e5ac15ad34a2c
BLAKE2b-256 d6fa16a827f6f87a979cddadc1dcf0e419169ec45cfddaed9cb502f6d91ae81d

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a73c2c17e8c83bb2d09bfca7a6655a2b8c7b85ec046c44c1b92b8ac1628787cf
MD5 e96d5fadab6978e9726d79b26c5b526f
BLAKE2b-256 cee7b01deb454684edd65071da0d4cf1b8e6b8aebd65de9c164e41045e834fbd

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0a862bc74a5758400d7e725083a50fa77ae73d7448b8f361a4f0cdfe7d730982
MD5 e64721e85be04aa11d8fa70b2b473a3f
BLAKE2b-256 4abf9d646b287981dd4d097c41fb15009758c1166ef2681afa62129e7fc450fd

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c7820fa2ed5ccd1f30f0a74612d965e802e3ab551bce6d991983a16cc7e197e4
MD5 fafb3dabbe63273ce6c222062c664703
BLAKE2b-256 78e20396eef6b042b01978383beb9424c960f39ff562af84dfb69cdffdfa23b3

See more details on using hashes here.

File details

Details for the file finch_sketch-0.6.3-cp311-cp311-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for finch_sketch-0.6.3-cp311-cp311-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2eb51743f02006fe9a1363ee257c738928a480b448472cc46467b3f255d7391a
MD5 eaed28fb0b3f52b752d9ead823da31bf
BLAKE2b-256 25ff0d955aacd1171b8755120912c899800100795fb4e2f1803c6551368449e5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page