wuxing0105's picture
Add files using upload-large-folder tool
84bcf84 verified
Raw
History Blame Contribute Delete
4.7 kB
"""A Python wrapper for hmmsearch - search profile against a sequence db."""
import os
import tempfile
from absl import logging
from flax_model.alphafold3.data import parsers
from flax_model.alphafold3.data.tools import hmmbuild
from flax_model.alphafold3.data.tools import subprocess_utils
class Hmmsearch(object):
"""Python wrapper of the hmmsearch binary."""
def __init__(
self,
*,
binary_path: str,
hmmbuild_binary_path: str,
database_path: str,
alphabet: str = 'amino',
filter_f1: float | None = None,
filter_f2: float | None = None,
filter_f3: float | None = None,
e_value: float | None = None,
inc_e: float | None = None,
dom_e: float | None = None,
incdom_e: float | None = None,
filter_max: bool = False,
):
"""Initializes the Python hmmsearch wrapper.
Args:
binary_path: The path to the hmmsearch executable.
hmmbuild_binary_path: The path to the hmmbuild executable. Used to build
an hmm from an input a3m.
database_path: The path to the hmmsearch database (FASTA format).
alphabet: Chain type e.g. amino, rna, dna.
filter_f1: MSV and biased composition pre-filter, set to >1.0 to turn off.
filter_f2: Viterbi pre-filter, set to >1.0 to turn off.
filter_f3: Forward pre-filter, set to >1.0 to turn off.
e_value: E-value criteria for inclusion in tblout.
inc_e: E-value criteria for inclusion in MSA/next round.
dom_e: Domain e-value criteria for inclusion in tblout.
incdom_e: Domain e-value criteria for inclusion of domains in MSA/next
round.
filter_max: Remove all filters, will ignore all filter_f* settings.
Raises:
RuntimeError: If hmmsearch binary not found within the path.
"""
self._binary_path = binary_path
self._hmmbuild_runner = hmmbuild.Hmmbuild(
alphabet=alphabet, binary_path=hmmbuild_binary_path
)
self._database_path = database_path
flags = []
if filter_max:
flags.append('--max')
else:
if filter_f1 is not None:
flags.extend(('--F1', filter_f1))
if filter_f2 is not None:
flags.extend(('--F2', filter_f2))
if filter_f3 is not None:
flags.extend(('--F3', filter_f3))
if e_value is not None:
flags.extend(('-E', e_value))
if inc_e is not None:
flags.extend(('--incE', inc_e))
if dom_e is not None:
flags.extend(('--domE', dom_e))
if incdom_e is not None:
flags.extend(('--incdomE', incdom_e))
self._flags = tuple(map(str, flags))
subprocess_utils.check_binary_exists(
path=self._binary_path, name='hmmsearch'
)
if not os.path.exists(self._database_path):
logging.error('Could not find hmmsearch database %s', database_path)
raise ValueError(f'Could not find hmmsearch database {database_path}')
def query_with_hmm(self, hmm: str) -> str:
"""Queries the database using hmmsearch using a given hmm."""
with tempfile.TemporaryDirectory() as query_tmp_dir:
hmm_input_path = os.path.join(query_tmp_dir, 'query.hmm')
sto_out_path = os.path.join(query_tmp_dir, 'output.sto')
with open(hmm_input_path, 'w') as f:
f.write(hmm)
cmd = [
self._binary_path,
'--noali', # Don't include the alignment in stdout.
*('--cpu', '8'),
]
# If adding flags, we have to do so before the output and input:
if self._flags:
cmd.extend(self._flags)
cmd.extend([
*('-A', sto_out_path),
hmm_input_path,
self._database_path,
])
subprocess_utils.run(
cmd=cmd,
cmd_name=f'Hmmsearch ({os.path.basename(self._database_path)})',
log_stdout=False,
log_stderr=True,
log_on_process_error=True,
)
with open(sto_out_path) as f:
a3m_out = parsers.convert_stockholm_to_a3m(
f, remove_first_row_gaps=False, linewidth=60
)
return a3m_out
def query_with_a3m(self, a3m_in: str) -> str:
"""Query the database using hmmsearch using a given a3m."""
# Only the "fast" model construction makes sense with A3M, as it doesn't
# have any way to annotate reference columns.
hmm = self._hmmbuild_runner.build_profile_from_a3m(a3m_in)
return self.query_with_hmm(hmm)
def query_with_sto(
self, msa_sto: str, model_construction: str = 'fast'
) -> str:
"""Queries the database using hmmsearch using a given stockholm msa."""
hmm = self._hmmbuild_runner.build_profile_from_sto(
msa_sto, model_construction=model_construction
)
return self.query_with_hmm(hmm)