Package: pyfastani
🐍⏩🧬 PyFastANICythonbindings and Python interface toFastANI, a method for fast whole-genome similarity estimation.Now with multithreading!🗺️ OverviewFastANI is a method published in 2018 byChirag Jainet al.for high-throughput computation of whole-genomeAverage Nucleotide Identity (ANI).
It usesMashMapto compute orthologous mappings
without the need for expensive alignments.pyfastaniis a Python module, implemented using theCythonlanguage, that provides bindings to FastANI. It directly interacts with the
FastANI internals, which has the following advantages over CLI wrappers:simpler compilation: FastANI requires several additional libraries,
which make compilation of the original binary non-trivial. In PyFastANI,
libraries that were needed for threading or I/O are provided as stubs,
andBoost::mathheaders are vendored so you can build the package without
hassle. Or even better, just install from one of the provided wheels!single dependency: If your software or your analysis pipeline is
distributed as a Python package, you can addpyfastanias a dependency to
your project, and stop worrying about the FastANI binary being present on
the end-user machine.sans I/O: Everything happens in memory, in Python objects you control,
making it easier to pass your sequences to FastANI
without needing to write them to a temporary file.multi-threading: Genome query resolves the fragment mapping step in
parallel, leading to shorter querying times even with a single genome.This library is still a work-in-progress, and in an experimental stage,
but it should already pack enough features to be used in a standard pipeline.🔧 InstallingPyFastANI can be installed directly fromPyPI,
which hosts some pre-built CPython wheels for x86-64 Unix platforms, as well
as the code required to compile from source with Cython:$pipinstallpyfastaniIn the event you have to compile the package from source, all the required
libraries are vendored in the source distribution, so you'll only need a
C/C++ compiler.Otherwise, PyFastANI is also available as aBiocondapackage:$condainstall-cbiocondapyfastani💡 ExampleThe following snippets show how to compute the ANI between two genomes,
with the reference being a draft genome. For one-to-many or many-to-many
searches, simply add additional references withm.add_draftbefore indexing.Note that any name can be given to the reference sequences, this will just
affect thenameattribute of the hits returned for a query.🔬BiopythonBiopython does not let us access to the sequence directly, so we need to
convert it to bytes first with thebytesbuiltin function. For older
versions of Biopython (earlier than 1.79), userecord.seq.encode()instead ofbytes(record.seq).importpyfastaniimportBio.SeqIOsketch=pyfastani.Sketch()# add a single draft genome to the mapper, and index itref=list(Bio.SeqIO.parse("vendor/FastANI/data/Shigella_flexneri_2a_01.fna","fasta"))sketch.add_draft("S. flexneri",(bytes(record.seq)forrecordinref))# index the sketch and get a mappermapper=sketch.index()# read the query and query the mapperquery=Bio.SeqIO.read("vendor/FastANI/data/Escherichia_coli_str_K12_MG1655.fna","fasta")hits=mapper.query_sequence(bytes(query.seq))forhitinhits:print("E. coli K12 MG1655",hit.name,hit.identity,hit.matches,hit.fragments)🧪Scikit-bioScikit-bio lets us access to the sequence directly as anumpyarray, but
shows the values as byte strings by default. To make them readable aschar(for compatibility with the C code), they must be cast withseq.values.view('B').importpyfastaniimportskbio.iosketch=pyfastani.Sketch()ref=list(skbio.io.read("vendor/FastANI/data/Shigella_flexneri_2a_01.fna","fasta"))sketch.add_draft("Shigella_flexneri_2a_01",(seq.values.view('B')forseqinref))mapper=sketch.index()# read the query and query the mapperquery=next(skbio.io.read("vendor/FastANI/data/Escherichia_coli_str_K12_MG1655.fna","fasta"))hits=mapper.query_genome(query.values.view('B'))forhitinhits:print("E. coli K12 MG1655",hit.name,hit.identity,hit.matches,hit.fragments)⏱️ BenchmarksIn the original FastANI tool, multi-threading was only used to improve the
performance of many-to-many searches: each thread would have a chunk of the
reference genomes, and querying would be done in parallel for each reference.
However, with a small set of reference genomes, there may not be enough for
all the threads to work, so it cannot scale with a large number of threads. In
addition, this causes the same query genome to be hashed several times, which
is not optimal. Inpyfastani, multi-threading is used to compute the hashes and mapping of query genome fragments. This allows parallelism to be useful even
when a only few reference genomes are available.The benchmarks below show the time for querying a single genome (withMapper.query_draft) using a variable number of threads.Benchmarks
were run on ai7-8550U CPUrunning @1.80GHz with 4 physical / 8 logical
cores, using 50 bacterial genomes from theproGenomesdatabase.
For clarity, only 5 randomly-selected genomes are shown on the second graph. Each run was repeated 3 times.🔖 CitationPyFastANI is scientific software; it was presented among other optimized
software at theEuropean Student Council Symposium (ESCS) 2022duringECCB 2022. Please
cite bothPyFastANIandFastANIif you are using it in an academic work,
for instance as:PyFastANI (Larralde, 2022), a Python library with optimized bindings to FastANI (Jainet al., 2018).🔎 See AlsoComputing ANI for metagenomic sequences? You may be interested inpyskani, a Python package for computing ANIusing theskanimethoddeveloped byJim ShawandYun William Yu.💭 Feedback⚠️ Issue TrackerFound a bug ? Have an enhancement request ? Head over to theGitHub issue
trackerif you need to report
or ask something. If you are filing in on a bug, please include as much
information as you can about the issue, and try to recreate the same bug
in a simple, easily reproducible situation.🏗️ ContributingContributions are more than welcome! SeeCONTRIBUTING.mdfor more details.⚖️ LicenseThis library is provided under theMIT License.The FastANI code was written byChirag Jainand is distributed under the terms of theApache License 2.0,
unless otherwise specified in vendored sources. Seevendor/FastANI/LICENSEfor more information.
Thecpu_featurescode was written byGuillaume Chateletand is distributed under the terms of theApache License 2.0.
Seevendor/cpu_features/LICENSEfor more information.
TheBoost::mathheaders were written byBoost Librariescontributors
and is distributed under the terms of theBoost Software License.
Seevendor/boost-math/LICENSEfor more information.This project is in no way not affiliated, sponsored, or otherwise endorsed
by theoriginal FastANI authors. It was developed byMartin Larraldeduring his PhD project
at theEuropean Molecular Biology Laboratoryin
theZeller team.