|
|
|
|
| """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', |
| *('--cpu', '8'), |
| ] |
| |
| 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.""" |
|
|
| |
| |
| 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) |
|
|