FN6
Fast, efficient and scalable SNP distance calculation from disk.
FN5 reworked into Rust. Approximately 10x faster, easier to use and maintain, and adds checking for matching reference and mask in FN6 saves, all while retaining interoperability with FN5 saves.
Quickstart
Requirements
Version >= 1.85.0 of cargo, the Rust package manager. Recommended installation can be found here. If an earlier version is installed, please try rustup update instead.
CLI installation
You don't need to clone this repository, but if you're working on M.Tuberculosis then you will probably want to make a copy of masquerade_std_tb_plus.mask and it might be a convenient place from which to obtain NC_000962.3.fasta.
cargo install fn6
Mask
Masking is used for SNP distance calculation to avoid counting SNPs at problematic sites, e.g homoplastic sites. This repo includes an example mask for Mycobacterium Tuberculosis (specifically NC_000962.3) generated by https://github.com/oxfordmmm/masquerade
Masking can be ignored if you would prefer by omitting the --mask argument
Reference
A reference is required to compute SNP distances from FASTA files. Included in this repo are reference genomes for Mycobacterium Tuberculosis and SARS-CoV-2
Cut off
As SNP distances become decreasingly useful for outbreak detection as they increase, FN6 saves computation by stopping compute early when SNPs increase above a given cutoff. This intentionally results in missing distances as they add little information - if you run FN6 and recieve no results, the likely cause is that none of the given samples lie within the SNP cut off.
For M.Tuberculosis, the evolution rate is roughly 1 SNP per year, so transmission networks often look at SNP thresholds of 3, 6, or 12 SNPs.
By default, FN6 uses a cut off of 20 SNPs. This can be controlled with the --cutoff argument. To remove the cutoff, set this arbitrarily high; e.g --cutoff 99999999. This can be useful for things such as building a neighbour joining tree.
Calculate distances directly from FASTA files
With all of your .fasta files within path/to/your/fastas:
fn6 compute --reference NC_000962.3.fasta --mask masquerade_std_tb_plus.mask --directory path/to/your/fastas --allow-fasta
Reference
All FASTA inputs can be optionally gzipped.
Fast, efficient and scalable SNP distance calculation from disk.
Usage: fn6 <COMMAND>
Commands:
reference-compress Reference compress a sample genome. This will create a .fn6 file that can be used for fast comparisons with other samples. The .fn6 file is a binary file that contains the compressed representation of the sample genome, as well as metadata about the reference and mask used for compression
compute Compute SNP distances
add-samples Add some samples to existing samples. Only computes the extra distances required rather than all pairwise distances
bulk-compress Reference compress a set of genomes. Dumber than `ReferenceCompress` as it doesn't allow for setting specific IDs or output paths, but much faster as it can be parallelized across samples
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
Reference compress
Reference compress a sample genome. This will create a .fn6 file that can be used for fast comparisons with other samples. The .fn6 file is a binary file that contains the compressed representation of the sample genome, as well as metadata about the reference and mask used for compression
Usage: fn6 reference-compress [OPTIONS] <REFERENCE> <SAMPLE> [MASK]
Arguments:
<REFERENCE> Path to the reference genome FASTA file
<SAMPLE> Path to the sample genome FASTA file
[MASK] Path to the mask file. The mask file is a text file containing the positions of the reference genome that should be masked (i.e., ignored) during the analysis. The positions are 0-based and should be separated by newlines
Options:
--id <ID> ID for this sample
--output <OUTPUT> Output path for the .fn6 file. If not provided, the .fn6 file will be saved in the same directory as the sample FASTA file with the same name but with a .fn6 extension
--debug Whether to print debug information to stderr
-h, --help Print help
Compute
Compute SNP distances
Usage: fn6 compute [OPTIONS]
Options:
-r, --reference <REFERENCE>
Path to the reference genome FASTA file. Only required if >=1 of the samples specified are fasta files
-m, --mask <MASK>
Path to the mask file. The mask file is a text file containing the positions of the reference genome that should be masked (i.e., ignored) during the analysis. The positions are 0-based and should be separated by newlines. Only required if >=1 of the samples specified are fasta files
-s, --samples <SAMPLES>...
Paths to sample files. Either .fn6, .fn5 or FASTA files. If FASTA files are provided, the `allow-fasta` flag must also be used. They will then be reference compressed on the fly (using the provided reference and mask) before distance computation
-d, --directory <DIRECTORY>
Directory to load from. Either .fn6, .fn5 or FASTA files. If FASTA files are provided, the `allow-fasta` flag must also be used. They will then be reference compressed on the fly (using the provided reference and mask) before distance computation
--cutoff <CUTOFF>
SNP threshold [default: 20]
-o, --output <OUTPUT>
Path to a file to store distances in using a space-separated file. Columns are sample1, sample2, distance. If not provided, distances will be printed to stdout in the same format
--fasta-extension <FASTA_EXTENSION>
FASTA file extension to look for when loading from a directory. Only used if loading from a directory and if reference and mask are provided (i.e., if FASTA files need to be reference compressed on the fly). Default is "fasta" [default: fasta]
--allow-fasta
Whether to enable computation from FASTAs. It is recommended to pre-cache the reference compressed versions of the new samples to speed up computation
--debug
Whether to print debug information to stderr
-h, --help
Print help
Add samples
Add some samples to existing samples. Only computes the extra distances required rather than all pairwise distances
Usage: fn6 add-samples [OPTIONS]
Options:
-r, --reference <REFERENCE>
Path to the reference genome FASTA file. Only required if >=1 of the samples specified are fasta files
-m, --mask <MASK>
Path to the mask file. The mask file is a text file containing the positions of the reference genome that should be masked (i.e., ignored) during the analysis. The positions are 0-based and should be separated by newlines. Only required if >=1 of the samples specified are fasta files
-s, --existing-samples <EXISTING_SAMPLES>...
Paths to existing sample files. Either .fn6, .fn5 or FASTA files. If FASTA files are provided, the `allow-fasta` flag must also be used. They will then be reference compressed on the fly (using the provided reference and mask) before distance computation
-d, --existing-directory <EXISTING_DIRECTORY>
Directory to load existing saves from. Either .fn6, .fn5 or FASTA files. If FASTA files are provided, the `allow-fasta` flag must also be used. They will then be reference compressed on the fly (using the provided reference and mask) before distance computation
-S, --new-samples <NEW_SAMPLES>...
Paths to sample files to add. Either .fn6, .fn5 or FASTA files. If FASTA files are provided, the `allow-fasta` flag must also be used. They will then be reference compressed on the fly (using the provided reference and mask) before distance computation
-D, --new-directory <NEW_DIRECTORY>
Directory to load new saves from. Either .fn6, .fn5 or FASTA files. If FASTA files are provided, the `allow-fasta` flag must also be used. They will then be reference compressed on the fly (using the provided reference and mask) before distance computation
--cutoff <CUTOFF>
SNP threshold [default: 20]
-o, --output <OUTPUT>
Path to a file to store distances in using a space-separated file. Columns are sample1, sample2, distance. If not provided, distances will be printed to stdout in the same format
-f, --fasta-extension <FASTA_EXTENSION>
FASTA file extension to look for when loading from a directory. Only used if loading from a directory and if reference and mask are provided (i.e., if FASTA files need to be reference compressed on the fly). Default is "fasta" [default: fasta]
--allow-fasta
Whether to enable computation from FASTAs. It is recommended to pre-cache the reference compressed versions of the new samples to speed up computation
--debug
Whether to print debug information to stderr
-h, --help
Print help
Bulk Compress
Reference compress a set of genomes. Dumber than `ReferenceCompress` as it doesn't allow for setting specific IDs or output paths, but much faster as it can be parallelized across samples
Usage: fn6 bulk-compress [OPTIONS] <REFERENCE> [MASK]
Arguments:
<REFERENCE> Path to the reference genome FASTA file
[MASK] Path to the mask file. The mask file is a text file containing the positions of the reference genome that should be masked (i.e., ignored) during the analysis. The positions are 0-based and should be separated by newlines
Options:
-s, --samples <SAMPLES>...
Paths to sample files. Either FASTA files or .fn6 files
-d, --directory <DIRECTORY>
Directory to load from
-l, --list <LIST>
Line separated file to read paths from
-o, --output <OUTPUT>
Output directory to write saves to. Useful when using `list` as it consolidates saves in a single directory. If not provided, the .fn6 files will be saved in the same directory as their corresponding FASTA files with the same name but with a .fn6 extension
--fasta-extension <FASTA_EXTENSION>
FASTA file extension to look for when loading from a directory [default: fasta]
--debug
Whether to print debug information to stderr
-h, --help
Print help
Performance
Both FN5 and FN6 produce the same results, but with condsiderable time differences. Below is a table of comparison between FN5 and FN6 performance on varying sets of Mycobacterium tuberculosis samples, randomly selected from the CRyPTIC dataset https://doi.org/10.5281/zenodo.16041005 All of the benchmarks were run on the same laptop with an Intel i9-13900H and 32GB RAM, directly from SSD.
| N Samples (passing QC) | Comparisons | FN5 Reference compression | FN5 Compute pairwise matrix (per comparison) | FN5 Compute pairwise matrix (per comparison) no cutoff | FN6 Reference compression | FN6 Compute pairwise matrix (per comparison) | FN6 Compute pairwise matrix (per comparison) no cutoff | FN6 Compute pairwise matrix from FN5 saves (per comparison) | FN6 Compute pairwise matrix from FN5 saves (per comparison) no cutoff |
|---|---|---|---|---|---|---|---|---|---|
| 100 | 4,950 | 1.394s | 44ms (8.9µs) | 175ms (35.6µs) | 0.17s | 7.93ms (1.60µs) | 81.28ms (16.42µs) | 9.29ms (1.88µs) | 53.49ms (10.81µs) |
| 250 | 31,125 | 1.698s | 208ms (6.7µs) | 1087ms (34.9µs) | 0.33s | 32.29ms (1.04µs) | 280.36ms (9.01µs) | 24.75ms (795.00ns) | 270.21ms (8.68µs) |
| 500 | 124,750 | 3.506s | 628ms (5.0µs) | 3905ms (31.3µs) | 0.67s | 84.04ms (673.00ns) | 921.34ms (7.39µs) | 48.75ms (390.00ns) | 1010ms (8.13µs) |
| 750 | 280,875 | 5.091s | 1298ms (4.6µs) | 8179ms (29.1µs) | 0.92s | 114.78ms (408.00ns) | 2000ms (7.14µs) | 91.94ms (327.00ns) | 5580ms (19.85µs) |
| 1000 | 499,500 | 6.735s | 2287ms (4.6µs) | 14299ms (28.6µs) | 0.90s | 152.88ms (306.00ns) | 3480ms (6.98µs) | 143.89ms (288.00ns) | 8910ms (17.85µs) |
| 1500 (1493) | 1,113,785 | 11.363s | 7481ms (6.7µs) | 100481ms (90.2µs) | 2.03s | 300.10ms (269.00ns) | 9130ms (8.20µs) | 296.32ms (266.00ns) | 22720ms (20.40µs) |
| 2000 (1992) | 1,983,044 | 16.377s | 30805ms (15.5µs) | 205160ms (103.5µs) | 2.69s | 487.53ms (245.00ns) | 18390ms (9.27µs) | 613.04ms (309.00ns) | 42150ms (21.25µs) |
All of the times to compute a pairwise matrix include the time taken to read the saves from disk. The time taken to load the saves from disk varies by tool, but is an important component of the real world runtime.
Mean time to load a save from disk across all above runs:
| FN5 | FN6 | FN6 (from FN5 saves) |
|---|---|---|
| 64.6µs | 25.0µs | 41.3µs |
This also demonstrates the importance of utilising a SNP cutoff within the computation. Otherwise, per sample comparison times scale according to how disparate samples are.
Testing
For simplicity, testing is based on a dummy genome with 80 bases. This allows for known SNPs to be introduced and manually calculated
cargo test
Release files for fn6 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 9.6 MB
Release files / fn6-0.2.1-cp310-abi3-win_amd64.whl
| Download URL | fn6-0.2.1-cp310-abi3-win_amd64.whl |
|---|---|
| Size | 270.0 kB |
| Tags | CPython 3.10 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
4a5c4ea551a532b51eb46a2c6d4737353e3a039f1d36c4a639c446bbf0766fc1
|
|
BLAKE2b-256 checksum How to use checksums |
8eb282bb570ba64fce01511809ea118750c2a7e1b28b2da1aa41c4df762d83f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl
| Download URL | fn6-0.2.1-cp310-abi3-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 991.7 kB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
83780b940d9015da20e9f90a5e1864fb809dfe15b5887c076c94f5fd1674746a
|
|
BLAKE2b-256 checksum How to use checksums |
796e6a19b8315a4026e4145c2216405af67689713c20704a6eb9ffbd7f560a66
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-musllinux_1_2_i686.whl
| Download URL | fn6-0.2.1-cp310-abi3-musllinux_1_2_i686.whl |
|---|---|
| Size | 1.0 MB |
| Tags | CPython 3.10 Linux musl 1.2+ x86-32 abi3 |
|
SHA-256 checksum How to use checksums |
7024bbaca74e6dc746af6a9775625722badefe5dddaf3bea35d6a044e66ce8a7
|
|
BLAKE2b-256 checksum How to use checksums |
4000c632e59e6891e05705269430b514d22acc76481ac74026d7cdd3daca16e6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-musllinux_1_2_armv7l.whl
| Download URL | fn6-0.2.1-cp310-abi3-musllinux_1_2_armv7l.whl |
|---|---|
| Size | 1.1 MB |
| Tags | CPython 3.10 Linux musl 1.2+ ARMv7l abi3 |
|
SHA-256 checksum How to use checksums |
29fc415c096d960a4ac6ee05dd5e427899f98b2ca3d5be7f4ba53bf69b1b5c22
|
|
BLAKE2b-256 checksum How to use checksums |
db7cc420724afe29cac420e01f642b7cefd4f010cbdca9701f80833c970fc85c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl
| Download URL | fn6-0.2.1-cp310-abi3-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 953.0 kB |
| Tags | CPython 3.10 Linux musl 1.2+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
e1eb51e94d05728a89817335c49db052c3f94b693425a24fd6607513745ee625
|
|
BLAKE2b-256 checksum How to use checksums |
ddadcb94de0ec4092429601875bf2e9a94dc268a810f5b57e5284d190da35d73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | fn6-0.2.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 830.5 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
cb100af13f96495cf85d68f5d0950649b6abd4aad47c530893be26f20c26503b
|
|
BLAKE2b-256 checksum How to use checksums |
889a85b0f452b798e2c4e545b04f7f8ef47d182dd08e6ef7b23c38f57d799d17
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl
| Download URL | fn6-0.2.1-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl |
|---|---|
| Size | 847.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ IBM System/390x abi3 |
|
SHA-256 checksum How to use checksums |
99656bcff8d711749057cf2e784a29d93921eb87918926f66a0ffadb478842d8
|
|
BLAKE2b-256 checksum How to use checksums |
3f7c7597e07c702ad4d9fa8f2e78bd14d4a626c745690d0a6b0bd609b9144bbc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl
| Download URL | fn6-0.2.1-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl |
|---|---|
| Size | 812.8 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ PowerPC 64-le abi3 |
|
SHA-256 checksum How to use checksums |
3fef8b8388bbaebb1545a57be741abd9cf9f1cab8798a35b80f1de40498debef
|
|
BLAKE2b-256 checksum How to use checksums |
a9489e5f2029c59e15122147ce2bf423d79d7ba662ebd9fa937f7b78f5e6f5f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
| Download URL | fn6-0.2.1-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl |
|---|---|
| Size | 805.6 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARMv7l abi3 |
|
SHA-256 checksum How to use checksums |
51faab1d98724e36eff0a3ec3a48002e1f04992ed2e23a59871d8d90f93c5143
|
|
BLAKE2b-256 checksum How to use checksums |
d6671b3a958385b8825841640998bfc377641b41e2f4824f2e6b9cba464beb24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | fn6-0.2.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 776.8 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
e1d1cda4ca95463c9edb0f6370e0d6a254c26dbb81281034283f4c6044980894
|
|
BLAKE2b-256 checksum How to use checksums |
afc4c8bffd7f37aaae1d3ddad9aaf97977d32dbffc98769103e351871e1561ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-manylinux_2_12_i686.manylinux2010_i686.whl
| Download URL | fn6-0.2.1-cp310-abi3-manylinux_2_12_i686.manylinux2010_i686.whl |
|---|---|
| Size | 817.0 kB |
| Tags | CPython 3.10 Linux glibc 2.12+ x86-32 abi3 |
|
SHA-256 checksum How to use checksums |
793dde6959a9829a4d8a0bc170fb775ca6b99a519903f009bba6d0f82228868c
|
|
BLAKE2b-256 checksum How to use checksums |
7168483f5681dd677c6ee2c07cbe31342660321c3fd51fbc0eaad0acfeaab2e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|
Release files / fn6-0.2.1-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | fn6-0.2.1-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 368.9 kB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
341a5c10a8aa40cbeac6250306b482e808a5ba01a57e34060967ad97b695ffdd
|
|
BLAKE2b-256 checksum How to use checksums |
b36719632835d8705ae5a0a9b76ad096b3ced597b59deef2f1fe6653aa8c8fdd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.15.0
|