From 438093e4b591e297c097f9f24e60d50060be5662 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 09:02:57 +0200 Subject: [PATCH 01/17] feat: pass MMseqs2 db_load_mode through to search and result2msa MMseqs2 reads the whole target database into RSS unless told otherwise; mode 2 memory-maps it instead. The workflow config documented db_load_mode but nothing read it, and there was no core flag to receive it. It reaches both commands, since both read the target database. It is a process-level setting on the adapter rather than part of MsaBatchSettings, because it changes memory behaviour and never the alignment: two runs differing only here must keep reusing each other's bundles, so it is kept out of the cache signature by construction, and a test asserts that on two real adapters. Unset, nothing is passed and MMseqs2 chooses as before. Co-Authored-By: Claude Opus 5 (1M context) --- alphapulldown/feature_batch.py | 21 ++- alphapulldown/scripts/_mmseqs2_cli.py | 10 ++ .../scripts/create_batch_features.py | 4 +- alphapulldown/scripts/create_batch_msas.py | 4 +- test/unit/test_mmseqs_process_options.py | 141 ++++++++++++++++++ 5 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 test/unit/test_mmseqs_process_options.py diff --git a/alphapulldown/feature_batch.py b/alphapulldown/feature_batch.py index 32fbdb2e..acc2f006 100644 --- a/alphapulldown/feature_batch.py +++ b/alphapulldown/feature_batch.py @@ -379,9 +379,26 @@ def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: .. class SubprocessMmseqsProcess: """Production adapter for one local MMseqs2 executable.""" - def __init__(self, binary_path: str | Path, *, gpu: bool = True): + def __init__( + self, + binary_path: str | Path, + *, + gpu: bool = True, + db_load_mode: int | None = None, + ): self._binary_path = str(binary_path) self._gpu = gpu + # How MMseqs2 reads the target database (0 auto, 1 fread, 2 mmap, + # 3 mmap+touch). Deliberately a process-level setting rather than part of + # MsaBatchSettings: it changes memory behaviour and nothing else, so it + # must never reach the cache signature. Two runs that differ only here + # produce the same alignment and must keep reusing each other's bundles. + self._db_load_mode = db_load_mode + + def _db_load_mode_option(self) -> tuple[str, ...]: + if self._db_load_mode is None: + return () + return ("--db-load-mode", str(self._db_load_mode)) def _run(self, command: Sequence[str]) -> str: try: @@ -459,6 +476,7 @@ def search( if settings.split_memory_limit else () ) + + self._db_load_mode_option() ) def result_to_msa( @@ -478,6 +496,7 @@ def result_to_msa( "--msa-format-mode", "2", ) + + self._db_load_mode_option() ) def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: diff --git a/alphapulldown/scripts/_mmseqs2_cli.py b/alphapulldown/scripts/_mmseqs2_cli.py index babe96e0..0377a9b5 100644 --- a/alphapulldown/scripts/_mmseqs2_cli.py +++ b/alphapulldown/scripts/_mmseqs2_cli.py @@ -110,6 +110,16 @@ def define_msa_search_flags( 8, "CPU threads for MMseqs2 operations.", ) + _define_once( + "mmseqs_db_load_mode", + flags.DEFINE_integer, + None, + "How MMseqs2 reads the target database: 0 auto, 1 fread, 2 mmap, " + "3 mmap+touch. Left unset MMseqs2 chooses, which reads the whole target " + "database into RSS; 2 memory-maps it instead and lowers peak memory. It " + "changes memory behaviour only, never the alignment, so it is not part of " + "the MSA cache identity and switching it reuses existing bundles.", + ) _define_once( "mmseqs_rna_e_value", flags.DEFINE_float, diff --git a/alphapulldown/scripts/create_batch_features.py b/alphapulldown/scripts/create_batch_features.py index 84c4f749..25735216 100644 --- a/alphapulldown/scripts/create_batch_features.py +++ b/alphapulldown/scripts/create_batch_features.py @@ -93,7 +93,9 @@ def main(argv) -> None: template_mmcif_database_id=FLAGS.template_mmcif_database_id, ), mmseqs_process=SubprocessMmseqsProcess( - FLAGS.mmseqs_binary_path, gpu=FLAGS.mmseqs_use_gpu + FLAGS.mmseqs_binary_path, + gpu=FLAGS.mmseqs_use_gpu, + db_load_mode=FLAGS.mmseqs_db_load_mode, ), af3_pipeline=pipeline, ).generate(requests) diff --git a/alphapulldown/scripts/create_batch_msas.py b/alphapulldown/scripts/create_batch_msas.py index fe61ddeb..4ed43be0 100644 --- a/alphapulldown/scripts/create_batch_msas.py +++ b/alphapulldown/scripts/create_batch_msas.py @@ -57,7 +57,9 @@ def main(argv) -> None: result = MsaBatch( settings=settings, mmseqs_process=SubprocessMmseqsProcess( - FLAGS.mmseqs_binary_path, gpu=FLAGS.mmseqs_use_gpu + FLAGS.mmseqs_binary_path, + gpu=FLAGS.mmseqs_use_gpu, + db_load_mode=FLAGS.mmseqs_db_load_mode, ), ).generate(requests) logging.info( diff --git a/test/unit/test_mmseqs_process_options.py b/test/unit/test_mmseqs_process_options.py new file mode 100644 index 00000000..45b5864e --- /dev/null +++ b/test/unit/test_mmseqs_process_options.py @@ -0,0 +1,141 @@ +"""Process-level MMseqs2 options, and which of them may touch the cache identity. + +Deliberately free of any AlphaFold 3 import: the search stage runs in the +AlphaFold 2 image too, and a module-level skip there would report success while +silently testing nothing. The equivalent assertions in ``test_feature_batch.py`` +cannot run in that image because that module needs AlphaFold 3 for the finalizer. +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from alphapulldown.feature_batch import ( + DatabaseSpec, + MsaBatch, + MsaBatchSettings, + SubprocessMmseqsProcess, +) + + +PROTEIN_DATABASES = ("uniref90", "mgnify", "small_bfd") + + +@pytest.fixture +def recording_binary(tmp_path: Path) -> tuple[Path, Path]: + """A stand-in executable that records the arguments it was called with.""" + binary = tmp_path / "mmseqs" + binary.write_text( + '#!/bin/sh\nprintf \'%s\\n\' "$@" > "${0}.arguments"\n', encoding="utf-8" + ) + binary.chmod(0o755) + return binary, Path(f"{binary}.arguments") + + +def _settings(tmp_path: Path) -> MsaBatchSettings: + return MsaBatchSettings( + output_dir=tmp_path / "out", + temp_dir=tmp_path / "tmp", + unpaired_databases=tuple( + DatabaseSpec(name=name, path=tmp_path / name, identifier=f"{name}-fixture") + for name in PROTEIN_DATABASES + ), + paired_database=DatabaseSpec( + name="uniprot", path=tmp_path / "uniprot", identifier="uniprot-fixture" + ), + max_sequences_per_batch=8, + max_residues_per_batch=10_000, + threads=4, + ) + + +def _database(tmp_path: Path) -> DatabaseSpec: + return DatabaseSpec( + name="uniref90", path=tmp_path / "uniref90", identifier="fixture" + ) + + +def test_db_load_mode_reaches_the_search(tmp_path: Path, recording_binary): + binary, arguments = recording_binary + SubprocessMmseqsProcess(binary, db_load_mode=2).search( + tmp_path / "query", + _database(tmp_path), + tmp_path / "result", + tmp_path / "work", + _settings(tmp_path), + ) + command = arguments.read_text(encoding="utf-8").splitlines() + assert command[command.index("--db-load-mode") + 1] == "2" + + +def test_db_load_mode_reaches_result_to_msa(tmp_path: Path, recording_binary): + # Both commands read the target database, so both must honour the setting; + # passing it only to the search would leave the peak memory it exists to + # lower untouched in the second half of the stage. + binary, arguments = recording_binary + SubprocessMmseqsProcess(binary, db_load_mode=2).result_to_msa( + tmp_path / "query", + _database(tmp_path), + tmp_path / "result", + tmp_path / "msa", + ) + command = arguments.read_text(encoding="utf-8").splitlines() + assert command[command.index("--db-load-mode") + 1] == "2" + + +@pytest.mark.parametrize("operation", ("search", "result_to_msa")) +def test_the_option_is_absent_when_unset( + tmp_path: Path, recording_binary, operation: str +): + """Unset must mean "say nothing", so MMseqs2 keeps choosing for itself.""" + binary, arguments = recording_binary + process = SubprocessMmseqsProcess(binary) + if operation == "search": + process.search( + tmp_path / "query", + _database(tmp_path), + tmp_path / "result", + tmp_path / "work", + _settings(tmp_path), + ) + else: + process.result_to_msa( + tmp_path / "query", + _database(tmp_path), + tmp_path / "result", + tmp_path / "msa", + ) + assert "--db-load-mode" not in arguments.read_text().splitlines() + + +def test_db_load_mode_stays_out_of_the_cache_signature(tmp_path: Path): + """It changes memory behaviour, never the alignment. + + If it reached the signature, turning it on to survive a tight allocation + would discard every alignment already computed -- a re-search costing hours + per shard to produce byte-identical output. Asserted on two real adapters + that differ in exactly this one setting. + """ + binary = tmp_path / "mmseqs" + binary.write_text("#!/bin/sh\necho mmseqs-fixture-version\n", encoding="utf-8") + binary.chmod(0o755) + settings = _settings(tmp_path) + + plain = MsaBatch( + settings=settings, mmseqs_process=SubprocessMmseqsProcess(binary) + ) + mapped = MsaBatch( + settings=settings, + mmseqs_process=SubprocessMmseqsProcess(binary, db_load_mode=2), + ) + assert plain._cache_signature() == mapped._cache_signature() + + # The comparison above is only meaningful if a setting that DOES change the + # alignment moves the signature. GPU and CPU search are such a setting. + on_cpu = MsaBatch( + settings=settings, + mmseqs_process=SubprocessMmseqsProcess(binary, gpu=False), + ) + assert plain._cache_signature() != on_cpu._cache_signature() From 82c4e8700652fa659fc820c4da06ad6117fb3983 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 09:03:15 +0200 Subject: [PATCH 02/17] feat: recover MSA insertions with a two-pass result2msa format Every local MMseqs2 MSA had an all-zero deletion matrix. result2msa mode 2, the only format we ran, keeps full database headers but drops every column the query does not span, so no insertion ever reached AlphaFold. Against a real 586-residue query that was 98 of 120 small_bfd hits (81.7%) and 712 of 824 uniprot hits (86.4%), 13035 residues on uniprot alone. The code assumed mode 2 delivered insertions as query-gap columns and converted them; the pinned build never emits one, so that path never ran on real data. Mode 5 keeps the insertions but cuts the header to the database key, so sp|P83570|GWA_SEPOF becomes P83570 -- and AlphaFold reads the species it pairs chains by out of the long form. Neither format alone is usable, so each result is formatted both ways and joined row by row. The join is verified, not trusted: stripping insertions from every mode-5 row must reproduce its mode-2 row, and a disagreement fails the request instead of labelling one hit with another's header. The second pass costs about 16 ms a hit (2 s against a 947 s search on small_bfd, 13 s against 3739 s on uniprot). RNA takes the same route. This also removes the last AlphaFold 3 dependency from the search stage. It converted rows with alphafold3.cpp.msa_conversion, which the AlphaFold 2 image does not have, so the stage imported there and died on its first result. The bundle, now schema 3, also records how many unpaired rows each database contributed. AlphaFold 3 does not need it; an AlphaFold 2 consumer does, since it searches templates from uniref90 alone and caps each database separately. A bundle whose counts do not add up is searched again rather than sliced wrongly. Provenance moves (protein schema 5, RNA 2, plus msa_format), so no bundle written before this is reused. The only workflow cache that existed held two bundles of e2e test data. Co-Authored-By: Claude Opus 5 (1M context) --- CONTEXT.md | 3 +- alphapulldown/feature_batch.py | 269 ++++++++++++++---- alphapulldown/utils/msa_formats.py | 91 ++++++ .../test_mmseqs2_command_contract.py | 48 +++- test/unit/data/small_bfd.mode2.txt | 240 ++++++++++++++++ test/unit/data/small_bfd.mode5.txt | 240 ++++++++++++++++ test/unit/data/uniprot.mode2.txt | 120 ++++++++ test/unit/data/uniprot.mode5.txt | 120 ++++++++ test/unit/test_feature_batch.py | 158 +++++++++- test/unit/test_feature_batch_rna.py | 37 ++- test/unit/test_light_import_invariant.py | 45 +++ test/unit/test_msa_formats.py | 171 +++++++++++ workflows/mmseqs2-gpu.md | 20 +- 13 files changed, 1473 insertions(+), 89 deletions(-) create mode 100644 alphapulldown/utils/msa_formats.py create mode 100644 test/unit/data/small_bfd.mode2.txt create mode 100644 test/unit/data/small_bfd.mode5.txt create mode 100644 test/unit/data/uniprot.mode2.txt create mode 100644 test/unit/data/uniprot.mode5.txt create mode 100644 test/unit/test_msa_formats.py diff --git a/CONTEXT.md b/CONTEXT.md index 9e300788..cd1f8aad 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -20,7 +20,8 @@ - **Feature batch**: an ordered collection of feature requests handled as one operation. - **MSA batch**: the GPU stage that searches MMseqs2 and durably publishes one reusable MSA bundle per feature request. - **Feature finalization**: the CPU stage that reads an MSA bundle, performs native AF3 template search, and publishes the standard AF3 feature artifact. -- **MSA bundle**: an atomic intermediate JSON containing one sequence, merged unpaired A3M, paired A3M, and complete MMseqs/database provenance. +- **MSA bundle**: an atomic intermediate JSON containing one sequence, merged unpaired A3M, paired A3M, how many unpaired rows each database contributed, and complete MMseqs/database provenance. Its A3Ms carry both full database headers and insertions. +- **Two-pass format**: formatting one MMseqs2 search result twice and joining the passes row by row, because the format with full headers drops insertions and the format with insertions drops the headers. - **Database identifier**: the caller-supplied immutable identity of one MMseqs2 database build; cache validity depends on it, not only its filesystem path. - **Feature artifact**: the standard AlphaFold 3 JSON (optionally LZMA-compressed) produced for one feature request. - **MSA cache hit**: an existing MSA bundle whose sequence, MMseqs2 executable version, search settings, and database identifiers match the request. diff --git a/alphapulldown/feature_batch.py b/alphapulldown/feature_batch.py index acc2f006..213d71e3 100644 --- a/alphapulldown/feature_batch.py +++ b/alphapulldown/feature_batch.py @@ -19,6 +19,11 @@ embed_metadata_in_af3_json, extract_metadata_from_af3_json, ) +from alphapulldown.utils.msa_formats import ( + StitchMismatch, + stitch_headers_and_insertions, + strip_insertions, +) PROTEIN = "protein" @@ -64,6 +69,12 @@ # future GPU-capable nucleotide search does not silently reuse these bundles. NUCLEOTIDE_SEARCH_MODE = "cpu" +# How the alignment text was produced, recorded in every bundle's provenance. +# Bundles written before insertions were recovered came from mode 2 alone and carry +# none -- 81.7% of small_bfd hits and 86.4% of uniprot hits lost theirs, measured on +# a real 586-residue query -- so they must never satisfy a request made now. +_MSA_FORMAT = {"headers": "result2msa mode 2", "sequences": "result2msa mode 5"} + def _describe_exit(returncode) -> str: """Say what an MMseqs2 exit code means, especially when it died on a signal. @@ -283,6 +294,19 @@ class MsaFailure: error: str +@dataclasses.dataclass(frozen=True, slots=True) +class SearchedMsas: + """What one search produced for one sequence, before it becomes a bundle.""" + + unpaired: str + paired: str + # How many rows of ``unpaired`` each database contributed, in merge order and + # after deduplication. The query row belongs to none of them. AlphaFold 2 builds + # its template profile from uniref90 ALONE and caps each database separately, so + # the merged alignment is unusable to it unless these boundaries are kept. + unpaired_rows: tuple[tuple[str, int], ...] = () + + @dataclasses.dataclass(frozen=True, slots=True) class MsaBatchResult: written: tuple[MsaArtifact, ...] @@ -371,7 +395,19 @@ def result_to_msa( database: DatabaseSpec, result_db: Path, msa_db: Path, - ) -> None: ... + ) -> None: + """Format the hits with their full database headers and no insertions.""" + ... + + def result_to_a3m( + self, + query_db: Path, + database: DatabaseSpec, + result_db: Path, + msa_db: Path, + ) -> None: + """Format the same hits as A3M: insertions kept, headers cut to one token.""" + ... def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: ... @@ -499,6 +535,30 @@ def result_to_msa( + self._db_load_mode_option() ) + def result_to_a3m( + self, + query_db: Path, + database: DatabaseSpec, + result_db: Path, + msa_db: Path, + ) -> None: + # Mode 5 is the only format that keeps insertions, and it keeps nothing of + # the header but the database key -- so it is run alongside mode 2, not + # instead of it. Measured at 2 s against a 947 s search on small_bfd and + # 13 s against 3739 s on uniprot, roughly 16 ms per hit. + self._run( + ( + "result2msa", + str(query_db), + str(database.path), + str(result_db), + str(msa_db), + "--msa-format-mode", + "5", + ) + + self._db_load_mode_option() + ) + def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: del query_db self._run( @@ -550,7 +610,7 @@ def generate(self, requests: Sequence[FeatureRequest]) -> MsaBatchResult: missing_requests = [] # Keyed by molecule type as well as sequence: the same letters searched as a # protein and as RNA are two different searches with two different answers. - msa_by_sequence: dict[tuple[str, str], tuple[str, str]] = {} + msa_by_sequence: dict[tuple[str, str], SearchedMsas] = {} for request in requests: cached = self._read_matching_msa(request) if cached is None: @@ -559,8 +619,7 @@ def generate(self, requests: Sequence[FeatureRequest]) -> MsaBatchResult: path, payload = cached reused.append(MsaArtifact(name=request.name, path=path)) msa_by_sequence.setdefault( - _request_key(request), - (payload["unpairedMsa"], payload["pairedMsa"]), + _request_key(request), _searched_msas_from_payload(payload) ) sequence_to_requests: dict[tuple[str, str], list[FeatureRequest]] = {} @@ -576,7 +635,7 @@ def generate(self, requests: Sequence[FeatureRequest]) -> MsaBatchResult: continue for request in matching_requests: try: - payload = self._msa_payload(request, *cached_msas) + payload = self._msa_payload(request, cached_msas) path = self._msa_path(request.name) _write_atomic(path, payload) written.append(MsaArtifact(name=request.name, path=path)) @@ -612,7 +671,7 @@ def generate(self, requests: Sequence[FeatureRequest]) -> MsaBatchResult: for sequence, msas in chunk_msas.items(): for request in sequence_to_requests[(molecule_type, sequence)]: try: - payload = self._msa_payload(request, *msas) + payload = self._msa_payload(request, msas) path = self._msa_path(request.name) _write_atomic(path, payload) written.append(MsaArtifact(name=request.name, path=path)) @@ -686,6 +745,10 @@ def _read_matching_msa( payload.get("pairedMsa"), str ): return None + # Raises on a bundle whose row spans are missing or do not add up, so a + # damaged one is re-searched instead of handed on to a consumer that + # would slice it at the wrong rows. + _searched_msas_from_payload(payload) return path, payload except ( KeyError, @@ -785,7 +848,7 @@ def _pack(self, sequences: Sequence[str]) -> tuple[tuple[str, ...], ...]: def _search_chunk( self, sequences: Sequence[str], molecule_type: str = PROTEIN - ) -> dict[str, tuple[str, str]]: + ) -> dict[str, SearchedMsas]: unpaired_databases, paired_database = self._databases(molecule_type) with tempfile.TemporaryDirectory( prefix="alphapulldown_mmseqs_", dir=self._settings.temp_dir @@ -820,24 +883,33 @@ def _search_chunk( result_db = database_root / "result_db" work_dir = database_root / "work" work_dir.mkdir() - msa_db = database_root / "msa_db" - output_dir = database_root / "a3m" - output_dir.mkdir() self._mmseqs.search( query_db, database, result_db, work_dir, self._settings ) - self._mmseqs.result_to_msa(query_db, database, result_db, msa_db) - self._mmseqs.unpack_msa(query_db, msa_db, output_dir) + # One search, formatted twice: headers from one pass, insertions + # from the other. See msa_formats for why neither alone will do. + headers_db = database_root / "headers_db" + headers_dir = database_root / "headers" + headers_dir.mkdir() + self._mmseqs.result_to_msa(query_db, database, result_db, headers_db) + self._mmseqs.unpack_msa(query_db, headers_db, headers_dir) + insertions_db = database_root / "insertions_db" + insertions_dir = database_root / "insertions" + insertions_dir.mkdir() + self._mmseqs.result_to_a3m( + query_db, database, result_db, insertions_db + ) + self._mmseqs.unpack_msa(query_db, insertions_db, insertions_dir) by_database[database.name] = self._read_results( - query_db, output_dir, query_ids, molecule_type + query_db, headers_dir, insertions_dir, query_ids, molecule_type ) results = {} for query_id, sequence in query_ids.items(): - unpaired = _merge_a3ms( + unpaired, unpaired_rows = _merge_a3ms( sequence, [ - by_database[database.name][query_id] + (database.name, by_database[database.name][query_id]) for database in unpaired_databases ], ) @@ -848,13 +920,16 @@ def _search_chunk( if paired_database is not None else "" ) - results[sequence] = (unpaired, paired) + results[sequence] = SearchedMsas( + unpaired=unpaired, paired=paired, unpaired_rows=unpaired_rows + ) return results @staticmethod def _read_results( query_db: Path, - output_dir: Path, + headers_dir: Path, + insertions_dir: Path, query_ids: Mapping[str, str], molecule_type: str = PROTEIN, ) -> dict[str, str]: @@ -870,10 +945,7 @@ def _read_results( str(index): query_id for index, query_id in enumerate(query_ids) } - results = {} - for index, query_id in index_to_query.items(): - if query_id not in query_ids: - continue + def unpacked_records(output_dir: Path, index: str, query_id: str): candidates = ( output_dir / f"{index}.fasta", output_dir / f"{index}.a3m", @@ -887,14 +959,29 @@ def _read_results( "MMseqs2 unpackdb did not produce an alignment for " f"{query_id!r} in {output_dir.parent.name!r}" ) - aligned_fasta = result_path.read_text(encoding="utf-8") - if not _fasta_records(aligned_fasta): + records = _fasta_records(result_path.read_text(encoding="utf-8")) + if not records: raise RuntimeError( "MMseqs2 unpackdb produced no FASTA records for " f"{query_id!r} in {output_dir.parent.name!r}" ) - results[query_id] = _aligned_fasta_to_a3m( - aligned_fasta, query_ids[query_id], molecule_type + return records + + results = {} + for index, query_id in index_to_query.items(): + if query_id not in query_ids: + continue + try: + stitched = stitch_headers_and_insertions( + unpacked_records(headers_dir, index, query_id), + unpacked_records(insertions_dir, index, query_id), + ) + except StitchMismatch as exc: + raise RuntimeError( + f"{query_id!r} in {headers_dir.parent.name!r}: {exc}" + ) from exc + results[query_id] = _stitched_to_a3m( + stitched, query_ids[query_id], molecule_type ) missing_queries = set(query_ids) - set(results) if missing_queries: @@ -905,16 +992,19 @@ def _read_results( return results def _msa_payload( - self, request: FeatureRequest, unpaired_msa: str, paired_msa: str + self, request: FeatureRequest, msas: SearchedMsas ) -> dict[str, Any]: payload = { - "schemaVersion": 2, + "schemaVersion": 3, "name": request.name, "sequence": request.sequence, - "unpairedMsa": unpaired_msa, - "pairedMsa": paired_msa, - "unpairedDepth": _msa_depth(unpaired_msa), - "pairedDepth": _msa_depth(paired_msa), + "unpairedMsa": msas.unpaired, + "pairedMsa": msas.paired, + "unpairedDepth": _msa_depth(msas.unpaired), + "pairedDepth": _msa_depth(msas.paired), + "unpairedDatabaseRows": [ + {"name": name, "rows": rows} for name, rows in msas.unpaired_rows + ], "provenance": self._cache_signature(request.molecule_type), } # Only non-protein bundles record their molecule type, so a protein bundle is @@ -939,10 +1029,11 @@ def database_value(database: DatabaseSpec) -> dict[str, Any]: if molecule_type == RNA: return { - "schema_version": 1, + "schema_version": 2, "molecule_type": RNA, "mmseqs_identity": self._process_identity(), "search_mode": NUCLEOTIDE_SEARCH_MODE, + "msa_format": _MSA_FORMAT, "e_value": self._settings.rna_e_value, "unpaired_databases": [ database_value(database) @@ -951,9 +1042,10 @@ def database_value(database: DatabaseSpec) -> dict[str, Any]: } signature = { - "schema_version": 4, + "schema_version": 5, "mmseqs_identity": self._process_identity(), "search_mode": self._search_mode(), + "msa_format": _MSA_FORMAT, "e_value": self._settings.e_value, "unpaired_databases": [ database_value(database) @@ -1325,33 +1417,40 @@ def _transcribe(sequence: str) -> str: return sequence.replace("T", "U").replace("t", "u") -def _aligned_fasta_to_a3m( - aligned_fasta: str, query_sequence: str, molecule_type: str = PROTEIN +def _stitched_to_a3m( + records: Sequence[tuple[str, str]], + query_sequence: str, + molecule_type: str = PROTEIN, ) -> str: - """Remove query-gap columns while retaining insertions and full headers.""" - from alphafold3.cpp import msa_conversion - - records = _fasta_records(aligned_fasta) + """Validate stitched A3M records against the query and write them out. + + The mode-5 sequences are already A3M against the gapless query, so nothing is + rewritten. What is checked is that every row spans exactly the query: a row + whose match columns number anything else would silently shift every residue + after the discrepancy once AlphaFold reads it as a table. The stitch already + implies this -- mode 2 rows equal mode 5 rows minus insertions -- but a + malformed row should fail here with the query named, not deep in a parser. + """ if not records: - raise ValueError("MMseqs2 aligned FASTA contains no records") - query_alignment = records[0][1] + raise ValueError("MMseqs2 alignment contains no records") normalise = _transcribe if molecule_type == RNA else (lambda sequence: sequence) - if normalise( - query_alignment.replace("-", "").replace(".", "").upper() - ) != normalise(query_sequence.upper()): - raise ValueError( - "MMseqs2 aligned FASTA query does not match its input sequence" - ) + query_row = strip_insertions(records[0][1]) + if normalise(query_row.replace("-", "").upper()) != normalise( + query_sequence.upper() + ): + raise ValueError("MMseqs2 alignment query does not match its input sequence") converted = [] for description, sequence in records: - a3m_sequence = msa_conversion.align_sequence_to_gapless_query( - sequence=sequence, - query_sequence=query_alignment, - ).replace(".", "") + if len(strip_insertions(sequence)) != len(query_sequence): + raise ValueError( + f"MMseqs2 row {description.split()[0]!r} spans " + f"{len(strip_insertions(sequence))} query positions, not " + f"{len(query_sequence)}" + ) if molecule_type == RNA: - a3m_sequence = _transcribe(a3m_sequence) - converted.append(f">{description}\n{a3m_sequence}\n") + sequence = _transcribe(sequence) + converted.append(f">{description}\n{sequence}\n") return "".join(converted) @@ -1363,13 +1462,65 @@ def _normalise_query(a3m: str, query_sequence: str) -> str: return "".join(f">{description}\n{sequence}\n" for description, sequence in records) -def _merge_a3ms(query_sequence: str, a3ms: Sequence[str]) -> str: +def _merge_a3ms( + query_sequence: str, a3ms: Sequence[tuple[str, str]] +) -> tuple[str, tuple[tuple[str, int], ...]]: + """Merge per-database A3Ms in order, and say how many rows each contributed. + + Rows are deduplicated on their aligned residues with the insertions removed. + That is the key this stage used before insertions were recovered, when the two + were the same string, so a merged alignment keeps exactly the rows it kept + then and only their content grows. Keying on the full row instead would keep a + second copy of every hit that two databases aligned with different insertions. + + Databases are appended whole, one after another, so each one's rows are + contiguous and a count is enough to recover them. + """ rows = [("query", query_sequence)] seen = {query_sequence} - for a3m in a3ms: - for _, (description, sequence) in enumerate(_fasta_records(a3m)): - if sequence in seen: + contributed = [] + for database_name, a3m in a3ms: + added = 0 + for description, sequence in _fasta_records(a3m): + key = strip_insertions(sequence) + if key in seen: continue - seen.add(sequence) + seen.add(key) rows.append((description, sequence)) - return "".join(f">{description}\n{sequence}\n" for description, sequence in rows) + added += 1 + contributed.append((database_name, added)) + text = "".join(f">{description}\n{sequence}\n" for description, sequence in rows) + return text, tuple(contributed) + + +def _searched_msas_from_payload(payload: Mapping[str, Any]) -> SearchedMsas: + """Read a bundle back, refusing row spans that do not describe its alignment. + + The spans are what a consumer slices by, so a wrong count does not fail -- it + hands AlphaFold 2 the wrong database's rows as uniref90. Check that they add up. + """ + unpaired = payload["unpairedMsa"] + raw_rows = payload.get("unpairedDatabaseRows") + if not isinstance(raw_rows, list): + raise ValueError("MSA bundle lacks unpairedDatabaseRows") + rows = [] + for entry in raw_rows: + if ( + not isinstance(entry, Mapping) + or not isinstance(entry.get("name"), str) + or not isinstance(entry.get("rows"), int) + or isinstance(entry.get("rows"), bool) + or entry["rows"] < 0 + ): + raise ValueError(f"MSA bundle has a malformed row span: {entry!r}") + rows.append((entry["name"], entry["rows"])) + # The query row belongs to no database. + if unpaired and sum(count for _, count in rows) != _msa_depth(unpaired) - 1: + raise ValueError( + "MSA bundle row spans account for " + f"{sum(count for _, count in rows)} rows but the alignment has " + f"{_msa_depth(unpaired) - 1} besides the query" + ) + return SearchedMsas( + unpaired=unpaired, paired=payload["pairedMsa"], unpaired_rows=tuple(rows) + ) diff --git a/alphapulldown/utils/msa_formats.py b/alphapulldown/utils/msa_formats.py new file mode 100644 index 00000000..4fafb74c --- /dev/null +++ b/alphapulldown/utils/msa_formats.py @@ -0,0 +1,91 @@ +"""Turn MMseqs2 output into A3M that keeps both its headers and its insertions. + +No AlphaFold dependency of any kind. The search stage used to convert results +with ``alphafold3.cpp.msa_conversion``, and the AlphaFold 2 image installs +AlphaPulldown without the ``alphafold3`` extra, so the shared stage imported +cleanly there and then died on the first search result. + +The formats. ``mmseqs result2msa`` offers several, and none gives both things an +AlphaFold alignment needs. Measured on the pinned build +(8cc5ce367b5638c4306c2d7cfc652dd099a4643f), with a target carrying a deliberate +four-residue insertion:: + + mode 2 >sp|P00002|INSERT_MOUSE has a 4-residue insertion OS=Mus musculus + MKTAYIAKQRQISFVKSHFSRQLEE... <- the WWWW is gone + mode 5 >P00002 + MKTAYIAKQRQISFVKSHwwwwFSRQLEE... <- kept, as an A3M insertion + +Mode 2 keeps the full header and drops every column the query does not span, so +an alignment built from it alone has no insertions and AlphaFold derives an +all-zero deletion matrix from it. That is not a small detail: against a real +586-residue query, 98 of 120 small_bfd hits (81.7%) and 712 of 824 uniprot hits +(86.4%) carry insertions, 13035 residues of them on uniprot alone. + +Mode 5 keeps the insertions and cuts the header to the database key. How much +that loses depends on the FASTA the database was built from: small_bfd headers +are a single token and survive whole, but uniprot's ``sp|P83570|GWA_SEPOF …`` +becomes ``P83570`` -- and AlphaFold 2 reads the species out of the long form, and +species is what pairs chains in a complex. The same holds for nucleotide +searches, so RNA takes the same route. + +So both are run over one search result and joined by +:func:`stitch_headers_and_insertions`. The second pass costs little: 2 s against +a 947 s search on small_bfd, 13 s against 3739 s on uniprot, roughly 16 ms a hit. +""" + +from __future__ import annotations + +from typing import Sequence + + +def strip_insertions(a3m_row: str) -> str: + """Drop the insertion residues, leaving one column per query position.""" + return "".join(residue for residue in a3m_row if not residue.islower()) + + +class StitchMismatch(ValueError): + """Two result2msa passes over one result set disagreed about their rows.""" + + +def stitch_headers_and_insertions( + headers_from: Sequence[tuple[str, str]], + insertions_from: Sequence[tuple[str, str]], +) -> list[tuple[str, str]]: + """Join mode-2 headers to mode-5 sequences, verifying the join row by row. + + Both arguments are ``(description, sequence)`` records read from one search + result formatted twice: ``headers_from`` carries the full database headers and + no insertions, ``insertions_from`` carries the insertions and a bare accession. + MMseqs2 emits both in result order, so they line up positionally. + + Positional joins are exactly the kind that rot silently, so this one is + checked rather than trusted: removing the insertions from a mode-5 row has to + reproduce the mode-2 row character for character, on every row. If a future + MMseqs2 ever reorders, filters or realigns one pass and not the other, this + raises instead of emitting a chimeric alignment in which headers describe the + wrong sequences -- which for the paired database would mean pairing chains by + the wrong species, a wrong answer that looks entirely plausible. + + Verified against real data: 120/120 rows on small_bfd, and 31/31 on a + synthetic set built with random insertions and deletions. + """ + if len(headers_from) != len(insertions_from): + raise StitchMismatch( + "the two result2msa passes returned different row counts " + f"({len(headers_from)} with headers, {len(insertions_from)} with " + "insertions); they cannot describe the same search result" + ) + stitched = [] + for index, ((description, aligned), (_, with_insertions)) in enumerate( + zip(headers_from, insertions_from) + ): + if strip_insertions(with_insertions) != aligned: + raise StitchMismatch( + f"row {index} differs between the two result2msa passes: " + f"{strip_insertions(with_insertions)!r} from the insertion pass " + f"does not match {aligned!r} from the header pass. The two are " + "no longer in the same order, so headers cannot be trusted to " + "describe these sequences" + ) + stitched.append((description, with_insertions)) + return stitched diff --git a/test/integration/test_mmseqs2_command_contract.py b/test/integration/test_mmseqs2_command_contract.py index 2313267d..7aecb998 100644 --- a/test/integration/test_mmseqs2_command_contract.py +++ b/test/integration/test_mmseqs2_command_contract.py @@ -11,14 +11,12 @@ pytestmark = [pytest.mark.integration, pytest.mark.external_tools] -try: - from alphafold3.cpp import msa_conversion as _msa_conversion # noqa: F401 -except ImportError as exc: - pytest.skip( - f"AlphaFold 3 MSA conversion is unavailable: {exc}", allow_module_level=True - ) - -from alphapulldown.feature_batch import ( # noqa: E402 +# No AlphaFold 3 skip here any more. This module exercises the shared protein +# search, which the AlphaFold 2 image has to run too -- and that image has no +# AlphaFold 3 at all. Skipping the whole module on its absence meant an AlphaFold 2 +# environment reported success while silently skipping the one test that runs a +# real MMseqs2 search end to end. +from alphapulldown.feature_batch import ( DatabaseSpec, FeatureRequest, MsaBatch, @@ -47,9 +45,15 @@ def test_real_createdb_padded_search_result2msa_and_unpack_contract(tmp_path): query_sequence = "MKTAYIAKQRQISFVKSHFSRQDILDLWIYHTQGYFPQYQKVEKLLKQGADVVVT" target_sequence = query_sequence[:-1] + "A" + # A UniProt-headed hit with a four-residue insertion. result2msa mode 2 keeps + # this header and drops the insertion; mode 5 keeps the insertion and cuts the + # header to "P0CTR1". The bundle has to carry both, on the same row. + inserted_sequence = query_sequence[:20] + "WWWW" + query_sequence[20:] target_fasta = tmp_path / "target.fasta" target_fasta.write_text( - f">target_hit expected description OX=9606\n{target_sequence}\n", + f">target_hit expected description OX=9606\n{target_sequence}\n" + f">sp|P0CTR1|INSRT_HUMAN inserted OS=Homo sapiens OX=9606\n" + f"{inserted_sequence}\n", encoding="utf-8", ) target_db = tmp_path / "target" @@ -87,6 +91,32 @@ def test_real_createdb_padded_search_result2msa_and_unpack_contract(tmp_path): "gpu" if use_gpu else "cpu" ) + # The point of the two-pass format, against the real binary: the species + # header and the insertion arrive together, on one row, in the paired MSA + # AlphaFold pairs chains from. + paired = payload["pairedMsa"].splitlines() + header_index = next( + index for index, line in enumerate(paired) if line.startswith(">sp|P0CTR1|") + ) + assert paired[header_index] == ( + ">sp|P0CTR1|INSRT_HUMAN inserted OS=Homo sapiens OX=9606" + ) + assert "wwww" in paired[header_index + 1], paired[header_index + 1] + assert ( + paired[header_index + 1].replace("wwww", "").upper() == query_sequence + ), "removing the insertion must leave the row aligned to the query" + + # And the bundle says which database contributed which unpaired rows. + assert [span["name"] for span in payload["unpairedDatabaseRows"]] == [ + "uniref90", + "mgnify", + "small_bfd", + ] + assert ( + sum(span["rows"] for span in payload["unpairedDatabaseRows"]) + == payload["unpairedDepth"] - 1 + ) + def test_real_nucleotide_createdb_search_and_unpack_contract(tmp_path): """The same contract for RNA: a nucleotide database, searched on CPU.""" diff --git a/test/unit/data/small_bfd.mode2.txt b/test/unit/data/small_bfd.mode2.txt new file mode 100644 index 00000000..9369aaa2 --- /dev/null +++ b/test/unit/data/small_bfd.mode2.txt @@ -0,0 +1,240 @@ +>O31912 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A163VT74_9BACL +-----------IDPAKWGISTDGTNSRATTDGLNAALADAKSKGFGEVYLPKGKYLIDAVCKTN-HSPEIGGGIRVPSNLKLTLDSEAELKVEPNGSYGYSCIFLDNVHNVTITGGIVTGDRNEHDYS--NKTKPTHEWGFGINVRGGTNITIDNVRIKDCSGDCIYVNAIGMINYGTVPYTPPQKVMIQNCTLDGSRRNNISISACDGVVIRNNLILNAGIQTIGPGFGIDIEGYGEGDIDYETPLNIVIQGNQFRGNRVYSVGNFNGYGVVIEGNFADNTLSYGNGTDTVIANNVLIRT-DRQRTGIDGQGVSQGLEANHVTIMGNIVKGFGSGMDIRGKDVVVTGNALSHEAGVGIAAFAAENVWIANNSVHRTKGTPYRIASCKDVQLVNNKAHGSDKT-AIEANASSQVILRGNVVRDCSGGIEASNSEVVHIDLTEY--KGKAYAISFDSKSEVTLKGNRIPGPRNTAIYGEGGIKRAKIADNEIADANSFTAIQIVGGAKHEIVGNNVTFNKSSNGGVGIYLKDAKDSIVAKNTVYSNSEYALTHSIATKESTGTKVLNN------------------- +>A0A090ZKM7_PAEMA +---------YVIDPAQWGIKTDGTEAVKTTEGLNKAIAHAKSAGYNEAFIPKGTYLIQGVGTTFPNTPEKGGGIVVPSHMKLTLDHEAELKVQPNAERGYSCIYLRKVQNVTISGGIITGDLDQHDFSKL--PKSTYEWGFGIYVHGGKNITIENMKIRKCIGDCIFLGSVGLLGVDPDYDKPEK-VAIRNCSLDGARRNNISITAADGVFVENNVITNAG--TVKPWAGIDIEGYGEGAIDYEEPRRVVVRGNVFRGNAEVSVLNFNGYGVIIEGNHADNTFSYGNGTDTVISNNVMVRTDGSK-VAIAAQQVSNGYDGNNVTIVGNIIKGFSSGIDARGKDVVVTGNTVSNTGGTGIGVWDAENVLVADNAVHRCAGLPYKVDNSNDVQFLNNKAL-HSERFGLELDKSTNVVLRGNSFGQCNGGIWGTKGTSVFAEGNYISYTGKNYAISFDKNSDVTLKENYIFGSRSVAIYGESSAGKIKIADNEISDITGNSAIQIKGGQRAEIVGNRITFKRKDDAAYGISLDNAEDAIIAQNTIYSNNGKSIPNAIVTESSKRTKVLNNLLINGKMLLNKDDTNI--- +>C2WEL3_BACCE +---------YLIELSRWGI--INDGSKETEKEINNALQWAYDNGINRCILSSGTYLINAVGPPNDLQ---AGGIKIPDNMTLDLWHDTVLKVKANDSYSYSCIYLYNKNNIKIRGGTIQGDRYHHDFSTAPTGKLTHEWGRGINIIGCSNITIDNMNIKECTGDAIDVLSIGLMN--TQVYIPSSNITIRNCTLDKSRRNNLSLEGCDGVLVENNVITNAGDDGTAPRFGIDIEGYGEGATDYVVPLNIVIKNNKFEGNVTTSICNFNGYNVIIEGNISDNTISYAYGTQTIIS-NNIFKRVDLTTKAISSIGTAQGLDFNNTTITGNIITGFDTALDIRGKNVTVSSNIIYDVK-IGISLFQAESILVQGNLIKKATFGKIIINTCTNIKCTENQLK-DIGMLCIELNNSSAVTINQNDIFNSKQGIRISKSNAVSIDLNTF--NSPSYNIDFDATSNVLIINNLLKNCSSFAINGSASSKS-RIIKNIIENFTAISAINLSGG-RHELIDNILIANKNIAGGYGINLHSCNQSTVLRNHIFSSSIYNLSTPIKTNTSTNTKIIEN------------------- +>A0A238U6X6_9FLAO +-------------------------------------------------------------------------ILLPSNFHLSLHEETVFRVQPNAFPWYSLMTIDKKENVKISGGNFIGDRYEHDYPFFDLKRSTHEWGVLLLVRGSENINIDNITLKSSIADGLITGSEGHRIYPETVW--NKKVSLTNSIVSDNRRNNISITDGEDILIEGNEILDAGGETVAPRFGLDVEGYDESRKTYEWVENVIIRNNIFKGNEAGSIIVYTGDNVLIDGNFSDHVIAQN-----NTSGSKIINNTEARDDVRGRIGISTSDTGN--DVKNNTIRNFFGGYNIRGNNAEVSGNTVEGATVCLL------------------------INKAENIKVHDNTTSGAIASKAIRLTDANNIEIYNEKFT-LSNGFYLE-SIDFNMPNDDFHLN-------------------------------------------------------------------------------------------------------------------------------------------- +>LauGreSBDMM110SN_4_FD.fasta_scaffold226965_1 +-------------------------------------------------------------------------IHLPSDFHFKMSKSTFLRVQPNFWPRGVLLSVYEQKNTLVSGGNLIGDRYTHNYAPIKDERDTHEWPVLLSIAGCKDVIFEKIYMTDSTGDAVTGATNGSRDIGGADKKFNQNVIIRGCVMNASRRNNISITDGEDIFITNCIIQNGGGDTVAPRAGIDIEGYNPDGRNFEIVKRVTISGCTFKNNRVASIIDYSGINTTIKNNTSDHGFFASFSTGTKFLYNTFKASAINKDKVAIVTGINNTQLSKNNEVTGNKIEGFRVGITTQGDEGNVSNNTI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_4058357 +-------------------------------------------------------------------------IKVPSNTHLLMSDNTFIRVQPSNNPFSRLLMTYKAQNVLIEGGNLVGDRYLHDYSEIGVSRATHGYGSLINIAGSQHVTVDNVNIYEGEGDGVLIQISAIRNKDGSIKAESSNVVIKNSLIDKCRRNNFSIIDANGVLIENNVISNAGGEGTAPEVGIDLEAYRERRSEYERVTNVTIRNNEFVGNDVADVIVYTASFVDIIGNTFDNRVGVHAGHDVKIANNEF--TAGERAVSFDNFIVNETETYN-IDVTGNTISGYDTAMKVGTQNVTVSENKIYDFVTGINITDI-ENAQISNNTLE------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1V5WUJ2_9DELT +---------YVVDTDKWNIPTDGSDPERTSAGLSEALAWAVDNGFGTVRLPAGAYVVG-----REINSMFIEGVVVPGPLRLDFEPGAIIQMKPNDHPFYCILDIADASDVWIRGGTVLGDRESHQY----VGESTHEFGTAVCVGGSERILIENMSLAEATGDGITI-----NDAPG----SSRDITIRGNDIHHHRRQGISIISGSAIVIEDNEIHHIAG--TAPQFGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A090II36_9GAMM +--LLNSSINFVFDNQRWGVIVNNEQAKENTRLFQYALNQAHNVHANVFRINKASFWVGNYKKFN--STEL-SGITLPSNIKLSMRHDTILRTQANGYARYALLGLYNADNVTIEGGVLIGDRDTHDYK--DPQSPKPYWGHLMKIGGSRNVTIKGVTFKNATADGLSIHSLGTYKRTGSIET--KNILVTDCLFDNNRRLGTAITSGSEIIVEHNTYLNSGSESVSPAWAIDIEGGYKDHEYLERPYNITIRNNIERNSYRGAFIGAIGDGITIENNNTENTIALG-SVFNSKAFNNTITRDLNKEY-LNPNGLSVAYDGEKMFYPTEEVVGIRARMYISGSGNSIFNNSISN-SLTGITIQKAKNAEIYNNSVHSNNSIGLSARDSNNVNVYDN--DFNIEGLAIRFISINE-KLGHENFS---------------MYLNNNRFTSSGY----NKAASVSRSRNVYFNENNFSNIGFI-MYNIQLIGNRV-ETKTRIGLQIEEGNEQIKLHDNLVIHPEKKK---CIRNLSEQIPDIKNNV-------------------------------------------- +>SRR5690625_80756 +---------YELELARWNVSNNGTRPHETTKGINEALNWAKENGYTSLLIPDGTYSIAKGNAENDRHAR----INMLSDMTFLMSNNTILQKEPNGFEEYSVLHVGAVKNVVIQGGTLIGDREDHNYSSGDWSSGTHEWGHGISIVGGENITVDGVKIKDFTGDGIYI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_9554453 +---------YLVELDRWGISADGTNAEATTDGINEAIRWAQGEGYGRVRLPAGTYLIG-----KRLYDHYTGGIELVDDVALMMDDETVLQIVPNDTWAYCGIAMSGVRNAGVYGGTIRGDRDEHTYG----GSMTHEDGHCICIHESELVEIDGVTMEDPTGDGVAIVAEGGDG------SSCKHITIKNSEIARGRRQGISIVGGTNVWIENNEIHHIEG--TAPQFGIDIESLNFTSR------DIVIRNNRFHHN-RGGDFENADGKVWFEENHLD------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>APAga8741243855_1050100.scaffolds.fasta_scaffold124648_1 +---------YTIDNEQFGIYSNNTHARTTTDGINEALNWAKSHGYTKVRFAAGTYLIQC--TWNNRYCAPDDGILVPSGMTLDLG-TATFRMEANNYPAYTIFGIVNKSNVTITGGTLIGDLGSHTYSSV-SGSSSHEWGFGICISASKNVVIDDVTIKNMTGDGVILGSYAALSNGGRV---CSNIKVTDCTISNCRRQGISVIGADSELARNRIYGIKGTD---PQYGIDVEDYVVDDLKIHH---NNISDC-----SGGAINCNKGENYDVYSNTVDNIIA-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2G5GBI8_9FLAO +------------------------------------------------------FVIDKLDAYFKIDGPLSEGIQIPSNFTFRMSENTHLRVQPNATDKCTLLSVYLSDNAVIEGGNLYGDRDEHDYSDGIND---HGWGHLFTSRGSTNVTVRNVTMIDAAGDALKLEGEGHAVNPD--YAPTRNFLATGCKFIRSRRNNLSITAADGVVIEDCDFIDAGIHTTIPGFALDIEALKPN----ELSENIIIRNNRETGSRRGGFLVAIGDKVTFEGNVINSAINLQSARNCIVRNNIVTAQSDAKEYGAGII-TGRSDRGNLVTIYNNTVNGFSTGISISNFDMKVYGNTINNCSNVDKSAGISMGASLNNVVVRNNDVNVMRFANVNNTDESGNKGNNIVSGSSTPINSSHGIELIENTFNNAYEFYNCSNLNII------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A167HAM4_9BURK +---------------RWGVASNASNATATTDGMQAAIDWASSQGIGQFRVPAGEYLLGKIQTYN-----YAGGIKLPSNMALVLEPGAVLRMVPNDRWNYCVVTINGKKNVSVSGGTIVGDRYNHTYTPSSSGGTAHDEGHAICIEGSSQVEVQGVYITQANGDGILIV--------GKAPSTPQDITITGNNFDTNRRQGISIVGGARVLIEGNQIHHTKG--TSPQFGIDIEPLGGRGNNFHHNRGGDVVNTRTMHQGEASTTGGDDGRT-----YIDGPIVFWPEADQTIRNNNI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A1I1IH73_9FLAO +-------------------------------------------------------------------------INVPSDFHLIMTDNTHLRQQPNANKRATLLAAYLISNTIIEGGNLHGDRDTHDYSDTSTSQ---EWGHCIRVGASKNVIIKNMNIYDAGGDGIDIHAYGHAYNSHYTYTENLLITNNK--IYRSRRNGISITDGRNIVIEDNEFIDSGVSTVAPGWAIDVEAVRNSGVIFEIAEDILIKNNVERGSKYGGFIIHTGDRVTIDGNTMENSIAYAGTIGSVIKNNNLKSNSETALRGQTTGIIAQNKASSKNSVYGNTVYGYPIGIKVGDTNLNVYNN---NILECAVG---------------------ISLNTSKDSRIYGNTIKSTT---------ANSRGISNHTISNLIGSGLDENNESAKSNVIDVVIVFNGIKEIENSDTHSIIIKNNIIE--NGANLWLIDINNFEMHDNVI----------------------------------------------------------------------------------------------- +>A0A238U509_9FLAO +--LLNNSLTIQGDFDKWGIEGVTTNEISRT---NRDIL---ENNMTFIKLGASIFKIDKMDAFNVDEPDIEAAINVPSDFTLKMTNNTHLRMQPNAAIRPTLLATFTASNVTIDGGVLHGDRDSHDYTTINS---THEWGHLLRITGTKNSVFKNIRFEDATGDAIDVHAYGHSFDPH--YTYCDNVLITNNIMLRSRRNHISITDGRNITVEKNDFIDASIHTIAPGFAIDVEAV-----RHGNPRGISIAEDIFIKNNTGAVTVHTGDRVTIEGNKFENSISYSTSIGTIIRNNEIINNG----TAIVAGRADRYDDNYNGKVYGNTIENYAIGMTVSNKDLEVYANKITN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A0P0CI41_9FLAO +-----------------------------------------EGSFELVKLGVSTFIIDAMDAYFKVDDENFKGINPPSNFTLKMSENTHLRTQPTNFSNYALISVRDVENVVIDGGNLYGERDEHDYS----SGGSHEFGMCLTVSGSKDVTIKNMTITDALGDGIIIDNIG-HTYDSF-YTYTDNLLIQNNKIIRSRRNGISIVEGKNIVIDGNELVDTGITTAAPMWAIDIEPVWENGIKYQIVEYVTIKNNIERGSEKGGFINARGWYITYENNTMENTIAIGETVGSIVRNNIFKNPGKNSNVAIDPLGYGN-ERNYDNEVYGNTITGFPKGIELQDPGIDLHHNTM------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>J8DZ85_BACCE +--MIEKVNIYVIELDKWNIKKDGTDAVNTTKGINKALLWAKENDYDVCKLPAGNYLVDK-----------DSNIEMVSDMTLDLF-GCTIRKETNGYQGYSIVRIFRQKNATILGGTIEGDKDTHDYSTIP---GTHEWGIGIDVSGNRNIKIDSVKIKNTTGYGVRTGTYGHLSW---VYTTDESGTVLKADVNFTRSNQIQENGYFSIMGNGYGFTKDGGEVNLDRVPITIYFFDESNKFLGKITKRTFDNIYYSSFPKGT----SKFKIGFRFNYNNNALSMTIRSMTYTKGINVIN---TDIYGCRALGIAITGAQNMLV---DNCEIYGIGGINPGYAIDIED-----------GYNINQNIIIRNNYIHDNNNGAIVVVSARNVLLESNKFYG-----SVFLGGSRGENYLSR--HNLYGSTNAGGGDAATITFDDYMLEGQLYNAFYDNDNMTFVLQSDTF---------------------------------------------------------------------------------------------------------------------- +>X4ZGB9_9BACL +---------YLIELARWGIYNDGTHPVETVKGINNALVWARQKGITATTLPAGTYLIDKASRIN-----------MVGDMLFDLPMDAVLQKETNGKERYDVMYVGYANNVTLRGGTYLGDKLTHDYSQRDPNTGTHEGGYGIFVEGAKNTTIDGVKAMNFTGDGLVLGGFGTM---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1A5YEI2_9BACL +---------HMIDLKRWGISSNGTKPVQTTQGINKALQWAAKSKITAVTLPPGTYLIDK----NSR-------INMVGNMLFQLSDDTILKKQENGKEHYELMFIGYANNVTLRGGTYLGDKDSHDYSKKDNPHTTHERGYGITVLGANNITIEGVKGTHFTGDGLIIGAH------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2B8JB68_BACME +--------------EKWTIHNDGTYPIETTSGFNNALAWASAQGIHTFKVPAGIYLIK-----KGVDYDATARINMVSDMTFIADNKAIFQKETNGLTGYSVMYIGQVKNAIIKGGVYKGEKDTHDYSI----SSTHEWGYGVLVEGGENIIVDDIEAYNFTGDGLWVPTKGEVNIPASVYDNSKSVTVKNSKMHDNRRQGITVGGGYGVLLENNEIYNIRG--IAPQSGIDVEGYGINGNVHDNVYGVILYDGIGATVEENQIKNHSYPGLVVQEEYKDALVQNNYNSGMSIK---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1M6AGX2_9FLAO +-------------------------------------------------------------TTNQNFYPSREAINVPSDFTLRMTDNTNLRVQPNSRKNYVLLAVRDASNVRVEGGNLIGDRLEHD---DNSQPGPHAFGFVLMIHGGSNVDLVGVRTILGTGDGIDVNSIGFTFEAG--YIPSNNIRITNCIMDSNRRNNMSITDGFNIVVDGCQFLNAGIDMPGPGVAMDVEAFAGNFILYERAYDLTFRN-NFEKGSKGSFVVAIGEDVTIENNTTEDGIAIGAGHGIKIIGNTLIAAADDNGAGITTGHPNSTDTYDNV-IANNRIIGHNIGIAAYQRDMKIYGNVIE------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>GraSoiStandDraft_43_1057313.scaffolds.fasta_scaffold3393195_1 +-----------IDNAYWGIVTETNTEIANMENINRAIKTAHENGIYKIKLAKATYWFDA--TSDKTTPSIG----LLSNMQFNL-XXAXLRVMPNNLTHHYFIYIESAENVKIFNGTITGDRYEHGY--VPATYPTHEWCHGLRVGSNSSNYCKNIEIYDLVVQE--------FTGDGINVSWSKNVTIRNTEVSNARRNGITISNTDETYIYDNYIHDTHG--VSPACGIDLEKAAGDGPKNIVIRNNRIYDCINPETGQGQAMAISGGQVTVRDNDIRGVIGFAYAEKILIENNRI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A229GVH8_9GAMM +---------------------------DDTAAIQKAIDAVAAKGGGIVEIPAGTYMINGAATLGPGDVPRTSGLQVKSNVIIRMADDTVMQVIPNGEKHYDIFNIYNAENVAIMGGTLRGDRHSH---LNDQG----EWGSGIKIASAKNVVIEKVIAREFWGDAVHISDSG-----SLPRTPSQNVTIYQLAADGNRRQGISITSADKVLIEDSAFKNTGGQGTPPMAGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A098MBD8_9BACL +---------HLIELSRWGIYNDGTHPVETTKGINNALTWAYQQGITATTLTPGTYLIDKASQINM----------VP-NMLFDLTMEVVLQKETNDKESYQIVSLDYGDNVTLRGGTYIGDRLTHDYSKKDGSAGTHEFGYGIIARGVKNLVIDRVKTTHFTGDGIILAGHGTM---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2A2AT09_9BURK +-----------------------------------------------VWIPAGTYMIDTVNACGGWGQE-RCGLQMRSGVTVHMSQQAVLKAMPNGSRHYNIFHFNDVENAHVLGGQLQGERYAH---RIPTDGRLGEWGAGLVMRGARHAAIENVTAREFWGDGF--------------YVGGSSQNVKFCAVDKNRRQGMSITDVDTIVVQDSVFKNTHG--TPPQDGIDIEPWGENEPIREHVKNVTIRRSQFINNGIGMVTTHPGENVVLEGNFIDNSIGLGLSWKTRITGNRIIN----SQY--LNIGLGPLAT--FITVTDNAVTG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_2407419 +-----------------------------------AAIQAAINSLPTVTIPAGTYLIDTSKKIN-----------LKSNMLLKLDPNAILKAKSCSLIRHYLVYVNGKTNVEIAGGQLVGDRDGHNY----VGSSTHEWGHGIQILGSTKVTVRDLRVSKCTGDGVCIGG------------GASDVVIGNIIATNNRRQGLSITNCTNIKVYDSEFSYSKG--TSPECGIDIEGHSNNNGKYKRVSGVTITQCTLERN--GSLGLGTNGCSGIK--FTNNIVRYNSATGV------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1719318_174446 +---------YKLNLEDWDIPNNGHEPRKTTENLQKAIDWAHGNAYTKVLLPRGHFLLGITNGKRKEDNFSMRGLSMHSNTEFILDSAATLEMVSNDKVMYCIICIEDVTDVIIRGGTLKGDRETHTYTP-HHNRTTHEWGHGILISDRHRILVTNMEIKDVTGDGVYVKSEKK--------SIGSDIIIKNNDIHNARRQGVSIVGGLRVKIEDNEIHHIKG--TSPQFGVDIEG------PWTVTKDVIIHRNNFHDNRGGDVVNFDGKNVFITENKMIESDSYSYT---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>APHig6443718053_1056840.scaffolds.fasta_scaffold2008830_1 +-------IKYYTP-QQFGAVANDTG--DDTVAFNRALAAASSSSTDTVFVPAGTYMIKADGG--------DGGVQVLSKTKLKMDPGAVLQVITNAERGYNCVRTNGVTDAEISGGTICGDRTTHTGT-------SGEWGHGIGIYDSTDVTISNVVVKNCWGDGVYI---GTAN-DNSTTAKSRQISLSGVTTDNNRRNGLSVVAADGVTVDGCLFVNTNG--TDPQAGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_7665223 +---------------------------DVTSQLQTVLTNIAKNGGGIVYLPKGNYMIKATNPQSLLTPAKLEGLQVGSNTTILLDKDASLSVIPNNFWNYLVLNIQGADNVNILGGTLNGDRLSHDMSNPNNSPYYGEWGNGLSIQSSNNTLVSGVKFKNFWGDGISLFPDKDQAEAGAL-SQAKNVHITGCTFDYNRRQGISVGHANNVEIDHSLFENT--DGTGPAAGIDLE---PGGGSTEQVTNVKIHDNVFLNNNNAGLTAYAAPKSKV--------------SDVHVYNNTFINNG-------------AWMPG---QITFNN-----------AEYIEIDHNKFDNDD--ASRFHSSWIVNTANDNIHDN-----YGRNSSIAKEAHGEGKVTNNYVSSIMIENTGYDVANNHLPN-------------EISSTDLGTMGANWNYQNDVDYPGLATNEKVFNSRGKALNVTANPDNTVLNQSDPSNCQADISFDIDG---------------------------------------------------------------------------------- +>SRR5699024_10005537 +-------------------NAKGDGVTDDTNSINEAIDYAVENNINTVYFPSGIYMIDAEEIIPNGSK---GGIHLKSNITLKLDDNAILQAISNSAEGYNIIRAKESNNIKVIGGTIKGERSNHSGS-------EGEWGHGIHLKGCSNVYIQS-NIIDCWGDGIYVG--------GDVSTPTKNLIDENTVCDNNRRQGISIVSGKHIRLLNSDFINTNG-TL-PESGIDIE------PSHDRHIDVKVIDCNFNNNGTGFLIDGKSG--SVEDIYVNGI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5207342_2131982 +---------------------------DDTRAFQDAIDAAKGG---IVIVPAGDYLIDPLHS-----------VRVRSGTQLRMDRNARLRAIPNAAPRAYVLLLQGVEDITISGGQILGDRKEH----LGT---TGEWGHGIAIYGASNVKVRDVRISGCWGDGISIGS--TKAGKGGVMRPSTDIEIANVASLGNRRQGLSIGRSRRVYVHDCEFSDTGG--TPPSAGIDVE--PDAG---DIAQDVRIERCILRRNGPGRATSVAIRDCTIEDNRNAGVLAVG-AIDLAIERNRIRGNG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_3757948 +-------------------------------------IQAAINSLPTVFVPAGTYLVDAVRS-----------VKLRSQMHLKLDPGAKLVAKPTSSESYNVVFADVAHDVEISGGQIIGERHQHKGTV-------GEGGHCIRIRGCERVTVRDIRLSDGWGDGITV---GPRPNRRKRFTYSQDVAIANIICDGNRRNGLSIGNVIGIKVYDCEFNNTNG--TAPQCGIDV----EPSPDFDHCDDVHIENCRMSGNGAMNVWKNTSNKNTIEGNKTCGLVTRG-MTSSSITGNTI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>R6FQI5_9CLOT +---------YGVDIQKFNINNNGLNPIETSKGINDALNYAAKNKYDKITFPKGEYCI------SEENP-----ITMVSNLIVDLN-GATFKINDNGLQHYTVIDFSNCSNSQLINGIILGDRETHDYKTIE---GSHEWTCGIVFNNCDNCILDNVTISSFPG-------YGISSSLGENLS-DLIIGVTKENLSIGNINDKGLNNKKGTIIDPLNISNVGGEELGYNKGYMGYPYMQSKEYLSYFYDSKVDNCKQYK------------KVLIPDNYVHFVFKQDY-----------VPERGDTDFNGTTVFLTNYSSPNNITIKNCLIEKNKLGMGIGGYNWNIENNMFKGAPGYAIGWEYMDSFLFKNNKFNNNDIVSCAGDN---IIFENNSFTSTVYMWG----RTTNYKFLNNSFSNIAMNINYEYSTDTECSGNTYAITSK------NKDAEFNINNENIIDPENVSIIDADNIDNIRIYGN-FKDCH----ISKVTGSLVNFRGEKCKINNSN----------------------------------------------------------------- +>SRR4249919_2030177 +-------------------------------------------------VPAGRYLIDAVKS-----------VKLPSNRKLKMHPDAILVAKANNAEGYNVLLVERVDNVQIVGGQIVGERDKH----IGT---TGEGGMGIRFRGATNSSVTDTIVSNFWGDGI-VAG----PYKGSKYIPSTDITLKNVTMSGNRRNGLSVGNVVRFLAEDCKVLDNGNDPDGPFCGVDVE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1S1V829_9FIRM +---------YYAD------AAFTKPATDATQAINSAVKHASQNGIQKVVIPSGNYLIKAEGTGIEGDYAKTGGILLQSNMTLEMSSNAVLVTNTVNKPGYSLITVNNKSNVKIVGGKLVGDKDTH-------PANTHNACYGISINGSKNIYVDGTEITKMEDDGIMITDYAIDQSGG---TRSSDIEIRNVKSHNNGRQGLTI--ATGSNIKILNSEFSNQTKHEPKSGIDIE-----IESYDHVKNVEISGNKFEGNAFSGVSRHAEGKSNGLDMSNNNITVNNYSSGVVISGNNIISD-DSKAH--TSMGVYSTTPG--VSINGNNLVGQNVGMMLSGGGEQIVGNKIENEISVSGAAHLAENLAIKNNNFHDMKSYGINVRNT---EVSGNTMKNITEAFPNKASENTGINVTGNTFDGAYPTLYLGISYANSVKANSFTFSSYGYGM-------------------------------------------------------------------------------------------------------------------------------------- +>A0A1M5UZK5_9CLOT +---------YTIELDKFGIKNDATFAVETSKGINDALQYAKEKGYEKIVFPKGEYLISELNPV------------VIDLKNVVIDNQATFQINTNGLEKYSIIQIDGAENIRLTNGIIRGDKDTHDYKTIKT---PHEWGCGIVFKGGKDLEMDNITVTNVTGYGIYTESGTNSNRFDAVYT-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5687768_13918870 +--------------------------------------------------------------------------------------------------------------VSIRGGKIVGERGAHHGT-------TGEWGMGVRLAGCHDVRIQGVQITDCWGDGIYVGANGVGN-------ESRRIKITECILRNNRRQGLSITGCIGALIRDCEFTDTNG-TL-PASGIDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A250E5Q6_9FLAO +---------------------------DDTEAIQNAINEASKKGGGVVYIPEGTYLIDAKQSLVIRS---NVTLQLAANAILEAKANTILEAKANTSERYDILYIKNVENVKVVGGTIKGDRNIH-------IGNRGEWGMGIGIYDGKNIVIENVSVRDCWGDGIYI---------GKNRNRSENIILEKVKSVNNRRQGVSITAAHKVTINHCVFSQTNG--IPPQAGVDIE-----PNAADTVSNVVIKNSIFDSNENSGILIYTGAERS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_21041421 +--------------------ADNTGSVSTQSAINAAIALQNARGGGVVYVPRGTYLIDT-------NYLTGGSVRVLSNVTLHLDPGAVLQAVPTSNGQGAIVWAYNAENIIIQGGYIRGERDGH----IGTDQP--DGNHGISIFSCDNVTVKNVRVSHCWGDGMYIRNDTGGNNTG--DTLSTQIRVLDSSFFNNRRTGLACVAVDGLTISKCYF--YGNTGANPYAGLNLEPNSDGWVR-----NCVVSDC-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1H9W652_BUTFI +---------------------------------------ASNGGLNTIYLPAGVYNITDIGNYDH-------GIELKSNVNLIMDKNAVLKVSGMPYGDYEIFSMRYLSNVTIAGGQLVGERYSHSYG---------ESGHGIAMHGCSNITITNMCISANWGDGIYFGTQAVWLGSGQGYFGNTNVTISGCDIFDNRRNSISFTDADYITVDRCNLRDSHG--TAPQCCVYFEPNGDSSDK-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR2546423_4745973 +-----------INVRDWG--ALGDGISDDTPAFAAALATLADRG-GTLSVPDGDYRIDPLKS-----------VRLTDNVALNLSRDAILRAIPVTARNSAVVLVERARNVRIIGGTIIGERDGH----LGVGG---EGGMGIWVSASSNVRIERVTALDCWGDGFYIAGRGSYDANSLHESHSDNVTVSRCIARNNRRQGLSVVGCIGGLIERCGFTDTNG--TAPQSGIDIEPQG----------NWTVSNVTV----RNCVTARNAGWGIL---VCGNDIYNASVSDILIEGNR------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6185503_5510564 +-----------------------------------------------VDVPAGRYRIDPVRSIHLADSEMASGAVLAA-LPVAQGNSAVIRL--DGIQGAS-----------IRGGMIIGERDGH----LGT---AGEWGMGIQIMGGSTISVEGVRIEGCWGDGIYVG--------GRSGVEATHITIRRCVVTNNRRQGMSMTGCRDSLVEGCTFASTHG--TAPQAGIDLEGYGLSGGREQHVQTITLDDNRVADNG-----FHGIGVVS--------------SVDCSVRGNTVEHNG---RDGVQIAGSSRVRTGNTIRDNSRRTAGVWDNVIV--QSLSTDNTVANN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1E7DPH2_9BACI +-----------INITDYGANADDSK--DDTSSIQAAIDAAAGKN-GIVLIPAGTFLINT-------DPET-GSLNVKDNIEINMDEKTILKSIPNGLPIYRMLTIYNRENVKITGGTLIGDRYKHEGT-------EGEFGHGIYIGGSSEITISNVRAQDFWGDGFFVEGNASQTYP-------SSITIDNVESHNNRRQGISITAGKQIVVKNSIFSGTNG--TPPAAGIDLE--------RDPPYSLPLEEVELLNN-----------EVFNNEGY---GISFIYASNSSAQKNIVKNKGGIYIGGGVEQGIAKNNT-----VDDNFISENGLGIFVNSTQNNISNNVIEKSKKDGIVNHVGQN-RLVKNLVRDNQGNGLYIHDQSGIVVQQNKSKNSKAGIAVNVLDATITD--NDLLDNAGAGLHREEAKESTIERN------------------------------------------------------------------------------------------------------------------------------------------------- +>F3B2U2_9FIRM +---------------------------DDTAAIQRAIDAVSAAGGGIVDIPAGNYMI---NTLHQTGHSYRAGLVLKSNIIVRMANGAVLRAIPNGERSYQIFSITHVDNVHIMGGKLIGDRDTHIGNLGQT-------GYGVRITDATNVVIEDLYAGEFWGDGVFLG------------EDSRNITLYRVICDHNRRQGMSIVGGHNVKILESEFKRS--DGTPPKSGIDIEPEG------DHPIGVEIRNCLFEGSSTGFVVSNQSNSVAENIIFADNI----------VRGNKT---------AVNLVGIQSGETGNTISITEN------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A177L0L1_9BACI +--------------------------IDDTDRIQKTIDFVNKKGGGVVTFPKGIYLIDA---------EI--SLKLKDNITLKFEKGAILKALPNNAESYEIVKIHDVENVSLLGDTIIGERKEH-------IGKTGEWGFGISIRGAENITIENPFIKDCWGDGIYIGATTKKKY-------SKRVTIINPLIENNRRQGISVISAVDLTIISPKLLNTNG--TSPQGGIDFEPNSEN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A150W909_9BACL +--------------------ATGNGEVDDTIAIQNAIDFAYSNGNKTVFFSKGIYLVDSSTSL-----------VVKDGIVLKFENEAILKAIPNALERSEVIRIHDVKNVKILGPEIIGERDEHLGS-------TGEWGFGVSIRGAENIYIENAKISNFWGDGIYIGSTAKKNY-------NINIEINNVELTNNRRQGISIISVENLLIKDATITNTNG--TSPQCGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1G2XYR5_9BACT +--------------------------------------------------PSAVYNIDADGTGDQ-----SAGLKLPSDVNVAFEEGSKLKVIPNSSTVYSVITITGKNNISLSGACIEGDRNFHTGT-------TGEWGFGISISNSQNITIKDVNVYDCWGDGIYIC------------SVSDRVTVRDSIFNHNRRNGCSIISAKNVLFENCVFSNS--DGTSPYKGVDIEPNYENCRSYNNPVSITFSNCSSDGDGTGAGPRNTLGTITFRDCTSTNAVENGFSINTVIDGLYIVNPG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6478735_8854003 +-----------VDVREFG--AKGDGRADDTDAFEEAIEALPAGG--ILDVPDGDYMIDTLRSIRLRD---GIHLRLARNARLIAQPNAA----PRSY----VILLRNVRDIRITGGAIVGDRDRH----LGLDG---EWGHGIAIYSVRNLVISGIHISKCWGDGMSIG--GKSAQKGQPATPSMDIEIANVTSVGNRRQGLSIGRSRRVWVHDSEFSGTGG--TPPQAGIDVENRGPGIQVWKDTHDVSISDCTIEDNRNAGILAVDATDVTIRDNRIRDNTQVGITRQVSISGN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1C7EEP3_9BACL +--------------------SYGNDKMDDTQFIQNAIDFQSSKGGGVVYFNKGEYLIDSTKSITLRD-----------NITLEFEQGAILKAIPNSAERYEIVKIHNVKNVNITGQSIVGDRSEHTSSL-------GEWGVGISIRGAQDINIENVSISDSWGDGIYIGNTSKKNY-------SENIKINNSNFDNNRRQGITVVSVKKLEIINATITNTNG--ISPQSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1I2HG07_9BACL +-----------------------------------ARINAAINSLPTVYIPEGTYMI---NTGNPYNPVTNATISLKNNITIKMTENTVLKAITNAYNNYAIFLVRAVSNVTIEGGILQGERYTH------TGPTAGQVGVGVWLEGATNVTIRDVTCKEFWGDGIYTLYHSTLG-------NTKKVTVENVSFIDNRRQGISICANENFRVIGCSFEPAAGIDIEPELGVTITGNVFKGNKIGGDASATITGNVFEGNTMGIYLASSSRYYSVTGNIVYASGNYGISTDNVISGNVVYNNG--------SHGIYLLNNADRNVITDNKVYGNS------GEGI----NVYKSFDNII-----------------------------NDNNVTNNKGRG----IFIAVSTDNSING-NTSSSNALSGIYLWNSKYNLVDSNRCSKNGQ-HGIFVKGDAANDSLSNSI--------------SNNQCKENSQTTNQGYQNIFLSSGAQGANTINNVQGNMCRAGGYGILIDNTSETLLKNNDTRGGGAK-------------------------------------- +>M2U1I2_9SPHN +--------------------------------------------------------LDVVSPTNGRR-----GLVIPSGSHWVMHPEMRIRALPNASSHYEILNILDEEDIVINGARLIGER--------DTHRGAEEWGFGLSVRGARNVLVENLIAEDCWGDGFYIGS-GRRKY-------SQDILFRNTKAIRARRNGLSLISVRGFLSEDHESAHTFGSA--PQWGVDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690349_1434838 +--------------DVTSMGALGNGVHDDTAAFQSA-IDALPADGGVIDVPPGTYMIDATHTCPGRGTALQCGLILRSHVALSMDVGAVLRVIPNDQERYYAIYVRGLSDVEIVGGRLVGDRTTH----LGT---TGEHGYGIAIAGSSNVRVRWTEVSNFWGDGFIVSRTGGDTNP----TYSRYVTLDHVKSSNNRRQGLVAGGVQYLLVQYSTFRDSNG--TAPEAGVDFE--------PDEPTVAPVSDIRLYDN--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_575702 +----------------------------------------------------GTYIING--ELEGHTYESVGGIILHDNIILQFAEGAILKVMPSESEFYSDITLKDCNNVSVLGATIYGDRSEH-------RGVTGEWGHGVKVIRGENINIKNVRVSDCWGD-------------GVYFRDTKNVTVEYVISDNNRRQGMSIVGGENIYVRSSVFKNTNG--TQPETGVDI----EPNHDYQVVKNISFNDCSFHDNVSKGLMLFTNGGT-----FEDIVVN-----NCSFSGN-----------GAESFRVSGRGNHCNIKITNSTLEHMALGTSA---------THVLNAS--------ADNVIITNNYID-----KIVLNNTSNSIISKN-----IIIENIVLVDSNNIRIENNIFNDLYDEVYDDASKYIYITNN--TISGGKRGVF--VQSTEFLSLYSTINIKNNMFIGLTE---------------------------------------------------------------------------------------------------------- +>SRR3546814_95907 +-------------------------------------IYALPSTGGTVVVPDGTYMIDAVRK-----------VRLRSRMHLKLSSGAKLVAKTNSSPRYYVLDDGNASDLEISGGQIIGDRHRHTGT-------TGQWGQGIMIRGCRRVTIRDMRISDCWGDGMSISSI-RLNGRYDPWTPSNDVVIANVVSTGNRRMGLTLGGTRNIRVHGCEFSNTRG--IEPGCGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>R6GIV0_9FIRM +-------------------------------------------------------------------------LTVHSGQRLLFD-AATFQLTANGYDFYAVLNIHNVNNVTVEGGTIIGDRESHTAT-------TGESGHGIRIVNSHNVHVSDVDIRYTWGDGVCVGGNGTM------AEISQNVTLERIRTYKCSRNGLSIIEADGVVVRDCDFTYT--DRTAPQYGIDVE------PNLGTATNITIENVRMLNNGIGGFALYTT----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A088F0B6_9SPHI +-----------------------------------------------------------------------GGVALSSNTIVYGNNAKITAFADYNQPAYNIFRIENIENVIVKDLELIGDRNSHTGTL-------GEWGYGIAVLGSRNILLNNVVSKNMWGDGVNIQMLN-ANQAGVTQTHCSNVTLENCIFSNNRRQGLSIEDGSTIRVSGCTFDKSNGKA--PQCGIDIEPI-VAGRAFVD--GVTIEDCMFSDNNSGILMESLNGPISHKKAKISNAVYIGINTSRNNLNTKIL--GNTFDKSLDTGGMYMAISGNYINSTDTNLPEFYTDNLV------IDNNTL--LSGLTLESGVRK-VTISNNKIESPNTSSIGIFNKSQRLIANNNNNCETGIHSYNTTTTSAI-INENIFKNINIGVVAQLNS--KIISNQFINTGSGYG--------------------------------------------------------------------------------------------------------------------------------------- +>SRR5512133_1390 +-----------------------------------------------VSVPDGTYMINALTS-----------VLLKSNMTFSMSSGAVLKAITNSSSNYSILFANGVNHVNIIGGTIQGERTTHTGT-------GGEWGFGVRITGSQQIVVEKVLAKDCWGDGFYVSA-------------SASITLCNVTADHNRRQGLTITSVDGMVVRNSTFKNTQG-TL-PEDGIDIENAGET------VNNVLITGCTFTSNSGFGV------EIGVPISYTGQAWIKGVVVDNTVTGSGVNTLSTSPRAGIEASDIPS--AGNK--ITNNYCANNGLGILLRSNGMTISGNTVTQNTTDGIQVYSTDGNTITGNTATNNLGRGIYSTSNTNISISNNTVSG------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1X6W0S9_CHLAO +---------YLIDVNEWGISNDGTNPLETTQGINNALQWAYQNGYSYVKLPEGVYTVSKGSASKDYSENACILLQNDTTLDLY---GCVIQKEANGWDYYAAISIVEKRNVTILGGKIVGDHLAHDYATL--ANSIHEGCIGIIVRGSRNITLNGVEV---------------MNFPG------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>ERR1035438_889792 +-----------------------------------------------VMVPDGTYMVNAV-------AQNAAGIRLGSKMTMKLSSGAVLKAIPNASGNYAILAVSFASHVTIVGGTLLGERGSH----TGTDG---EWGMGLSINNSAHVVVQDVTAKECWGDGFYVT------------SLSSDVTLCGVVADHNRRQGLSVTSVEGLVVRNSTFKNSVG--TAPECGIDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>WorMetHERISLAND2_1045183.scaffolds.fasta_scaffold180453_1 +---------YYLDPVVAGITVSDTIALANTVAINTALETAKTEGNTTFVVPTMDAYFDTGGNGNSREEEVSGAIQIPDNMHFKMGAGTVLRRQPNDNRGYGSL---LGENVEISGGTLIGDINDHTYVLMDDDNTTFEFGFGISLYGAHNTYIHDITIRNFHGDAIFIDKTGLRNIDATLFRTCENVLIQRAYMQNNRRQAISVVDCNGVIIDNCDIVDTGRDIYHPAYGIDLECYRQLGAEYARVENVIIKNSRFSGNRKGDLNLYNSQYVQVFNNEFTYKIGHVASNNVSIHDNTFTYDPIVYPENTDSVAISITELVYDFDIYSNTISGYTFGIIVSGDRFNVYSNNISN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_498154 +-------------------------------------------DFGSIVFPSGTYMVDG---NDPAGPGGRQGVRVPSNRAISWLDGAEVRVIPNSNTGYNAFLVDQVENVLFLNPRIKGDRDEH-------TGVAGEFGMGIEIRSAENIVLRDPYIYNCWGDGIYI---GQVSEAA---GPCKDIYIERGKVDNNRRQGMSVISVDGLFVDNTQFTNTNG--TPPQAGVDFE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A0Q9EPM5_9GAMM +----------------------------------QAVIDALPADGGTVYVPAGNYIIDPTRNLRLR-----------SNMHLQLADGAKLLAKRNSADRAYVLMAYKVSDVEISGGQIVGDRDNH----LGT---TGEWGHGVMVRGSSRVTIRDIRISRCWGDGISVGGAIVTGLPTVI---SQSVVIANVASTGNRRQGLSIGRSSEIKVYDSEFSDNVG--IAPGCGIDVEGNQGNGQVYKRVKGITIKRCTIEYNGYGILTAPVSGYIAIAHNYLMGVMLRSATTSYQVSGN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2G6EWH0_9GAMM +-----------IDVTDAGYDAKGDGTTNDTTAIQKAIDAVADAGGGVVWIPKGRYMIDTEARLKMR-----------SNVTVQMTDDTVLEAIPNGAGSYSIFRFYNVENAHLLGGTLVGDRDSH----LGT---SGEWGTGVNISSSSNIRVENIVTKDFWGDGFYIGENGSLD-------KSENIVLYNVVGDNNRRQGLTIVNGDNIKIIDSTFQNTHG--TAPAAGICIEPNDNN-----LVSNVEILNCKTINNDGDGIGLYE--RVNAINNEIEN---------VRVDGNEIINSGGIIVSG--SV-TDSTITNNFINTTDSSEPGIRL----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_10317103 +----------------------------------------------------------------------GASIRLHSNSQIVIAPGAMLRAIPNNLNNHALFYCYDAENVYVTGGTLLGDRDDH------TDAEDGNAGMGWRISASSRVTVERQRILDFWGDGIYV-RNGTVETED-YDTLSTQVEIRQVECNNNRRTGIAAAGVEGLTVWKCWLRNTNGANAGANFEPNIDGYGNAGAGFQSGHDVTFDACTGRGNGNGFRILNTTG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>S3Y1Z0_9ACTN +---------------------------DDTAAIQRAINQASDAGGGTVNIPGGTYMIDSVHGLMMRN-----------NVTLKLADDAVLKALPTNTTHYSLISFVKVENANLVGGTLIGERYQH-------TGQGGEWGHGVNIQSSQKVTVQDVTSKDFWGDGFYIGQAWQV-------WDARSNQVALCNVTNNRRQGLSIVDGTNIRVLNSTFSRTNG--IAPQAGLDIE--PENGNLVEN---VEVRDSVFSENGDGI------------------VLTWGEQNDASIKG---------------------------VRLESNQVLDNESGIMLRAIGCQVINNTIRNAGN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_4714463 +-----------------------------------AIDYAVEKSIDLVWVPKGVYMIDAAGVNGEK------GLRLRSGITLKLHEEAVLKAMPNNVANYSILRVYDSANVKITGGSILGEKNEHTGT-------GGEWGMGIDIQSSNNIEISNVKVKECRGD-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1041385_954775 +----------------WG--ALGRSSPDQTKDDTQALQAALDSGARKVTIPNGHFMIDAARVQPGRTK---AGLNLPSNIELIMGTETFLHARNNSSISYNILVGWKVSNVIIRGGVLVGDN-------VTNSRRSNPSGFGLALFGAKNVWVYGLTSQEMFADGFFVCYD---DEPGS-HDECENVHLMDCRAYKNYRQGASVIGAKNSSIEGGQYRQTGGSP--PQDGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5581483_5383682 +--------------------AMGNGSMDDTKAIQAAIDALPESGGTII-VPNGTYMIDALK-----------GISLRSHDRLSLASGAALKAIGNSERRSWVVKVWNVNNVEIVGGGVIGERYSH------RGTSGGEWGYGINISSSDKVYVHDITIQDCWGDGLLIGALG--SGKGMV--EATNITLNRVKSKNNRRQGMSITPANRVYVVNSSFTGTHG--TAPESGIDIE---PRSQGWASQVRLENTDLS-NNNGNGNVDALTLYKVTAKNN--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1G7HPV6_9FLAO +------------------------------------------------------------------------GLRIRSNSKLYFQKESLLKLKSSAKVLYAILNIAKVENVSIYSPTIEGDRYRR----VNPEDKKGEWGMGIWIQESKNISVFNAKVTHCWGDGIYIGG-------GRDIVPNDSIYIHRPIIDENRRNGISITSGKNIRIIEPVVSNSRGKS--PESGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1G2Y1Y7_9BACT +-----------------------------------------------IRFPAGTYAIDGFDTIDKGNVTVYGGLKPASDTTLIFDIGAKLKAIPNDKIGYSILKIEGKNNVKIYGPTIEGERDSHTGT-------TGEYGMGIMLEGATNIVIKDANVYNCWGDGLLIGVHWT--------KPSDQIYVENSTFNNNRRLGCAVTNGTNILFKKCTFLNSNG--TAPQAGVDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1035438_766262 +----------------------------------QACINAVAGTGGTVVVPDGTYMI------NATHGSGVWGLMMGSNMTFAMTSGATLKAITNSSTDYGILCSNGASNFTITGGNIVGERSTHTGS-------GGEAGMGIYLNAS-NVTVSGVNVSECWGDGIYIC------------DASSNITITNCISNHNRRQGLSITAGNTFLISGCTFSNTTG--TDPQCGIDIEPNGSVPVTGVH-----ITNCQIFGNAGGGVQQGNVGNV---------------ASGTLLENCNIYSNGGG---GYNDGGIRFVETHDNI-IRNNNIHNNLNGMLDTNAGIGCPNNTVANNSGWGIYANLCNGSAITGNTI-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_3394488 +----------------------------------------------IVDVPAGTYMIDAETSILMRD-----------NTHLRLATGATLKAIPTSSAVYNVILCELVDSVEISGGAILGERDAHTGT-------GGEQGHGIRSRGATNVYIHDIHISKCWGDGI-DAGPDKSDSHNYVYT--ENLTIDNVVCTQNRRNGLSIGNVNTARVTDSEFSYTNG--TSPQCGIDVEPDGDADGDGDCS-DIVIDNCRLNNNAVYGINLYQRARVTISN--C--VIEYNSSCGIVSNG--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_325582 +-------------------------------------------------VPAGKYLINPVRVASGTS---FYGLLVGAGKRLEMDPNAVLVLKPNSAPRYCGVRI---DGGYMQGGQVLGDRLSHNYS----SGGTHEWGYGVQLRGTDSKAV-GVKVSQCTGDGF-----GMSGI---------RPVIENCISTQNRRQGVSLFGSDGLRISGCEFSNTGAAGTNPRCGVDFE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1E8BK68_BACMY +---------YFLELERWNVKNDGTDANNTSKGINNALLWASQQGFIEVVLPMGIYLID------ENTP-----IEPQSFMTLNLG-GATLKIRDNGLVKYAIVYQRNQKFSRITNGRIEGDKDTHDYTTIP---HTHEWGYGIEVEGSSYISIDNMEILNCTGDGI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>SRR5512142_681238 +-----------------------------------------------VYVPRGTYLV-----LADGYRDGGGGLAPRSRTRVVLAPDAVLQARPTGSSDYVVVRIERVSGVTVEGGTIRGERHEH------TGRGG-EWGFGIGIFGASDVVVQDVTIRDCWGDGLFIEE----AQPDFSVMP-RNISIRRVVSANNRRQGMSVPG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>D7W8T5_9FLAO +-------------------------------------------------------------------PLMTSGIFAQSNSQIYFQKNSSLILKPTADVRYQIISLHAVENVKIYNPTLIGDRDRHLGS-------KGEWGFGIDIRGSRNIEIYNANISDCWGDGI-VLVKTMRNMRSGVIFPTENINIIGGFINNVRRNGITIAGGKDIIIKNLLIANING--TNPMAGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_487370 +------------------------------------------------------------------------GIVLSSNTNIYFDVNSKLILKQSSKESYSMLKIYNVENVNLFNVHLVGDRYQHIGS-------EGEWGMGIRIQNAKNINIYNSTIRDMWGDGIYITSFG--------NTSNQNILIQSSWIDNTRRNGISIISGEDINIDYVKISNTNG--TAPASGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>H6LBC8_ACEWD +-------------------NAKGDGKTDDTSAIQNAL-----NKSDSVYIPDGTYMIN-----------VDQSLKPNSNQTITMNANAVLKAISSSRGEQYVITIDGVTNVSIIGGKIVGERNEH--QGLDG-----EWGMGINVNGSSNIVIKDTTISDCWGDGIYLGGSPAVN----------TITIDGVTSDNNRRQGLSITNAKNVLINNSVFKNTNG--TAPEAGIDIEPYGNNQSGIDGIQRVEITDCTIKDNGLGILLFEASGNTSVTNNKDDGV---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6185312_3767693 +------------------VGAVGDGTTDDTWAFQKAIDSVAAQGGGTVYVPAGTYLIDADVSINMKD-----SVTLD-----MVDTTRVLMAKPTATVRNYVIKLNNISNSKVIAGKIVGDRYQH----LGT---TGEWGMGMGINGSTNITVTGTNIIDCWGYGITISSYNCV---------LKNVI---CD--NNRRQGLTIGSSDSLIVDSCTCTHTNG--TAPQDGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A0D5BSE2_ELIMR +------------------------------------------------------------------------GLVLNNNQVLLFQEKSVLKLNPTTQKEYSVLGLSNVNNVKIFFANIEGDKYQHLTNV-------GEWGFGIGIFSSNNISIYSPYIKQTWGDGIYIGQ--------IKNIPSTNIQVYNAVIDDVRRNGMSITSAKNIDVVNAYISNTNG--TSPESGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_13262863 +------------------------------------------------------------------------GLKLRDNSKVLFQQNSVLILKPSSKSQYSIILMDGVSNVKVYFPKIKGDRVGHKGT-------KGQWGMGIWINNSQNILVHNPYITNCWGDGIYLG--NVNNRP-----PNKDIQIIDGMLDNNRRNGISIISGRNVEINGTFISNTNGHN--PQSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1035438_2623855 +------------------------------------------------------------------------GIRFGNNMTLRLDSGAILQALSTSSSSYRILLLSGVQNINIIGGTIIGNR--NNNTITDSV----EDGMGIQIANSQHVVIEGVTVQDCWCDGVYVS------------DGSGDVTLNGVVAKNNRRCGSAIVSVSGMVVRGC--------TFQGTTGMMENGLWANGTGVDVEPNLTVQNIQFLGN---TFTQNATGGLGIGPSNAN--MATTFVINCVIDGNTVSSNGDAVK---GTFGIVASSTGGH-QILNNTVNNYGVGIYLYGSNILIQGNTVSGTS--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2A8TS41_9BACI +-------------------------------------------------IPDGTYMI---------NADI--SLKPNSNQILSLSKKAKLKAKPNSDASYQIINIIEKENVIIEGGYIEGERDEH----VGVNG---EAGMGISVRNSKNITIRNTHISKCWADGIYIGG----------YLPCYNINIYNVTCDNNRRQGMSVVNVDTLTVRDSFFTNTAG-TL-PEAGIDIE--PEN---YSTVKNVTIDNCTGNRSGLDVFWAKTISNVQVLNSSMINNREYGFTTDILV----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5687768_6663082 +-----------------------------------------------VYVPAGTYLVDATRT-----------IRLRSRMHLKLDPGAKLLAKATSADRYYVVNAYKVHDVEISGGQIVGERDRHIGS-------SGQWGHCIGVRGCKRVTVRDIRLSKGWGDGISIGAAN-----GTTTVLSDDVAVANIVSTGNRRQGMTIGRCRNVKVYDSEFSYTSG--IKPGCGIDIE---------PDPFTIRIQNCWIHHNGNGVQVYKTVKNVTIK----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_2031064 +-----------------------------------------------------------------------------SNSYIKFHPDAVIKVNPNNYGDYDRKYIYMKDNIVIKNPRIVGDKHEKNYKKIDSE----EWAAGIQIRKSNNIKILNPHITAMWGDGISSAGRKSMGEP-------DNILISNCFIYDNGRNGYSITASSNTKVFGGIISKT--DRTEPISGIDVE-----PAQYSRDVSLNIKDVKF-TNGRGLILFKASQGAVIED---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5688500_1121635 +---------------------------------------------------------------------------------------------------------------IVGPGRITGARMVHRGS-------SGEWGMGISAWNSTNFRITGVEIADCWGDGIYVGSAGNGYCDGFLI---EGVKVRNC-----RRNGISVVAGRNGEIRNLDIAKI--DGIAPRGGIDLEPNSSNAPNRN----IRMSNGRIRDVAVGIYVTVANQRVSISDIEAENIIVSDNSVDVRIENNPNIKSIGGKEGGAFRTVVTRPETIRGLLIRNNQLSGFVIDIFGQGQGLVISGNRISNAGTQGIA---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_32025263 +------------------------------------------------------------------------GLKVKSNSVLEFQENSLLKLKASDKHTYNILEIHSVQKVKILNVKIKGD--------LDTHGKDGEHGMGISIRSSKDVEVVNAKIEDCWGDGIYIGRLNRYDRNGM-FEPSENIIIRDAYVNRNRRNAISITAGRNNLIDKLDANKTKG--TFPIIGIEIK---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5579883_944156 +-------------------------------------------------------------------------IQLRGRQEIIFEPGVVMLAKKGEFRGTGDSLLSIVSNLVLRGYGAILRMHKPDYQA--EPYKKGEWRMGIAIRGCKNVLIEGLRVESTGGDGFYVDGGADRGW-------SEDITIRNCTAYDNHRQGLSVISAMNLAVENCVFASTRG--TPPEAGIDLEPDTEENRLVN----CLIRNTVFQNNNGHQVLIHKSMPVSIRFENC------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1T3DZL3_9FLAO +---IKKDGSYYERQFEGGINPAWYGEL-TEKSINKALHIASVLN-------------KDVELMNDYKIDCSGGVKLLNNSVLRFSNNARLLAIPSSSGNYRMLSIDKVKNVKVYNPVIIGERSAH----LST---TGEWGYGINITNSQNVEIHNAVVKDTWGDGIYIGG-DYFDKTQTISTLTDNVLIYNPYIDNVRRNGISICSVGKVRVYNAVIKNVNG--ANPQSGIDIEPEGDTG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_10516162 +-SLLDRIVLYVDDF-----GAVGDGVSDDTDAIQQALNVAGELRTSVIFTKGKTYMTDG-----------SKGILPPSYSTLIMTGSKL-EVIPNALDRYICLYVLIAEHVTIIDPDLKGDRSNHSTNNNNVDGFTGEWGFGLRIARSKNVNVYNCKTSDFWGDGVLIGTDGIENTP------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5262249_48802186 +---------------------------DDTSAIQAAIDAVAEKRGGTVLVPNGTYMVSAVR---------DNRLSLKSNVTLRLANDAALKAIPNDSDHYSVLRIANVSNVAVIGGTFEGDRNEH-------SEKTGDWGMGIWIKGAEHVTISGVTATKMWGDGFYI---------------QDANDVRLCSVENNRRQGLSIIQVNGLEIKNSTFKNTHG--TRPSAGIDIEPDNDE----QHVANVRIHDSKFLDNGAGIAVVAKKSLVS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1700750_2813068 +-----------------------------------------------VEVAAGEYLID-----------VTKSVKLRSGVALVLDPDATLRAIPTDAGNSAVIRIHDATGVRVEGGSIVGERDKH----LGTNG---EWGMGLGARGSHDVLIQDVLISGCWGDGVYVGS-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR2546423_7159601 +--------------------ALGNGVVDDTAGINAAIRSLAGTGGSVL-IPAGVYLVD---------PTV--SVQMASNVSLLLDDSAILQAVPVAAKSYAVIAASGVHNVKISGGKIIGERQTHLAA-------TGEWGMGVRVMGSSNVQIERVE--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5680860_103890 +-----------------------------------------------VLVPNGVYMVQAV----------GESLALGSKMTLRLADKATLKVIPNGETRYYTLRIHEASDVTVIGGTLLGDRRAH-------KGKKGEWGMGLHIVRSSRVTIAGVTSTRMWGDGFYVA---------------DGTDIAFCSVANNRRQGLSIISANRLLVTDSVFRDTRG--TRPSAGIDME-PNKASQRIAH---VRIERSKFIGNGDGIVIQGYKGRVSIRNNLFD------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A1Z4RLG8_9CHRO +------------------------------------------------------------------------------NQKILFQPGVVLEAQPGAFKGYESMVSVMADNVTLSGYGAEFKMRKADYANPSLYEKS-EWRHNIHVRGARNFIIEGLTLKDSGGDGI-LVEHGPNEPNQLPVSKYSSGTIRGINASDNYRQGISVVSAKDLLIENSTFQNTSG--TEPASGVDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2B2C9D0_9BACI +---------YILELDVWSVSDFNDKTLSTSNGINNALTWASQRGYSEFMFPKGTYLIDE-------------NIPIPKNFMTLNLNGSTLRIRNNGLPKYS--VICYRQNQIVTNGIIQGDRYDHDYSN-PGELPTHEGGMGILFPNTTDTTIDNIEFLDLTGDGV-----SLFSSQGLVYTPTKSYAI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2C2T0P3_BACME +---------------------------------------------------------------------------------------------------------------------------------VDNERYTHEWGQGIEIAGSNHVEIKNIEICDCTGDAV---STGWLKYNSTDYTQNEHIWIHDCDIHHCRRQGITLASANDVCVYNNKIHHIGRNGIPPMFAIDIESVGESNIPYKQPYRLYIFNNHIHDNQRGHFVNADGNHVTVENN--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5215813_7905647 +-----------------------------------------------VFVPKGVYVVDAV--AKKRRLTLG------SDMTLKLDNDAVLKAMPTDSRKYSILTVSGVSNVTIVGGTLEGERAQH----MGNDG---EAGMGIRVGGAEHVTVSGVTSRKMWGDGFYVEDANDTKFCG--------------ETSDGRRQGLSIIEADGVLVTDSVFSNTHG--TRPSAGIDLE--------PDHPSQIRIQNSKFLNNGPGIEIAGKKGLVT------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6185312_5921845 +----------------------------------------------------------------------------------------------------------------------VGERQNHVYSGIGTG--TDEWCFGIQILGVTGMTIRGTQISQCTGDGIDLGNFGS--------SISSDIVICDVISTQNRRQALSITGGDGIFVYDSEFSYTNG--TAPLDGIDIEPGGAGAS------NITIENCLIRGNGCGQLNAHWGDIINVNVKNC------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690625_4101829 +------------------------------------------------------------------------GLEIHGNSTVFFDEGSVIKALPTSNGNYSILSIKGVDNVKIYNANIFGERNEH-------QGDTGEWGMGIRIEDADNVLVVNLKVSDCWGDGIYL---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1H6XJ90_9FLAO +------------------------------------------------------------------------GLNLRSNSVLVFQENSYIWLKASSKPNYGVINIKDIKNVTLINPRIVGDRDSH-------LNKIGEWGMGINILNSDYINIFNAIISKCWGDGIYIG--------NKINGFSSNININGGLIDNNRRNGISIVSGEVVVIKDITVSNTNG-TL-PMSGIDLEPNTNEDTLKDIKL-VNVNSFNNRENGLGGLLGENKREVDISDQYSNTVVSIGLRNDYEKKVKKI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>SRR5512133_257377 +-----------------------------------------------VTVPDGTYLVNALTS-----------IQLRSSMTLSLSGGAILKAIPNSSSSYTILRISGVSNVNVVGGTLLGDRSAHAGT-------SGEQGVGLRITGAQHIAVVGVTSKECWGD-------------GFMVADASDVTLCNITADHNRRQGLSITGGNGIVVKNSSFINSQG-TI-PEDGLDIE--PNSGQIVSN---VLITACVFANNAGDGI---ENGVPVL-------FTGLAFIYNVVIDGNTMTGNGVGTLHAGPRSGIEVSNTSGHV-IKNNTIQGYGIYLRDGVAGTTVTHNTVKNALN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A110B3A3_9SPHI +------------------------------------------------------------------------GLSLISNSTVIFRKYSKLVLQANGLPAYQILRIYNATNVNLYFPVVQGDR--------DLHSGNGQWGMGISISGSTKILVVNPKVSKCWGDGIYL---GRQN-----NAVDRNITIFYAELDNNRRNGLSITCADGVHLIRPIISNTAGQM--PMSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A229UP75_9BACL +---IGSPVSYAIELDRWGIQNNGTDAETTTRGINDALVWAKSAGYNHVVLRGGTYLI-------QVDPN-GTAIYMPSGMHFEMHHDCILQLAGNSFPNYRMIEMKGIRYAKVSGGKMIGDKAFHQYEM------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5262245_13989197 +-----------------------------------------------VVVPNGIYLIDAAGE---------NRIKLKSDMVLKLSDGATLKAIPTDAENYALLTIADASNVWVIGGTLEGERDRH-------KGKSGEWGMGIRIEGAKYITIMGLTSRKMWGDGFYVRG---------------AEDVRLCGVDANRRQGLSIIEADGLLVQKSVFKNTRG--TRPSAGIDF----EPNRDSQEISNVRIENSKFLDNGAGILVAGKKARIT------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5215831_1849565 +-----------------------------------------------VLIPAGTYMVNAVDS---------NRLSLKSNVTLKVANTAVVKAISNDSEHYSVLRIANVSNVAVIGGTLEGDRNQH-------LGKDGEWGMGIWIEGAEHVTISGVTALKMWGDGFYI---------------QDANDVRLCSVENNRRQGLSIIQVDGLEIRNSTFKNTHG--TRPSAGIDIEPDNDE----QHVANVRIHDSQFIDNGAGIAVVAKKSLVS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>OrbTnscriptome_3_FD_contig_123_161973_length_414_multi_3_in_0_out_1_1 +-------------------------------------------------------------------------VKLRSNINIVFEKGVVVEASQKGNAKYPMFEVKNVSNVAFIGGDKPGDVYIGKYRDNEERRRCHDYGSGFAIEGAQNVVIRNVKVAECSVDGISLSSLGRLN---------SNIYVQDVILDGNYRQACSICNADGLYFKNAFLNTSGGD---PMCGIDLEPTYE----LEPNSNIYLFDCRFEGNVGGGLTSSSYYPVTLHAKRCD------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>SRR5262245_2037218 +-------------------------------------------------VPNGVYMVSAVE----------NNLKLKSDMTLKLAGGAVLKAIPNDATHYAILTISGVSNVWVSGGTLEGERSEH-------RGKLGEWGMGIRIDDAKNITIAGLSSKKMWGDGFYV---------------QEAEDVRFCGVDANRRQGLSIIDANGLLVLNSTFKNTRG--TRPGAGIDLE-PDKDAQQITH---VCIENSKFFDNAGGGIMVAGNKKARV------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A0D4DCI2_9CAUD +--------------------------------FMVGYIYATSKNRPVVDIP---IYVQSTRKQSGFYNQVHYAVVAQSNSILWFMPEGLIQIGVD-EAAYSILSLYGADNFLIKNPKLRGDKY-------TKTGNTGESGFGLTVTGCSNGIIEYPNISECRGDGIYLGQEYFNNNASSLI--PKNIKIIKPTILDSYRNGLALSAGEDIYFDAPFIDIAKG--TAPEACIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5688572_15557399 +-----------------------------------AAIQAAINSLPVVSIPAGTYLVDTTKRINLR-----------SLMLLSLASGAVLKAKTSSVRRAYILNVNNVRDVEIAGGQLVGERDTHKYVSGTTD----EWNHGIAINGSARVTVRDIRISKC----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6266566_4873650 +-----------------------------------------------IHVPPGTYSVDAV----------SGSINLKSGITLDL-TQATLVANPNNQIFSIIMRVSDCENVTILGGTIRGERTTH---LGSTAAFMGGGGGGVAIWRSKNIKIQGMKISDCFCDGLLVWHSGQVEIQGMSLVDSHDVHIHNSQFTHDIENDLETETCANILVEHC----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>G2KPW0_MICAA +---------------------------------------------------------------------------------------------------------------------------------------------GIEVQGGKTVTVSGNNMDDVRGNGIQISSQGAVNHGIVVNTAPGAVVVDGNRVTDAGEFGIYTNGSKNVVVSDNRVS-------GGKNGIVVQNAAAS-AKIENNVVSGASDAGRVASGYGILVKDSAGAVSVTDNRSNANTGDGLNTDGAVVSGNITNDNGDK-------GIIINRSDNAV-VDDNRSNGNATGIWVESNGVDLTNNVIRHSKVDGIHLRDSDNTLVQGNQINDRNGIFVERSDSADIFRNTITGSGGYTGVKVEGSSNTDIGATDQT-SWVQTGFWPWQGHFVTVRGNTITNFDNGVTVAGGNDNDV--VRNTISVDYGVRLSGAT---NSDVLGNDLTG-NSIVGIEVVAGSHNAVIDNNTLDHFDT----GIVVNGSNNVDVTDNDLTDVGSGIVA----------------------------------- +>SRR6266511_2426516 +-----------------------------------------------------------------------GGLVPRSNTHLHLAPDAVLKAKTTSASDYNVVRIERVSNVVVEGGTIAGERHRHAGS-------GGEWGYGIGIFGATNVTIRNV---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1Q6A375_9SPHI +------------------------------------------------------------------------GLTLHTGQKVYFKKGSVLNLVPTAQPNYEMLRIHDVTNVSVYNVVIKGDKYSH---LV----KTGEWGMGISIRGASNINIYSAKIEQCWGDGMYIGTTPKQAF-------CENINLRYVNCNDNRRNGISVISARNVTILGPVLTNTSG--TQPMCGLDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_4058803 +------------------------------------------------------------------------GLNIISNQILNFSQNSKLIMKTNAEERYGILNIKYVKNVIVNNPNLIGDKEKH-------LGNRGEWGMGINIWASKDVTINNPRISETWGDGIYIGEPPVQE-------------KQKKKLKSYANHNIAIN---GGVIDDC----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6516164_3930632 +-----------------------------------------------VLVPNGTYMVNAVGDAR---------LFIESNVILKLANDAVLKAIPNDSKKYSVLRISNASNVAVIGGTIEGERYGHSGNV-------GEWGMGIWIEGAEHVTISGVTAAKMWGDGFYI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5262245_45879959 +-------------------------------------------------VPNGVYMVSAVE----------NNLKLKCDMTLKLAGGAVLKAIPNDATHYAILTISGVSNVWVTGGTLEGERSEH-------RGKLGEWGMGIRIDDAKNITIAGLSSKKMWGDGFYV---------------QEAEDVRFCGVDANRRQGLSIIDANGLLVLNSTFKNTRG--TRPGAGIDLE-PDKDAQQITH---VRIENSKFFDNGGGIMVAGKKARVS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_56255 +----------------------------------------NENN--VVIIPKGTYRVT--------------GLKLKSNFSLLFEEGAELELIANNKERYEILSLAGIKNVKIYNPVLIGD-------IRKRNSLKGEWGFGIDIRGSREIDIYSPFIKDCLGDGIIIS--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1I0S8N9_9BACT +------------------------------------------------------------------------------------------------------------------------------FATIEGDRSTHQWGMGIAIRAAKNVNIYAPRISKCWGDGIYVG--------GLKGVTSSNINIYNAMLDYNRRNGMSITSVSGLKLVAPVISNTYGQT--PMSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/test/unit/data/small_bfd.mode5.txt b/test/unit/data/small_bfd.mode5.txt new file mode 100644 index 00000000..9fe7ab29 --- /dev/null +++ b/test/unit/data/small_bfd.mode5.txt @@ -0,0 +1,240 @@ +>O31912 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A163VT74_9BACL +-----------IDPAKWGISTDGTNSRATTDGLNAALADAKSKGFGEVYLPKGKYLIDAVCKTN-HSPEIGGGIRVPSNLKLTLDSEAELKVEPNGSYGYSCIFLDNVHNVTITGGIVTGDRNEHDYS--NKTKPTHEWGFGINVRGGTNITIDNVRIKDCSGDCIYVNAIGMINYGTVPYTPPQKVMIQNCTLDGSRRNNISISACDGVVIRNNLILNAGIQTdagpgfkskIGPGFGIDIEGYGEGDIDYETPLNIVIQGNQFRGNRVYSVGNFNGYGVVIEGNFADNTLSYGNGTDTVIANNVLIRT-DRQRTGIDGQGVSQGLEANHVTIMGNIVKGFGSGMDIRGKDVVVTGNALSHlgEAGVGIAAFAAENVWIANNSVHRTKGTPYRIASCKDVQLVNNKAHGSDKT-AIEANASSQVILRGNVVRDCSGGIkvtnissEASNSEVVvesnHIDLTEY--KGKtAYAISFDSKSEVTLKGNRIPGPRNTAIYGEGGIgKRAKIADNEIADANSFTAmIQIVGGAKHEIVGNNVTFNKSSNGGVGIYLKDAKDSIVAKNTVYSNSEYALTHSIATKESTGTKVLNN------------------- +>A0A090ZKM7_PAEMA +---------YVIDPAQWGIKTDGTEAVKTTEGLNKAIAHAKSAGYNEAFIPKGTYLIQGVGTTFPNTPEKGGGIVVPSHMKLTLDHEAELKVQPNAERGYSCIYLRKVQNVTISGGIITGDLDQHDFSKL--PKSTYEWGFGIYVHGGKNITIENMKIRKCIGDCIFLGSVGLLGVDPDYDKPEK-VAIRNCSLDGARRNNISITAADGVFVENNVITNAG--TVkgtKPWAGIDIEGYGEGAIDYEEPRRVVVRGNVFRGNAEVSVLNFNGYGVIIEGNHADNTFSYGNGTDTVISNNVMVRTDGSK-VAIAAQQVSNGYDGNNVTIVGNIIKGFSSGIDARGKDVVVTGNTVShlgNTGGTGIGVWDAENVLVADNAVHRCAGLPYKVDNSNDVQFLNNKAL-HSERFGLELDKSTNVVLRGNSFGQCNGGIsiknWGTKGTSVFAEGNYIdcaSYTGKqtnNYAISFDKNSDVTLKENYIFGSRSVAIYGESSAGKIvKIADNEISDITGNSAIQIKGGQRAEIVGNRITFKRKDDAAYGISLaDNAEDAIIAQNTIYSNNGKSIPNAIVTESSKRTKVLNNLLINGKMLLNKDDTNI--- +>C2WEL3_BACCE +---------YLIELSRWGI--INDGSKETEKEINNALQWAYDNGINRCILSSGTYLINAVGPPNDLQ---AGGIKIPDNMTLDLWHDTVLKVKANDSYSYSCIYLYNKNNIKIRGGTIQGDRYHHDFSTAPTGKLTHEWGRGINIIGCSNITIDNMNIKECTGDAIDVLSIGLMN--TQVYIPSSNITIRNCTLDKSRRNNLSLEGCDGVLVENNVITNAGiDDGTAPRFGIDIEGYGEGATDYVVPLNIVIKNNKFEGNVTTSICNFNGYNVIIEGNISDNTISYAYGTQTIIS-NNIFKRVDLTTKAISSIGTAQGLDFNNTTITGNIITGFDTALDIRGKNVTVSSNIIYDVK-IGISLFQAESILVQGNLIKKATFGKaIIINTCTNIKCTENQLK-DIGMLCIELNNSSAVTINQNDIFNSKQGIRISKSNAVlqgnSIDLNTF--NSPSYNIDFDATSNVLIINNLLKNCSSFAInlsNGSASSKS-RIIKNIIENFTAISAINLSGG-RHELIDNILIANKNIAGGYGINLHSCNQSTVLRNHIFSSSIYNLSTPIKTNTSTNTKIIEN------------------- +>A0A238U6X6_9FLAO +-------------------------------------------------------------------------ILLPSNFHLSLHEETVFRVQPNAFPWYSLMTIDKKENVKISGGNFIGDRYEHDYvPFFDrhgLKRSTHEWGVLLLVRGSENINIDNITLKSSIADGLITGSEGHRIYPETVW--NKKVSLTNSIVSDNRRNNISITDGEDILIEGNEILDAGiGETlkdndgntiyssagVAPRFGLDVEpfvGYDdfsfESRKTYEWVENVIIRNNIFKGNEAGSIIVYTGDNVLIDGNFSDHVIAQN-----NTSGSKIINNTlEARDDVRGRIGISTSDyrkfidfdggtlkqyaTGN--DVKNNTIRNFFGGYNIRGNNAEVSGNTVEGATVCLL------------------------INKAENIKVHDNTyTSGAIASKAIRLTDyANNIEIYNEKFT-LSNGFYLE-SIDFNMPNDDFHLN-------------------------------------------------------------------------------------------------------------------------------------------- +>LauGreSBDMM110SN_4_FD.fasta_scaffold226965_1 +-------------------------------------------------------------------------IHLPSDFHFKMSKSTFLRVQPNFWPRGVLLSVYEQKNTLVSGGNLIGDRYTHNYAPIKDElgiaRDTHEWPVLLSIAGCKDVIFEKIYMTDSTGDAcVTGATNGSRDIGGADKKFNQNVIIRGCVMNASRRNNISITDGEDIFITNCIIQNGGnGDTVkdasgnkivtsagtAPRAGIDIEpfrGYNPDGsfRNFEIVKRVTISGCTFKNNRVASIIDYSGINTTIKNNTSDHGFFASFSTGTKFLYNTFKASAINKDKVAIVTGnwiINNTQLSKNNEVTGNKIEGFRVGITTQGDEGNVSNNTI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_4058357 +-------------------------------------------------------------------------IKVPSNTHLLMSDNTFIRVQPSNNPFSRLLMTYKAQNVLIEGGNLVGDRYLHDYSnvtdEIGVSRATHGYGSLINIAGSQHVTVDNVNIYEGEGDGVLIQISAIRNKDGSIKAgemESSNVVIKNSLIDKCRRNNFSIIDANGVLIENNVISNAGGEhesgqayaGTAPEVGIDLEAYRERRSdgslyEYERVTNVTIRNNEFVGNDVADVIVYTASFVDIIGNTFDNRVGVHAGHDVKIANNEF--TAGERittqiAVSFDNFIVNETEhlTYN-IDVTGNTISGYDTAMKVGTQNVTVSENKIYDFVTGINITDI-ENAQISNNTLE------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1V5WUJ2_9DELT +---------YVVDTDKWNIPTDGSDPERTSAGLSEALAWAVDNGFGTVRLPAGAYVVG-----REINSMFIEGVVVPGPLRLDFEPGAIIQMKPNDHPFYCILDIADASDVWIRGGTVLGDRESHQY----VGESTHEFGTAVCVgsrGGSERILIENMSLAEATGDGITI-----NDAPG----SSRDITIRGNDIHHHRRQGISIISGSAIVIEDNEIHHIAG--TAPQFGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A090II36_9GAMM +--LLNSSIhiggdvhlsnaNFVFDNQRWGVvegIVNNEQAKENTRLFQYALNQAHNVHANVFRINKfdASFWVGNYKKFN--STEL-SGITLPSNIKLSMRHDTILRTQANGYARYALLGLYNADNVTIEGGVLIGDRDTHDYK--DPQSPKPYWGHLMKIGGSRNVTIKGVTFKNATADGLSIHSLGTYKRTGSIET--KNILVTDCLFDNNRRLGTAITSGSEIIVEHNTYLNSGqpseaSESVSPAWAIDIEGGYKDHEYLERPYNITIRNNIERNSYRGAFIGAIGDGITIENNNTENTIALG-SVFNSKAFNNTITRDLNKEY-LNPNGLSVAYDGEKMFYPTEEVVGnnevynnklIRARMYISGSGNSIFNNSISN-SLTGITIQKAKNAEIYNNSVHSNveNSIGLSARDSiNNVNVYDN--DFNIEGLAIRFISINE-KLGHENFS---------------MYLNNNRFTSSGY----NKAASVSRSRNVYFNENNFSNIGFI-MYtsdNIQLIGNRV-ETKTRIGLQIEEGNEQIKLHDNLVIHPEKKK---CIRNLSEQIPDIKNNV-------------------------------------------- +>SRR5690625_80756 +---------YELELARWNVSNNGTRPHETTKGINEALNWAKENGYTSLLIPDGTYSIAKGNAENDRHAR----INMLSDMTFLMSNNTILQKEPNGFEEYSVLHVGAgVKNVVIQGGTLIGDREDHNYSgkSGDWSSGTHEWGHGISIVGGENITVDGVKIKDFTGDGIYI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_9554453 +---------YLVELDRWGISADGTNAEATTDGINEAIRWAQGEGYGRVRLPAGTYLIG-----KRLYDHYTGGIELVDDVALMMDDETVLQIVPNDTWAYCGIAMSGVRNAGVYGGTIRGDRDEHTYG----GSMTHEDGHCICIgHESELVEIDGVTMEDPTGDGVAIVAEGGDG------SSCKHITIKNSEIARGRRQGISIVGGTNVWIENNEIHHIEG--TAPQFGIDIESLNFTSR------DIVIRNNRFHHN-RGGDFENADGKnVWFEENHLD------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>APAga8741243855_1050100.scaffolds.fasta_scaffold124648_1 +---------YTIDNEQFGIYSNNTHARTTTDGINEALNWAKSHGYTKVRFAAGTYLIQC--TWNNRYCAPDDGILVPSGMTLDLG-TATFRMEANNYPAYTIFGIVNKSNVTITGGTLIGDLGSHTYSSV-SGSSSHEWGFGICISASKNVVIDDVTIKNMTGDGVILeGSYAALSNGGRV---CSNIKVTDCTISNCRRQGISVIGAtDSELARNRIYGIKGTD---PQYGIDVEtefDYVVDDLKIHH---NNISDC-----SGGAINCNKGENYDVYSNTVtgDNIIA-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2G5GBI8_9FLAO +------------------------------------------------------FVIDKLDAYFKIDGPLSEGapvdlaIQIPSNFTFRMSENTHLRVQPNATDKCTLLSVYLnSDNAVIEGGNLYGDRDEHDYSDGIND---HGWGHLFTSRGSTNVTVRNVTMIDAAGDALKLEGEGHAVNPD--YAPTRNFLATGCKFIRSRRNNLSITAADGVVIEDCDFIDAGIHTdksqgTIPGFALDIEALKPN----ELSENIIIRNNRETGSRRGGFLVAIGDKVTFEGNVINSAINLQSARNCIVRNNIVTAQSDiAKEYGAGII-TGRSDRGNLVysnTIYNNTVNGFSTGISISNFDMKVYGNTINNCnrgmsigpvqnseiyentiiSNVDKSAGISMGASLNNVVVRNNDVNVMRygavFANVNNTDESGNytltfKGNNIVSGSSTPINSSHGIELIENTFNNAYEFYNCSNLNII------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A167HAM4_9BURK +---------------RWGVASNASNATATTDGMQAAIDWASSQGIGQFRVPAGEYLLGKIQTYN-----YAGGIKLPSNMALVLEPGAVLRMVPNDRWNYCVVTINGKKNVSVSGGTIVGDRYNHTYTPSSSGGTAHDEGHAICIEGSSQyVEVQGVYITQANGDGILIV--------GKAPSTPQDITITGNNFDTNRRQGISIVGGARVLIEGNQIHHTKG--TSPQFGIDIEPLGGylvrdviiRGNNFHHNRGGDVVNTRgfniliegnTMHQGEASTTGGDDGRT-----YIDGPIVFWPEADQTIRNNNI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A1I1IH73_9FLAO +-------------------------------------------------------------------------INVPSDFHLIMTDNTHLRQQPNANKRATLLAAYLISNTIIEGGNLHGDRDTHDYSDTSTSQ---EWGHCIRVGASKNVIIKNMNIYDAGGDGIDIHAYGHAYNSHYTYTENLLITNNK--IYRSRRNGISITDGRNIVIEDNEFIDSGVSTslsggVAPGWAIDVEAVRNSGVIFEIAEDILIKNNVERGSKYGGFIIHTGDRVTIDGNTMENSIAYAGTIGSVIKNNNLKSNSETALRGQTTGIIAQNKASSKdNSVYGNTVYGYPIGIKVGDTNLNVYNN---NILECAVG---------------------ISLNTSKDSRIYGNTIKSTT---------ANSRGISNHThdyISNLiIGSGLDENNESAKSNVIDVVgnaIVFNGIKEIENSDTHSIIIKNNIIE--NGANLWLIDINNFEMHDNVI----------------------------------------------------------------------------------------------- +>A0A238U509_9FLAO +--LLNNSLTIQGDiqltkneFDfipsKWGIvEGVTTNEISRT---NRDIL---ENNMTFIKsLGASIFKIDKMDAfFNVDEPDIlpsEAAINVPSDFTLKMTNNTHLRMQPNAAIRPTLLATFTASNVTIDGGVLHGDRDSHDYTTINS---THEWGHLLRITGTKNSVFKNIRFEDATGDAIDVHAYGHSFDPH--YTYCDNVLITNNIMLRSRRNHISITDGRNITVEKNDFIDASIHTnkstgIAPGFAIDVEAV-----RHGNPRGISeIAEDIFIKNNTengsrvGAVTVHTGDRVTIEGNKFENSISYSTSIGTIIRNNEIiattyknINNG----TAIVAGRADRYDDNYNGKVYGNTIENYAIGMTVSNKDLEVYANKITN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A0P0CI41_9FLAO +-----------------------------------------EGSFELVKsLGVSTFIIDAMDAYFKVDDENFKGyaytyaINPPSNFTLKMSENTHLRTQPTNFSNYALISVRDVENVVIDGGNLYGERDEHDYS----SGGSHEFGMCLTVSGSKDVTIKNMTITDALGDGIIIDNIG-HTYDSF-YTYTDNLLIQNNKIIRSRRNGISIVEGKNIVIDGNELVDTGITTskssgAAPMWAIDIEPVWENGIKYQIVEYVTIKNNIERGSEKGGFINARGWYITYENNTMENTIAIGETVGSIVRNNIFKNPGKNSNVAIaagmnDPLGYGN-ERNYDNEVYGNTITGFPKGIELQDPGIDLHHNTM------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>J8DZ85_BACCE +--MIEKVNIYVIELDKWNIKKDGTDAVNTTKGINKALLWAKENDYDVCKLPAGNYLVDK-----------DSNIEMVSDMTLDLF-GCTIRKETNGYQGYSIVRIFRQKNATILGGTIEGDKDTHDYSTIP---GTHEWGIGIDVSGlNRNIKIDSVKIKNTTGYGVRTGTeYGHLSW---VYTTDlESGTfsndgVLKADVNFTRSNkywriteypQIQENGYFSIMGNGYGFygsTKDGGEVNLDRVPITIYFFDESNKFLGKITKRTFDNIYYSSFPKGT----SKFKIGFRFNYNNiNALSMTIRSMTYTKGINVIN---TDIYGCRALGIAITGAQNMLV---DNCEIYGIGGINPGYAIDIED-----------GYNINQNIIIRNNYIHDNNNGAIVVVSARNVLLESNKFYG-----SVFLGGSRGENYLSR--HNLYncsfgtGSTNAGGGDAATITFrDDYMLEGQLYmegNAFYDNvcfDNMTFVLQSDTF---------------------------------------------------------------------------------------------------------------------- +>X4ZGB9_9BACL +---------YLIELARWGIYNDGTHPVETVKGINNALVWARQKGITATTLPAGTYLIDKASRIN-----------MVGDMLFDLPMDAVLQKETNGKERYDVMYVGYgANNVTLRGGTYLGDKLTHDYSQRDPyNTGTHEGGYGIFVEGAKNTTIDGVKAMNFTGDGLVLGGFGTM---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1A5YEI2_9BACL +---------HMIDLKRWGISSNGTKPVQTTQGINKALQWAAKSKITAVTLPPGTYLIDK----NSR-------INMVGNMLFQLSDDTILKKQENGKEHYELMFIGYgANNVTLRGGTYLGDKDSHDYSKKDNPHTpgTHERGYGITVLGANNITIEGVKGTHFTGDGLIIGAH------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2B8JB68_BACME +--------------EKWTIHNDGTYPIETTSGFNNALAWASAQGIHTFKVPAGIYLIK-----KGVDYDATARINMVSDMTFIADNKAIFQKETNGLTGYSVMYIGpQVKNAIIKGGVYKGEKDTHDYSI----SSTHEWGYGVLVEGGENIIVDDIEAYNFTGDGlligntirkgtyinssilesggldengnptnetgrirtvgrtqtnfddaiykelnsfyLWVPTgltknqydvyfydkdgkllerklnvnmwKGEVNIPkgadyfktvlyadstsgASVYryaiDNSKSVTVKNSKMHDNRRQGITVGGGYGVLLENNEIYNIRG--IAPQSGIDVEqGYGINGnvtirnnNVHDNVYGVILYDGIGATVEENQIKNHSYPGLVVQEEYKDALVQNNYfeNSGMSIK---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1M6AGX2_9FLAO +-------------------------------------------------------------TTNQNFYPSREAINVPSDFTLRMTDNTNLRVQPNSRKNYVLLAVRDASNVRVEGGNLIGDRLEHD---DNSQPGPHAFGFVLMIHGGSNVDLVGVRTILGTGDGIDVNSIGFTFEAG--YIPSNNIRITNCIMDSNRRNNMSITDGFNIVVDGCQFLNAGIDMPGspgmaPGVAMDVEAFrgkddAGNFILYERAYDLTFRN-NFEKGSKfGSFVVAIGEDVTIENNTTEDGIAIGAGHGIKIIGNTLIAAADDNiGAGITTGHPNSTDTYDNV-IANNRIIGHNIGIAAYQRDMKIYGNVIE------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>GraSoiStandDraft_43_1057313.scaffolds.fasta_scaffold3393195_1 +-----------IDNAYWGIVTETNTEqigIANMENINRAIKTAHENGIYKIKLAKATYWFDA--TSDKTTPSIG----LLSNMQFNL-XXAXLRVMPNNLTHHYFIYIESAENVKIFNGTITGDRYEHGY--VPATYPTHEWCHGLRVGSNSSNYCKNIEIYDLVVQE--------FTGDGINVSWSKNVTIRNTEVSNARRNGITIgSNTDETYIYDNYIHDTHG--VSPACGIDLEKAAGDGPKNIVIRNNRIYDCINPETGaeQGQAMAISGGsyQVTVRDNDIRGVIGFAYAEKILIENNRI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A229GVH8_9GAMM +---------------------------DDTAAIQKAIDAVAAKGGGIVEIPAGTYMINGAATsvLGPGDVPRTSGLQVKSNVIIRMADDTVMQVIPNGEKHYDIFNIYNAENVAIMGGTLRGDRHSH---LNDQG----EWGSGIKIASAKNVVIEKVIAREFWGDAVHISDSG-----SLPRTPSQNVTIYQLAADGNRRQGISITSADKVLIEDSAFKNTGGQgGTPPMAGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A098MBD8_9BACL +---------HLIELSRWGIYNDGTHPVETTKGINNALTWAYQQGITATTLTPGTYLIDKASQINM----------VP-NMLFDLTMEVVLQKETNDKESYQIVSLDYGDnNVTLRGGTYIGDRLTHDYSKKDhvGSAGTHEFGYGIIARGVKNLVIDRVKTTHFTGDGIILAGHGTM---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2A2AT09_9BURK +-----------------------------------------------VWIPAGTYMIDaTVNACGGWGQE-RCGLQMRSGVTVHMSQQAVLKAMPNGSRHYNIFHFNDVENAHVLGGQLQGERYAH---RIPTDGRLGEWGAGLVMRGARHAAIENVTAREFWGDGF--------------YVGGSSQNVKFCAVvaDKNRRQGMSITDVDTIVVQDSVFKNTHG--TPPQDGIDIEPWGqENEPIREHVKNVTIRRSQFINNagrGIGMVTTHPGqiENVVLEGNtFIDNSIGLGLgnrSWKTRITGNRIIN----SQY--LNIGLGPLAT--FITVTDNAVTG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_2407419 +-----------------------------------AAIQAAINSLPsaggTVTIPAGTYLIDTSKKIN-----------LKSNMLLKLDPNAILKAKSCSLIRHYLVYVNGKTNVEIAGGQLVGDRDGHNY----VGSSTHEWGHGIQILGSTKVTVRDLRVSKCTGDGVCIGG------------GASDVVIGNIIATNNRRQGLSITNCTNIKVYDSEFSYSKG--TSPECGIDIEpddGHSlstvliqncrmNNNGKYgmniwKRVSGVTITQCTLERN--GSLGLGTNGCSGIK--FTNNIVRYNSATGV------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1719318_174446 +---------YKLNLEDWDIPNNGHEPRKTTENLQKAIDWAHGNAYTKVLLPRGHFLLGIeaaakypwgwTNGKRKEDNFSMRGLSMHSNTEFILDSAATLEMVSNDKVMYCIICIEDVTDVIIRGGTLKGDRETHTYTP-HHNRTTHEWGHGILISDRvHRILVTNMEIKDVTGDGVYVKSEKK--------SIGSDIIIKNNDIHNARRQGVSIVGGLRVKIEDNEIHHIKG--TSPQFGVDIEG------PWTVTKDVIIHRNNFHDNRGGDVVNFDGKNVFITENKMIESDSYSYT---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>APHig6443718053_1056840.scaffolds.fasta_scaffold2008830_1 +-------IKYYTP-QQFGAVANDTG--DDTVAFNRALqAAASSSSTDTVFVPAGTYMIKADGG--------DGGVQVLSKTKLKMDPGAVLQVITNAERGYNCVRTNGVTDAEISGGTICGDRTTHTGT-------SGEWGHGIGIYDSTDVTISNVVVKNCWGDGVYI---GTAN-DNSTTAKSRQISLSGVTTDNNRRNGLSVVAADGVTVDGCLFVNTNG--TDPQAGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_7665223 +---------------------------DVTSQLQTVLTNIAKNGGGIVYLPKGNYMIKAtssdpswTNPQSLLTPAKLEGLQVGSNTTILLDKDASLSVIPNNFWNYLVLNIQGADNVNILGGTLNGDRLSHDMSNPNwtwnngkgfNSPYYGEWGNGLSIQSSNNTLVSGVKFKNFWGDGISLFPDKDQAEAGAL-SQAKNVHITGCTFDYNRRQGISVGHANNVEIDHSLFENT--DGTGPAAGIDLE---PGGGSTEQVTNVKIHDNVFLNNNNAGLTAYAAPKSKV--------------SDVHVYNNTFINNG-------------AWMPG---QITFNN-----------AEYIEIDHNKFDNDD--ASRFHSSWIVNTANDNIHDN-----YGRNSSirIAKEAHGEGKVTNNYVSSIMIENTGYDVANNHLPN-------------EISSTDLGTMGANWNYQNDVDYPGLATNEKVtfhdFNSRGKALNVTANPDNTVLNQSDPSNCQADISFDIDG---------------------------------------------------------------------------------- +>SRR5699024_10005537 +-------------------NAKGDGVTDDTNSINEAIDYAVENNINTVYFPSGIYMIkaDAEEIIPNGSK---GGIHLKSNITLKLDDNAILQAISNSAEGYNIIRAKESNNIKVIGGTIKGERSNHSGS-------EGEWGHGIHLKGCSNVYIQS-NIIDCWGDGIYVG--------GDVSTddskPTKNLIDENTVCDNNRRQGISIVSGKHIRLLNSDFINTNG-TL-PESGIDIE------PSHDRHIvrDVKVIDCNFNNNaGTGFLIDGKSG--SVEDIYVNGI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5207342_2131982 +---------------------------DDTRAFQDAIDAAKGG---IVIVPAGDYLIDPLHS-----------VRVRSGTQLRMDRNARLRAIPNAAPRAYVLLLQGVEDITISGGQILGDRKEH----LGT---TGEWGHGIAIYGASNVKVRDVRISGCWGDGISIGS--TKAGKGGVMRPSTDIEIANVASLGNRRQGLSIGRSRRVYVHDCEFSDTGG--TPPSAGIDVE--PDAG---DIAQDVRIERCILRRNrGPGiqvwkRATSVAIRDCTIEDNRNAGVLAVG-AIDLAIERNRIRGNG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_3757948 +-------------------------------------IQAAINSLPstggTVFVPAGTYLVDAVRS-----------VKLRSQMHLKLDPGAKLVAKPTSSESYNVVFADVAHDVEISGGQIIGERHQHKGTV-------GEGGHCIRIRGCERVTVRDIRLSDGWGDGITV---GPRPNRRKRFTYSQDVAIANIICDGNRRNGLSIGNVIGIKVYDCEFNNTNG--TAPQCGIDV----EPSPDFDgsgHCDDVHIENCRMSGNGAygMNVWKNTSNlvitKNTIEGNKTCGLVTRG-MTSSSITGNTI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>R6FQI5_9CLOT +---------YGVDIQKFNINNNGLNPIETSKGINDALNYAAKNKYDKITFPKGEYCI------SEENP-----ITMVSNLIVDLN-GATFKINDNGLQHYTVIDFSNCSNSQLINGIILGDRETHDYKTIE---GSHEWTCGIVFNNCDNCILDNVTISSFPG-------YGISSSLGENLS-DLIIGVTKENLSIGNINDKGkLNNKKGTIrtIDPLNISNVGGEfELGYNKGYMGYPYMQSKEYLSYFYDenmkfiSKVDNCKQYK------------KVLIPDNakYVHFVFKQDY-----------VPERGDTDFNGTTVFLTNYSSPNNITIKNCLIEKNKsLGMGIcGGYNWNIENNMFKenggGAPGYAIdledGWEYMDSFLFKNNKFigNNNDIVSCAGDN---IIFENNSFTSTVYMWG----RTTNYKFLNNSFSNIAMNINYEYSTDTECSGNTYnncriAITSK------NKDAEFNINNENIIDthvntmPENVSIIDskitADNIDNIRIYGN-FKDCH----ISKVTGSLVNFRGEKCKINNSN----------------------------------------------------------------- +>SRR4249919_2030177 +-------------------------------------------------VPAGRYLIDAVKS-----------VKLPSNRKLKMHPDAILVAKANNAEGYNVLLVERVDNVQIVGGQIVGERDKH----IGT---TGEGGMGIRFRGATNSSVTDTIVSNFWGDGI-VAG----PYKGSKYIPSTDITLKNVTMSGNRRNGLSVGNVVRFLAEDCKVLDNGNDPDGtgpivggtsPFCGVDVE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1S1V829_9FIRM +---------YYAD------AAFTKPATDATQAINSAVKHASQNGIQKVVIPSGNYLIKAEGvsaTGIEGDYAKTGGILLQSNMTLEMSSNAVLVTNTVNKPGYSLITVNNKSNVKIVGGKLVGDKDTH-------PANTHNACYGISiINGSKNIYVDGTEITKMEDDGIMITDYAIDQSGG---TRSSDIEIRNVKSHNNGRQGLTI--ATGSNIKILNSEFSNQTKHEPKSGIDIE-----IESYDHvgVKNVEISGNKFEGNAFSGVlfsnmfndrpnsmsenikingntingSRHgilAEGKSNGLDMSNNNITVNNYnvgqssvavgtlsaeSSGVVISGNNIISD-DSKAH--TSMGVYSTTPG--VSINGNNLVGQNVGMMLSGGGEQIVGNKIskvlatgihisgsnqnisENEISVSGAAHLssdsyhnviyaayAENLAIKNNNFHDMKSYGINlaegVRNT---EVSGNTMKNIgTEAFPNKnsflhiASENTGINVTGNTFDrGAYPTLYLGISYANSVKgANSFTnneiigFSSYGYGM-------------------------------------------------------------------------------------------------------------------------------------- +>A0A1M5UZK5_9CLOT +---------YTIELDKFGIKNDATFAVETSKGINDALQYAKEKGYEKIVFPKGEYLISELNPV------------VIDLKNVVIDlNQATFQINTNGLEKYSIIQIvDGAENIRLTNGIIRGDKDTHDYKTIKT---PHEWGCGIVFKGGKDLEMDNITVTNVTGYGIYTESGTNSNRFDAVYT-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5687768_13918870 +--------------------------------------------------------------------------------------------------------------VSIRGGKIVGERGAHHGT-------TGEWGMGVRLAGCHDVRIQGVQITDCWGDGIYVGANGVGN-------ESRRIKITECILRNNRRQGLSITGCIGALIRDCEFTDTNG-TL-PASGIDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A250E5Q6_9FLAO +---------------------------DDTEAIQNAINEASKKGGGVVYIPEGTYLIDAKQSLVIRS---NVTLQLAANAILEAKANTILEAKANTSERYDILYIKNVENVKVVGGTIKGDRNIH-------IGNRGEWGMGIGIYDGKNIVIENVSVRDCWGDGIYI---------GKNRNRSENIILEKVKSVNNRRQGVSITAAHKVTINHCVFSQTNG--IPPQAGVDIE-----PNAADTVSNVVIKNSIFDSNENSGILIYTGAERS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_21041421 +--------------------ADNTGSVSTQSAINAAIALQNARGGGVVYVPRGTYLIDT-------NYLTGGSVRVLSNVTLHLDPGAVLQAVPTSNGQGAIVWAYNAENIIIQGGYIRGERDGH----IGTDQP--DGNHGISIFSCDNVTVKNVRVSHCWGDGMYIRNDTGGNNTG--DTLSTQIRVLDSSFFNNRRTGLACVAVDGLTISKCYF--YGNTGANPYAGLNLEPNSDGWVR-----NCVVSDC-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1H9W652_BUTFI +---------------------------------------ASNGGLNTIYLPAGVYNITDIGNYDH-------GIELKSNVNLIMDKNAVLKVSGMPYGDYEIFSMRYLSNVTIAGGQLVGERYSHSgyYG---------ESGHGIAMHGCSNITITNMCISANWGDGIYFGTQAVWLGSGQGYFGNTNVTISGCDIFDNRRNSISFTDADYITVDRCNLRDSHG--TAPQCCVYFEPNGDSSDK-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR2546423_4745973 +-----------INVRDWG--ALGDGISDDTPAFAAALATLADRG-GTLSVPDGDYRIDPLKS-----------VRLTDNVALNLSRDAILRAIPVTARNSAVVLVERARNVRIIGGTIIGERDGH----LGVGG---EGGMGIWVSASSNVRIERVTALDCWGDGFYIAgwsGRGSYDANSLHESHSDNVTVSRCIARNNRRQGLSVVGCIGGLIERCGFTDTNG--TAPQSGIDIEPQG----------NWTVSNVTV----RNCVTARNAGWGIL---VCGNDIYNASVSDILIEGNR------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6185503_5510564 +-----------------------------------------------VDVPAGRYRIDPVRSIHLADSiamEMASGAVLAA-LPVAQGNSAVIRL--DGIQGAS-----------IRGGMIIGERDGH----LGT---AGEWGMGIQIMGGSTISVEGVRIEGCWGDGIYVG--------GRSGVEATHITIRRCVVTNNRRQGMSMTGCRDSLVEGCTFASTHG--TAPQAGIDLEpnggfvvegvtirgctvegnhGYGivLSGGREQHVQTITLDDNRVADNG-----FHGIGVVS--------------SVDCSVRGNTVEHNG---RDGVQIAGSSRVRlTGNTIRDNSRRTAGVWDNVIV--QSLSTDNTVANN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1E7DPH2_9BACI +-----------INITDYGANADDSK--DDTSSIQAAIDAAAGKN-GIVLIPAGTFLINT-------DPET-GSLNVKDNIEINMDEKTILKSIPNGLPIYRMLTIYNRENVKITGGTLIGDRYKHEGT-------EGEFGHGIYIGGnSSEITISNVRAQDFWGDGFFVEGNASQeTYP-------SSITIDNVESHNNRRQGISITAGKQIVVKNSIFSGTNG--TPPAAGIDLE--------RDPPYSLPLEEVELLNN-----------EVFNNEGY---GISFIYASNSSAQKNIVKNnkKGGIYIGGGVEQGIAKNNT-----VDDNFISENGLGIFVNfSTQNNISNNVIEKSKKDGIVliNHVGQN-RLVKNLVRDNQGNGLYIwgglHDQSGIVVQQNKiSKNSKAGIAVlNVLDATITD--NDLLDNAGAGLHREEAKESTIERN------------------------------------------------------------------------------------------------------------------------------------------------- +>F3B2U2_9FIRM +---------------------------DDTAAIQRAIDAVSAAGGGIVDIPAGNYMI---NTLHQTGHSYeRAGLVLKSNIIVRMANGAVLRAIPNGERSYQIFSITHVDNVHIMGGKLIGDRDTHIGNLGQT-------GYGVRITDATNVVIEDLYAGEFWGDGVFLG------------EDSRNITLYRVICDHNRRQGMSIVGGHNVKILESEFKRS--DGTPPKSGIDIEPEG------DHPIvsGVEIRNCLFEGSSTGFVVSNQySNSVAENIIFADNI----------VRGNKT---------AVNLVGIQSGEvTGNTIyhdqSITEN------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A177L0L1_9BACI +--------------------------IDDTDRIQKTIDFVNKKGGGVVTFPKGIYLIDA---------EI--SLKLKDNITLKFEKGAILKALPNNAESYEIVKIHDVENVSLLGDiTIIGERKEH-------IGKTGEWGFGISIRGAENITIENPFIKDCWGDGIYIGATTKKKY-------SKRVTIINPLIENNRRQGISVISAVDLTIISPKLLNTNG--TSPQGGIDFEPNSEN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A150W909_9BACL +--------------------ATGNGEVDDTIAIQNAIDFAYSNGNKTVFFSKGIYLVDSSTSL-----------VVKDGIVLKFENEAILKAIPNALERSEVIRIHDVKNVKILGyPEIIGERDEHLGS-------TGEWGFGVSIRGAENIYIENAKISNFWGDGIYIGSTAKKNY-------NINIEINNVELTNNRRQGISIISVENLLIKDATITNTNG--TSPQCGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1G2XYR5_9BACT +--------------------------------------------------PSAVYNIDADGTGDQ-----SAGLKLPSDVNVAFEEGSKLKVIPNSSTVYSVITITGKNNISLSGACIEGDRNFHTGT-------TGEWGFGISISNSQNITIKDVNVYDCWGDGIYIC------------SVSDRVTVRDSIFNHNRRNGCSIISAKNVLFENCVFSNS--DGTSPYKGVDIEPNYEsdilqnivfnNCRSYNnlakgfspafdgaliNPVSITFSNCSSDGDGTGfgidAGPRNTLGTITFRDCTSTNAVENGFSciaanINTVIDGLYIVNPG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6478735_8854003 +-----------VDVREFG--AKGDGRADDTDAFEEAIEALPAGG--ILDVPDGDYMIDTLRSIRLRD---GIHLRLARNARLIAQPNAA----PRSY----VILLRNVRDIRITGGAIVGDRDRH----LGLDG---EWGHGIAIYSVRNLVISGIHISKCWGDGMSIG--GKSAQKGQPATPSMDIEIANVTSVGNRRQGLSIGRSRRVWVHDSEFSGTGG--TPPQAGIDVEpdkgdivqgvriercvirgNRGPGIQVWKDTHDVSISDCTIEDNRNAGILAVDATDVTIRDNRIRDNTQVGIalrkgTRQVSISGN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1C7EEP3_9BACL +--------------------SYGNDKMDDTQFIQNAIDFQSSKGGGVVYFNKGEYLIDSTKSITLRD-----------NITLEFEQGAILKAIPNSAERYEIVKIHNVKNVNITGQvSIVGDRSEHTSSL-------GEWGVGISIRGAQDINIENVSISDSWGDGIYIGNTSKKNY-------SENIKINNSNFDNNRRQGITVVSVKKLEIINATITNTNG--ISPQSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1I2HG07_9BACL +-----------------------------------ARINAAINSLPasggTVYIPEGTYMI---NTGNPYNPVTNATcISLKNNITIKMTENTVLKAITNAYNNYAIFLVRAVSNVTIEGGILQGERYTH------TGPTAGQVGVGVWLEGATNVTIRDVTCKEFWGDGIYTLYHSTLG-------NTKKVTVENVSFIDNRRQGISICANENFRVIGCSFEttqgtdPAAGIDIEPELGgtvrdVTITGNVFKGNKIGiqalGDASATITGNVFEGNTMwGIYLASSSRYYSVTGNIVYASGNYGIyvntSTDNVISGNVVYNNG--------SHGIYLLNNADRNVITDNKVYGNS------GEGI----NVYKSFDNII-----------------------------NDNNVTNNKGRG----IFIAVSTDNSING-NTSSSNALSGIYLWNSKYNLVDSNRCSKNGQ-HGIFVKGDAANDSLSNSI--------------SNNQCKENSQTTNQGYQNIFLSSGAQGANTINNVQGNMCRAGGlankpqYGILIDaNTSETLLKNNDTRGGGAK-------------------------------------- +>M2U1I2_9SPHN +--------------------------------------------------------LDVVSPTNGRR-----GLVIPSGSHWVMHPEMRIRALPNASSHYEILNILDEEDIVIegNGARLIGER--------DTHRGAEgEWGFGLSVRGARNVLVENLIAEDCWGDGFYIGS-GRRKY-------SQDILFRNTKAIRARRNGLSLISVRGFLSEDHESAHTFGSA--PQWGVDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690349_1434838 +--------------DVTSMGALGNGVHDDTAAFQSA-IDALPADGGVIDVPPGTYMIDATHTsCPGRGTALQCGLILRSHVALSMDVGAVLRVIPNDQERYYAIYVRGLSDVEIVGGRLVGDRTTH----LGT---TGEHGYGIAIAGSSNVRVRWTEVSNFWGDGFIVSRTGGDTNP----TYSRYVTLDHVKSSNNRRQGLtVAGGVQYLLVQYSTFRDSNG--TAPEAGVDFE--------PDEPTVAPVSDIRLYDN--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_575702 +----------------------------------------------------GTYIING--ELEGHTYESVGGIILHDNIILQFAEGAILKVMPSESEFYSDITLKDCNNVSVLGATIYGDRSEH-------RGVTGEWGHGVKVIRGENINIKNVRVSDCWGD-------------GVYFRDTKNVTVEYVISDNNRRQGMSIVGGENIYVRSSVFKNTNG--TQPETGVDI----EPNHDYQVVKNISFNDCSFHDNVSKGLMLFTNGGT-----FEDIVVN-----NCSFSGN-----------GAESFRVSGRGNHCNIKITNSTLEHMALGTSA---------THVLNAS--------ADNVIITNNYID-----KIVLNNTSNSIISKN-----IIIENIVLVDSNtNIRIENNIFNDasdidrirlLYDEVYDDASKYIYITNN--TISGGKRGVF--VQSTEFLSLYSTINIKNNMFIGLTE---------------------------------------------------------------------------------------------------------- +>SRR3546814_95907 +-------------------------------------IYALPSTGGTVVVPDGTYMIDAVRK-----------VRLRSRMHLKLSSGAKLVAKTNSSPRYYVLDDGNASDLEISGGQIIGDRHRHTGT-------TGQWGQGIMIRGCRRVTIRDMRISDCWGDGMSISSI-RLNGRYDPWTPSNDVVIANVVSTGNRRMGLTLGGTRNIRVHGCEFSNTRG--IEPGCGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>R6GIV0_9FIRM +-------------------------------------------------------------------------LTVHSGQRLLFD-AATFQLTANGYDFYAVLNIHNVNNVTVEGGlTIIGDRESHTAT-------TGESGHGIRIVNSHNVHVSDVDIRYTWGDGVCVGGNGTM------AEISQNVTLERIRTYKCSRNGLSIIEADGVVVRDCDFTYT--DRTAPQYGIDVE------PNLGTATNITIENVRMLNNGIGGFALYTT----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A088F0B6_9SPHI +-----------------------------------------------------------------------GGVALSSNTIVYGNNAKITAFADYNQPAYNIFRIENIENVIVKDLELIGDRNSHTGTL-------GEWGYGIAVLGSRNILLNNVVSKNMWGDGVNIQMLN-ANQAGVTQdTHCSNVTLENCIFSNNRRQGLSIEDGSTIRVSGCTFDKSNGKA--PQCGIDIEPI-VAGRAFVD--GVTIEDCMFSDNeNSGILMESLNGPISnvtiqncffhHKKAKISNAVYIGINTSRNNLNTKIL--GNTFDKSLDrslyiTGGMYMAISGNYIakefivNSTDTNLPEFYTDNLV------IDNNTL--LSGLTLESGVRK-VTISNNKIESpirPNTSSIGIFNKSQRLIANNNefNNCETGIHSYNTTTTSAI-INENIFKNINIGVVAQLNS--KIISNQFINTGinktSGYG--------------------------------------------------------------------------------------------------------------------------------------- +>SRR5512133_1390 +-----------------------------------------------VSVPDGTYMINALTS-----------VLLKSNMTFSMSSGAVLKAITNSSSNYSILFANGVNHVNIIGGTIQGERTTHTGT-------GGEWGFGVRITGSQQIVVEKVLAKDCWGDGFYVSA-------------SASITLCNVTADHNRRQGLTITSVDGMVVRNSTFKNTQG-TL-PEDGIDIEpNAGET------VNNVLITGCTFTSNSGFGV------EIGVPISYTGQAWIKGVVVDgNTVTGSGVNTLSTSPRAGIEASDIPS--AGNK--ITNNYCANNGLGILLRngSNGMTISGNTVTQNTTDGIQVYSTDGNTITGNTATNNLGRGIYSTSNTNISISNNTVSG------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1X6W0S9_CHLAO +---------YLIDVNEWGISNDGTNPLETTQGINNALQWAYQNGYSYVKLPEGVYTVSKGSASKDYSENACILLQNDTTLDLY---GCVIQKEANGWDYYAAISIVEKRNVTILGGKIVGDHLAHDYATL--ANSIHEGCIGIIVeRGSRNITLNGVEV---------------MNFPG------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>ERR1035438_889792 +-----------------------------------------------VMVPDGTYMVNAV-------AQNAAGIRLGSKMTMKLSSGAVLKAIPNASGNYAILAVSFASHVTIVGGTLLGERGSH----TGTDG---EWGMGLSINNSAHVVVQDVTAKECWGDGFYVT------------SLSSDVTLCGVVADHNRRQGLSVTSVEGLVVRNSTFKNSVG--TAPECGIDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>WorMetHERISLAND2_1045183.scaffolds.fasta_scaffold180453_1 +---------YYLDPVVAGITegvVSDTIALANTVAINTALETAKTEGNTTFVVPTMDAYFDTGGNGNSREEEVSGAIQIPDNMHFKMGAGTVLRRQPNDkhhssllsviykpptstNRGYGSL---LGENVEISGGTLIGDINDHTyyvgatitspattttasiriqreyvptvyeipvtisnvttnateiasyintnlndmeatvdgatvwitpnqglYVLMDDDNTdlsniemvytpdyTFEFGFGISLYGAHNTYIHDITIRNFHGDAIFIDKTGLRNIDATLpsnFRTCENVLIQRAYMQNNRRQAISVVDCNgyednvalptpggagsrvGVIIDNCDIVDTGRDIYHlPAYGIDLECYRQLGAEYARVENVIIKNSRFSGNRKGDLNLYNSQYVQVFNNEFTYKIGHVASNNVSIHDNTFTYDPIVYPENTDnSVAISlfsyiaqdgITELVYDFDIYSNTISGYTFGIIVSGDRFNVYSNNISN----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_498154 +-------------------------------------------DFGSIVFPSGTYMVDG---NDPAGPGGRQGVRVPSNRAISWLDGAEVRVIPNSNTGYNAFLVDQVENVLFLNPRIKGDRDEH-------TGVAGEFGMGIEIRSAENIVLRDPYIYNCWGDGIYI---GQVSEAA---GPCKDIYIERGKVDNNRRQGMSVISVDGLFVDNTQFTNTNG--TPPQAGVDFE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A0Q9EPM5_9GAMM +----------------------------------QAVIDALPADGGTVYVPAGNYIIDPTRNLRLR-----------SNMHLQLADGAKLLAKRNSADRAYVLMAYKVSDVEISGGQIVGDRDNH----LGT---TGEWGHGVMVRGSSRVTIRDIRISRCWGDGISVGGAIVTGLPTVI---SQSVVIANVASTGNRRQGLSIGRSSEIKVYDSEFSDNVG--IAPGCGIDVEpdandlgttttvhienclitGNQGNGiQVYKRVKGITIKRCTIEYNgGYGILTiAPVSGYIAlnrIAHNYLMGVMLRSATTSYQVSGN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2G6EWH0_9GAMM +-----------IDVTDAGYDAKGDGTTNDTTAIQKAIDAVADAGGGVVWIPKGRYMIDTEARLKMR-----------SNVTVQMTDDTVLEAIPNGAGSYSIFRFYNVENAHLLGGTLVGDRDSH----LGT---SGEWGTGVNISSSSNIRVENIVTKDFWGDGFYIGENGSLD-------KSENIVLYNVVGDNNRRQGLTIVNGDNIKIIDSTFQNTHG--TAPAAGICIEPNDNN-----LVSNVEILNCKTINNDGDGIGLYE--RVNAINNEIEN---------VRVDGNEIIgNSGGIIVSG--SV-TDSTITNNFINTmeTDSSEPGIRL----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_10317103 +----------------------------------------------------------------------GASIRLHSNSQIVIAPGAMLRAIPNNLNNHALFYCYDAENVYVTGGTLLGDRDDH------TDAEDGvNAGMGWRISASSRVTVERQRILDFWGDGIYV-RNGTVETED-YDTLSTQVEIRQVECNNNRRTGIAAAGVEGLTVWKCWLRNTNGANpfAGANFEPNIDGYvrnvqvqnslaeGNAGAGFQtSGHDVTFDACTGRGNGtNGFRILNTTG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>S3Y1Z0_9ACTN +---------------------------DDTAAIQRAINQASDAGGGTVNIPGGTYMInpiavDSVHGLMMRN-----------NVTLKLADDAVLKALPTNTTHYSLISFVKVENANLVGGTLIGERYQH-------TGQGGEWGHGVNIQSSQKVTVQDVTSKDFWGDGFYIGQAWQV-------WDARSNQVALCNVTsvNNRRQGLSIVDGTNIRVLNSTFSRTNG--IAPQAGLDIE--PENGNLVEN---VEVRDSVFSENlGDGI------------------VLTWGEQNDASIKG---------------------------VRLESNQVLDNESGIMLhRAIGCQVINNTIRNAGN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_4714463 +-----------------------------------AIDYAVEKSIDLVWVPKGVYMIDAAGVNGEK------GLRLRSGITLKLHEEAVLKAMPNNVANYSILRVYDSANVKITGGSILGEKNEHTGT-------GGEWGMGIDIQSSNNIEISNVKVKECRGD-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1041385_954775 +----------------WG--ALGRSSPDQTKDDTQALQAALDSGARKVTIPNGHFMIDAARVQPGRTK---AGLNLPSNIELIMGTETFLHARNNSSISYNILVGWKVSNVIIRGGVLVGDN-------VTNSRRpdSNPSGFGLALFGAKNVWVYGLTSQEMFADGFFVCYD---DEPGS-HDECENVHLMDCRAYKNYRQGASVIGAKNSSIEGGQYRQTGGSP--PQDGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5581483_5383682 +--------------------AMGNGSMDDTKAIQAAIDALPESGGTII-VPNGTYMIDALK-----------GISLRSHDRLSLASGAALKAIGNSERRSWVVKVWNVNNVEIVGGGVIGERYSH------RGTSGGEWGYGINISSSDKVYVHDITIQDCWGDGLLIGALG--SGKGMV--EATNITLNRVKSKNNRRQGMSITPANRVYVVNSSFTGTHG--TAPESGIDIE---PRSQGWASQVRLENTDLS-NNNGNGlevhhNVDALTLYKVTAKNN--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1G7HPV6_9FLAO +------------------------------------------------------------------------GLRIRSNSKLYFQKESLLKLKSSAKVLYAILNIAKVENVSIYSPTIEGDRYRR----VNPEDKKGEWGMGIWIQESKNISVFNAKVTHCWGDGIYIGG-------GRDIVPNDSIYIHRPIIDENRRNGISITSGKNIRIIEPVVSNSRGKS--PESGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1G2Y1Y7_9BACT +-----------------------------------------------IRFPAGTYAIDGFDeTIDKdGNVTVYGGLKPASDTTLIFDIGAKLKAIPNDKIGYSILKIEGKNNVKIYGPTIEGERDSHTGT-------TGEYGMGIMLEGATNIVIKDANVYNCWGDGLLIGVHWT--------KPSDQIYVENSTFNNNRRLGCAVTNGTNILFKKCTFLNSNG--TAPQAGVDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1035438_766262 +----------------------------------QACINAVAGTGGTVVVPDGTYMI------NATHGSGVWGLMMGSNMTFAMTSGATLKAITNSSTDYGILCSNGASNFTITGGNIVGERSTHTGS-------GGEAGMGIYLNAS-NVTVSGVNVSECWGDGIYIC------------DASSNITITNCISNHNRRQGLSITAGNTFLISGCTFSNTTG--TDPQCGIDIEPNGSVPVTGVH-----ITNCQIFGNAGGGVQQGNVGNV---------------ASGTLLENCNIYSNGGG---GYNDGGIRFVETHDNI-IRNNNIHNNLNGgiMLDTNAGIGCPNttltgNTVANNSGWGIYANLCNGSAITGNTI-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_3394488 +----------------------------------------------IVDVPAGTYMIDAETSILMRD-----------NTHLRLATGATLKAIPTSSAVYNVILCELVDSVEISGGAILGERDAHTGT-------GGEQGHGIRSRGATNVYIHDIHISKCWGDGI-DAGPDKSDSHNYVYT--ENLTIDNVVCTQNRRNGLSIGNVNTARVTDSEFSYTNG--TSPQCGIDVEPDGDADGDGDCS-DIVIDNCRLNNNAVYGINLYQRARgVTISN--C--VIEYNSSCGIVSNG--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR4249919_325582 +-------------------------------------------------VPAGKYLINPVRVASGTS---FYGLLVGAGKRLEMDPNAVLVLKPNSAPRYCGVRI---DGGYMQGGQVLGDRLSHNYS----SGGTHEWGYGVQLRGTDSKAV-GVKVSQCTGDGF-----GMSGI---------RPVIENCISTQNRRQGVSLFGSDGLRISGCEFSNTGAlngqAGTNPRCGVDFE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1E8BK68_BACMY +---------YFLELERWNVKNDGTDANNTSKGINNALLWASQQGFIEVVLPMGIYLID------ENTP-----IEPQSFMTLNLG-GATLKIRDNGLVKYAIVrYQRNQKFSRITNGRIEGDKDTHDYTTIP---HTHEWGYGIEVgnttpiEGSniSYISIDNMEILNCTGDGI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>SRR5512142_681238 +-----------------------------------------------VYVPRGTYLV-----LADGYRDGGrGGLAPRSRTRVVLAPDAVLQARPTGSSDYVVVRIERVSGVTVEGGTIRGERHEH------TGRGG-EWGFGIGIFGASDVVVQDVTIRDCWGDGLFIEE----AQPDFSVMP-RNISIRRVVSANNRRQGMSVPG-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>D7W8T5_9FLAO +-------------------------------------------------------------------PLMTSGIFAQSNSQIYFQKNSSLILKPTADVRYQIISLHAVENVKIYNPTLIGDRDRHLGS-------KGEWGFGIDIRGSRNIEIYNANISDCWGDGI-VLVKTMRNMRSGVakenIFPTENINIIGGFINNVRRNGITIAGGKDIIIKNLLIANING--TNPMAGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_487370 +------------------------------------------------------------------------GIVLSSNTNIYFDVNSKLILKQSSKESYSMLKIYNVENVNLFNVHLVGDRYQHIGS-------EGEWGMGIRIQNAKNINIYNSTIRDMWGDGIYITSFG--------NTSNQNILIQSSWIDNTRRNGISIISGEDINIDYVKISNTNG--TAPASGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>H6LBC8_ACEWD +-------------------NAKGDGKTDDTSAIQNAL-----NKSDSVYIPDGTYMIN-----------VDQSLKPNSNQTITMNANAVLKAISSSRGEQYVITIDGVTNVSIIGGKIVGERNEH--QGLDG-----EWGMGINvVNGSSNIVIKDTTISDCWGDGIYLGGSPAVN----------TITIDGVTSDNNRRQGLSITNAKNVLINNSVFKNTNG--TAPEAGIDIEPnvnqaaedikimntqcYGNNQSGIDilgnngGIQRVEITDCTIKDNvGLGILLFEASGitfaNTSVTNNKDDGV---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6185312_3767693 +------------------VGAVGDGTTDDTWAFQKAIDSVAAQGGGTVYVPAGTYLIDADVSINMKD-----SVTLD-----MVDTTRVLMAKPTATVRNYVIKLNNISNSKVIAGKIVGDRYQH----LGT---TGEWGMGMGINGSTNITVTGTNIIDCWGYGITISSYNCV---------LKNVI---CD--NNRRQGLTIGSSDSLIVDSCTCTHTNG--TAPQDGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A0D5BSE2_ELIMR +------------------------------------------------------------------------GLVLNNNQVLLFQEKSVLKLNPTTQKEYSVLGLSNVNNVKIFFANIEGDKYQHLTNV-------GEWGFGIGIFSSNNISIYSPYIKQTWGDGIYIGQ--------IKNIPSTNIQVYNAVIDDVRRNGMSITSAKNIDVVNAYISNTNG--TSPESGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_13262863 +------------------------------------------------------------------------GLKLRDNSKVLFQQNSVLILKPSSKSQYSIILMDGVSNVKVYFPKIKGDRVGHKGT-------KGQWGMGIWINNSQNILVHNPYITNCWGDGIYLG--NVNNRP-----PNKDIQIIDGMLDNNRRNGISIISGRNVEINGTFISNTNGHN--PQSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1035438_2623855 +------------------------------------------------------------------------GIRFGNNMTLRLDSGAILQALSTSSSSYRILLLSGVQNINIIGGTIIGNR--NNNTITDSV----EDGMGIQIANSQHVVIEGVTVQDCWCDGVYVS------------DGSGDVTLNGVVAKNNRRCGSAIVSVSGMVVRGC--------TFQGTTGMMENGLWANGTGVDVEPNLgeTVQNIQFLGN---TFTQNATGGLGIGPSNAN--MATTFVINCVIDGNTVSSNGDAVK---GTFGIVASSTGGH-QILNNTVtNNYGVGIYLYGdaSNILIQGNTVSGTS--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2A8TS41_9BACI +-------------------------------------------------IPDGTYMI---------NADI--SLKPNSNQILSLSKKAKLKAKPNSDASYQIINIIEKENVIIEGGYIEGERDEH----VGVNG---EAGMGISiVRNSKNITIRNTHISKCWADGIYIGG----------YLPCYNINIYNVTCDNNRRQGMSVVNVDTLTVRDSFFTNTAG-TL-PEAGIDIE--PEN---YSTVKNVTIDNvvCTGNRSGLDVFgWAKTISNVQVLNSSMINNREYGlsiaFTTDILV----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5687768_6663082 +-----------------------------------------------VYVPAGTYLVDATRT-----------IRLRSRMHLKLDPGAKLLAKATSADRYYVVNAYKVHDVEISGGQIVGERDRHIGS-------SGQWGHCIGVRGCKRVTVRDIRLSKGWGDGISIGAAN-----GTTTVLSDDVAVANIVSTGNRRQGMTIGRCRNVKVYDSEFSYTSG--IKPGCGIDIE---------PDPFgtivcdTIRIQNCWIHHNaGNGVQVYKTVKNVTIK----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_2031064 +-----------------------------------------------------------------------------SNSYIKFHPDAVIKVNPNNYGDYDRKYgviiIYMKDNIVIKNPRIVGDKHEkpKNYKKIDSE----EWAAGIQIeRKSNNIKILNPHITAMWGDGISdSAGRKSMGEP-------DNILISNCFIYDNGRNGYSITASSNTKVFGGIISKT--DRTEPISGIDVE-----PAQYSRDVSgLNIKDVKF-TNGRGLILFKASQGAVIED---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5688500_1121635 +---------------------------------------------------------------------------------------------------------------IVGPGRITGARMVHRGS-------SGEWGMGISAWNSTNFRITGVEIADCWGDGIYVGSAGNGYCDGFLI---EGVKVRNC-----RRNGISVVAGRNGEIRNLDIAKI--DGIAPRGGIDLEPNSSNAPNRN----IRMSNGRIRDVAVGIYVTVANQRVSISgmDIEAENsgIIVSDNSVDVRIENNPNIKSlIGGKEGGAFRTVVTRPETIRGLLIRNNQLSGggaFVIDIFGQGyQGLVISGNRISatNAGTQGIA---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_32025263 +------------------------------------------------------------------------GLKVKSNSVLEFQENSLLKLKASDKHTYNILEIHSVQKVKILNVKIKGD--------LDTHiGKDGEHGMGISIRSSKDVEVVNAKIEDCWGDGIYIGRLNRYDRNGM-FEPSENIIIRDAYVNRNRRNAISITAGRNNLIDKLDANKTKG--TFPIIGIEIK---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5579883_944156 +-------------------------------------------------------------------------IQLRGRQEIIFEPGVVMLAKKGEFRGTGDSLLSIVgqSNLVLRGYGAILRMHKPDYQA--EPYKKGEWRMGIAIRGCKNVLIEGLRVESTGGDGFYVDGGADRGW-------SEDITIRNCTAYDNHRQGLSVISAMNLAVENCVFASTRG--TPPEAGIDLEPDTEENRLVN----CLIRNTVFQNNNGHQVLIHlkplsrKSMPVSIRFENC------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1T3DZL3_9FLAO +---IKKDGSYYERQFEGGINPAWYGEL-TEKSINKALHIASVLN-------------KDVELMNDYKIDCSGidtGVKLLNNSVLRFSNNARLLAIPSSSGNYRMLSIDKVKNVKVYNPVIIGERSAH----LST---TGEWGYGINITNSQNVEIHNAVVKDTWGDGIYIGG-DYFDKTQTISTLTDNVLIYNPYIDNVRRNGISICSVGKVRVYNAVIKNVNG--ANPQSGIDIEPEGDTG---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5699024_10516162 +-SLLDRIVLYVDDF-----GAVGDGVSDDTDAIQQALNVAGELRTSVIFTKGKTYMTDG-----------SKGILPPSYSTLIMTGSKL-EVIPNALDRYICLYVLIAEHVTIIDPDLKGDRSNHittpSTNNNNVDGFTGEWGFGLRIARSKNVNVYNCKTSDFWGDGVLIGTDGIENTP------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5262249_48802186 +---------------------------DDTSAIQAAIDAVAEKRGGTVLVPNGTYMVSAVR---------DNRLSLKSNVTLRLANDAALKAIPNDSDHYSVLRIANVSNVAVIGGTFEGDRNEH-------SEKTGDWGMGIWIgKGAEHVTISGVTATKMWGDGFYI---------------QDANDVRLCSVvaENNRRQGLSIIQVNGLEIKNSTFKNTHG--TRPSAGIDIEPDNDE----QHVANVRIHDSKFLDNaGAGIAVVAKKSLVS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>ERR1700750_2813068 +-----------------------------------------------VEVAAGEYLID-----------VTKSVKLRSGVALVLDPDATLRAIPTDAGNSAVIRIHDATGVRVEGGSIVGERDKH----LGTNG---EWGMGLGARGSHDVLIQDVLISGCWGDGVYVGS-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR2546423_7159601 +--------------------ALGNGVVDDTAGINAAIRSLAGTGGSVL-IPAGVYLVD---------PTV--SVQMASNVSLLLDDSAILQAVPVAAKSYAVIAASGVHNVKISGGKIIGERQTHLAA-------TGEWGMGVRVMGSSNVQIERVE--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5680860_103890 +-----------------------------------------------VLVPNGVYMVQAV----------GESLALGSKMTLRLADKATLKVIPNGETRYYTLRIHEASDVTVIGGTLLGDRRAH-------KGKKGEWGMGLHIVRSSRVTIAGVTSTRMWGDGFYVA---------------DGTDIAFCSVAaiNNRRQGLSIISANRLLVTDSVFRDTRG--TRPSAGIDME-PNKASQRIAH---VRIERSKFIGNaGDGIVIQGYKGRVSnveIRNNLFD------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A1Z4RLG8_9CHRO +------------------------------------------------------------------------------NQKILFQPGVVLEAQPGAFKGkYESMVSVMADNVTLSGYGAEFKMRKADYANPSLYEKS-EWRHNIHVRGARNFIIEGLTLKDSGGDGI-LVEHGPNEPNQLPVSKYSSGTIRGINASDNYRQGISVVSAKDLLIENSTFQNTSG--TEPASGVDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2B2C9D0_9BACI +---------YILELDVWSvsntVSDFNDKTLSTanSNGINNALTWASQRGYSEFMFPKGTYLIDE-------------NIPIqPKNFMTLNLNGSTLRIRNNGLPKYS--VICYRQNQIfsrVTNGIIQGDRYDHDYSN-PGELPTHEGGMGILFPNTTDpskgegtntlfTTIDNIEFLDLTGDGV-----SLFSSQGLVYattTPTKSYAI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A2C2T0P3_BACME +---------------------------------------------------------------------------------------------------------------------------------VDNERYTHEWGQGIEIAGSNHVEIKNIEICDCTGDAV---STGWLKYrtNSTDYTQNEmghHIWIHDCDIHHCRRQGITLASANDVCVYNNKIHHIGkaddnvtsdfRNGIPPMFAIDIESmVGESNIPYKQPYynkdglelnfRLYIFNNHIHDNQRGHFVNADGNHVTVENN--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5215813_7905647 +-----------------------------------------------VFVPKGVYVVDAV--AKKRRLTLG------SDMTLKLDNDAVLKAMPTDSRKYSILTVSGVSNVTIVGGTLEGERAQH----MGNDG---EAGMGIRiVGGAEHVTVSGVTSRKMWGDGFYVEDANDTKFCG--------------ETSDGnRRQGLSIIEADGVLVTDSVFSNTHG--TRPSAGIDLE--------PDHPSQqivnIRIQNSKFLNNaGPGIEIAGKKGLVT------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6185312_5921845 +----------------------------------------------------------------------------------------------------------------------VGERQNHVYSGIGTG--TDEWCFGIQILGVTGMTIRGTQISQCTGDGIDLGNFGS--------SISSDIVICDVISTQNRRQALSITGGDGIFVYDSEFSYTNG--TAPLDGIDIEPGGAGAS------NITIENCLIRGNtGCGiQLNAHWGDIINVNVKNC------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690625_4101829 +------------------------------------------------------------------------GLEIHGNSTVFFDEGSVIKALPTSNGNYSILSIKGVDNVKIYNANIFGERNEH-------QGDTGEWGMGIRIEDADNVLVVNLKVSDCWGDGIYL---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1H6XJ90_9FLAO +------------------------------------------------------------------------GLNLRSNSVLVFQENSYIWLKASSKPNYGVINIKDIKNVTLINPRIVGDRDSH-------LNKIGEWGMGINILNSDYINIFNAIISKCWGDGIYIG--------NKINGFSSNININGGLIDNNRRNGISIVSGEVVVIKDITVSNTNG-TL-PMSGIDLEPNTNEDTLKDIKL-VNVNSFNNRENGyliyLGGLLGENKREVDISiescfDQYSNTVVSIpGLRNDYEKKVKKI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>SRR5512133_257377 +-----------------------------------------------VTVPDGTYLVNALTS-----------IQLRSSMTLSLSGGAILKAIPNSSSSYTILRISGVSNVNVVGGTLLGDRSAHAGT-------SGEQGVGLRITGnAQHIAVVGVTSKECWGD-------------GFMVADASDVTLCNITADHNRRQGLSITGGNGIVVKNSSFINSQG-TI-PEDGLDIE--PNSGQIVSN---VLITACVFANNAGDGI---ENGVPVL-------FTGLAFIYNVVIDGNTMTGNGVGTLHAGPRSGIEVSNTSGHV-IKNNTIQstaGYGIYLRDGVAGTTVTHNTVtKNALN-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A110B3A3_9SPHI +------------------------------------------------------------------------GLSLISNSTVIFRKYSKLVLQANGLPAYQILRIYNATNVNLYFPVVQGDR--------DLHSGNGQWGMGISISGSTKILVVNPKVSKCWGDGIYL---GRQN-----NAVDRNITIFYAELDNNRRNGLSITCADGVHLIRPIISNTAGQM--PMSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A229UP75_9BACL +---IGSPVSYAIELDRWGIQNNGTDAETTTRGINDALVWAKSAGYNHVVLRGGTYLI-------QVDPN-GTAIYMPSGMHFEMHHDCILQLAGNSFPNYRMIEMKGIRYAKVSGGKMIGDKAFHQYEM------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5262245_13989197 +-----------------------------------------------VVVPNGIYLIDAAGE---------NRIKLKSDMVLKLSDGATLKAIPTDAENYALLTIADASNVWVIGGTLEGERDRH-------KGKSGEWGMGIRIgEGAKYITIMGLTSRKMWGDGFYVRG---------------AEDVRLCGVtaDANRRQGLSIIEADGLLVQKSVFKNTRG--TRPSAGIDF----EPNRDSQEISNVRIENSKFLDNaGAGILVAGKKARIT------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5215831_1849565 +-----------------------------------------------VLIPAGTYMVNAVDS---------NRLSLKSNVTLKVANTAVVKAISNDSEHYSVLRIANVSNVAVIGGTLEGDRNQH-------LGKDGEWGMGIWIgEGAEHVTISGVTALKMWGDGFYI---------------QDANDVRLCSVvaENNRRQGLSIIQVDGLEIRNSTFKNTHG--TRPSAGIDIEPDNDE----QHVANVRIHDSQFIDNaGAGIAVVAKKSLVS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>OrbTnscriptome_3_FD_contig_123_161973_length_414_multi_3_in_0_out_1_1 +-------------------------------------------------------------------------VKLRSNINIVFEKGVVVladEASQKGNAKYPMFEVKNVSNVAFIGrGDKPGDVYIGKYRDNEERRRmCHDYgGSGFAIEGAQNVVIRNVKVAECSVDGISLSSLGRLN---------SNIYVQDVILDGNYRQACSICNADGLYFKNvAFLNTSGGD---PMCGIDLEPTYE----LEPNSNIYLFDCRFEGNVGGGLnfTSSSYYPVTLHAKRCD------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>SRR5262245_2037218 +-------------------------------------------------VPNGVYMVSAVE----------NNLKLKSDMTLKLAGGAVLKAIPNDATHYAILTISGVSNVWVSGGTLEGERSEH-------RGKLGEWGMGIRIDDrAKNITIAGLSSKKMWGDGFYV---------------QEAEDVRFCGVtaDANRRQGLSIIDANGLLVLNSTFKNTRG--TRPGAGIDLE-PDKDAQQITH---VCIENSKFFDNAGGGIMVAGNKKARV------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +>A0A0D4DCI2_9CAUD +--------------------------------FMVGYIYATSKNRPfVVDIP---IYVQSTRKQSGFYNQVHYAVVAQSNSILWFMPEGeLIQIGVD-EAAYSILSLYGADNFLIKNPKLRGDKY-------TKTGNTGESGFGLTVTGCSNGIIEYPNISECRGDGIYLGQEYFNNNASSLI--PKNIKIIKPTILDSYRNGLALSAGEDIYFDAPFIDIAKG--TAPEACIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5688572_15557399 +-----------------------------------AAIQAAINSLPstggVVSIPAGTYLVDTTKRINLR-----------SLMLLSLASGAVLKAKTSSVRRAYILNVNNVRDVEIAGGQLVGERDTHKYVSGTTD----EWNHGIAINGSARVTVRDIRISKC----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6266566_4873650 +-----------------------------------------------IHVPPGTYSVDAV----------SGSINLKSGITLDL-TQATLVANPNNQIFSIIMRVSDCENVTILGGTIRGERTTH---LGSTAAFMGGGGGGVAIWRSKNIKIQGMKISDCFCDGLLVWHSGQVEIanviadhnrrQGMSLVDSHDVHIHNSQFTHcggtppgdgiDIENDLETETCANILVEHC----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>G2KPW0_MICAA +---------------------------------------------------------------------------------------------------------------------------------------------GIEVQGGKTVTVSGNNMDDVRGNGIQIsSSQGAVNlldnvvsdirlHGIVVNTAPGAVVVDGNRVTDAGEFGIYTNGSKNVVVSDNRVS-------GGKNGIVVQNAAAS-AKIENNVVSGASDAGRVASGYqtaiGILVKDSAGAVSVTDNRSNANTGDGiriLNTDGAVVSGNITNDNGDK-------GIIINRSDNAV-VDDNRSNGNATGIWVElSNGVDLTNNVIRHSKVDGIHLRDSDNTLVQGNQIlsNDRNGIFVERSDSADIFRNTITGSGGYTGVKVEGSSNTDIGATDQT-SWVQTGFWPWQGHFVtTVRGNTITNFDNGVTVAGGNDNDV--VRNTISgVDYGVRLSGAT---NSDVLGNDLTG-NSIVGIEVVAGSHNAVIDNNTLDHFDT----GIVVNGSNNVDVTDNDLTDVGSGIVA----------------------------------- +>SRR6266511_2426516 +-----------------------------------------------------------------------GGLVPRSNTHLHLAPDAVLKAKTTSASDYNVVRIERVSNVVVEGGTIAGERHRHAGS-------GGEWGYGIGIFGATNVTIRNV---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1Q6A375_9SPHI +------------------------------------------------------------------------GLTLHTGQKVYFKKGSVLNLVPTAQPNYEMLRIHDVTNVSVYNVVIKGDKYSH---LV----KTGEWGMGISIRGASNINIYSAKIEQCWGDGMYIGTTPKQAF-------CENINLRYVNCNDNRRNGISVISARNVTILGPVLTNTSG--TQPMCGLDLE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690554_4058803 +------------------------------------------------------------------------GLNIISNQILNFSQNSKLIMKTNAEERYGILNIKYVKNVIVNNPNLIGDKEKH-------LGNRGEWGMGINIWASKDVTINNPRISETWGDGIYIGEPPVQE-------------KQKKKLKSYANHNIAIN---GGVIDDC----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR6516164_3930632 +-----------------------------------------------VLVPNGTYMVNAVGDAR---------LFIESNVILKLANDAVLKAIPNDSKKYSVLRISNASNVAVIGGTIEGERYGHSGNV-------GEWGMGIWIgEGAEHVTISGVTAAKMWGDGFYI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5262245_45879959 +-------------------------------------------------VPNGVYMVSAVE----------NNLKLKCDMTLKLAGGAVLKAIPNDATHYAILTISGVSNVWVTGGTLEGERSEH-------RGKLGEWGMGIRIDDrAKNITIAGLSSKKMWGDGFYV---------------QEAEDVRFCGVtaDANRRQGLSIIDANGLLVLNSTFKNTRG--TRPGAGIDLE-PDKDAQQITH---VRIENSKFFDNaGGGIMVAGKKARVS------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>SRR5690606_56255 +----------------------------------------NENN--VVIIPKGTYRVT--------------GLKLKSNFSLLFEEGAELELIANNKERYEILSLAGIKNVKIYNPVLIGD-------IRKRNSLKGEWGFGIDIRGSREIDIYSPFIKDCLGDGIIIS--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +>A0A1I0S8N9_9BACT +------------------------------------------------------------------------------------------------------------------------------FATIEGDRSTHkgaagQWGMGIAIRAAKNVNIYAPRISKCWGDGIYVG--------GLKGVTSSNINIYNAMLDYNRRNGMSITSVSGLKLVAPVISNTYGQT--PMSGIDIE---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/test/unit/data/uniprot.mode2.txt b/test/unit/data/uniprot.mode2.txt new file mode 100644 index 00000000..17b94b62 --- /dev/null +++ b/test/unit/data/uniprot.mode2.txt @@ -0,0 +1,120 @@ +>O31912 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A6H0H3G5|A0A6H0H3G5_BACIU Right-handed parallel beta-helix repeat-containing protein OS=Bacillus subtilis subsp. subtilis str. SMY OX=535024 GN=HCN55_11075 PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A162RH73|A0A162RH73_BACIU Uncharacterized protein OS=Bacillus subtilis OX=1423 GN=B4417_1688 PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A6M4JNF4|A0A6M4JNF4_BACSU Right-handed parallel beta-helix repeat-containing protein OS=Bacillus subtilis (strain 168) OX=224308 GN=HIR78_12405 PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|O64135|O64135_BPSPB YorA protein OS=Bacillus phage SPbeta OX=66797 GN=yorA PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>sp|O31912|YORA_BACSU SPbeta prophage-derived uncharacterized protein YorA OS=Bacillus subtilis (strain 168) OX=224308 GN=yorA PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A857HHC0|A0A857HHC0_BACIU Prophage-derived uncharacterized protein OS=Bacillus subtilis OX=1423 GN=Bateq7PJ16_2250 PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVKGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A410R1H8|A0A410R1H8_9BACI Right-handed parallel beta-helix repeat-containing protein OS=Bacillus sp. WR11 OX=2448811 GN=D9C22_10995 PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFSIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNTELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGVSSTETSNRIQITDNNIQGFKIGMMIRGKGVSVDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSTYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGTRVLSHPYATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A7G5CIE1|A0A7G5CIE1_9CAUD NosD domain-containing protein OS=Bacillus phage vB_BsuS-Goe12 OX=2586960 GN=hypothetical PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNLNPIETTKGFNEALIYASENNFPIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGFSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVCNNKGKGTTSTYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYFNGTKKVRLIRNDVQGIGTRVLSHPYATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A7G5CIX1|A0A7G5CIX1_9CAUD NosD domain-containing protein OS=Bacillus phage vB_BsuS-Goe13 OX=2586961 GN=hypothetical PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNLNPIETTKGFNEALIYASENNFPIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGFSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVCNNKGKGTTSTYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYFNGTKKVRLIRNDVQGIGTRVLSHPYATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|G4EVD8|G4EVD8_BACIU Beta_helix domain-containing protein OS=Bacillus subtilis subsp. subtilis str. SC-8 OX=1089443 GN=BSSC8_22190 PE=4 SV=1 +MTLLNKSIRYYVDFDQWGINAFNLNPIETTKGFNEALIYASENNFPIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGFSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVCNNKGKGTTSTYAIKVMDSNDVTFINNKFSNLYGGLYCERSQSIRIKQNDFLLSGKGYGIYWDKDSKVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGSRILSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>tr|A0A7G5CHW7|A0A7G5CHW7_9CAUD Beta_helix domain-containing protein OS=Bacillus phage vB_BsuS-Goe11 OX=2586959 GN=hypothetical PE=4 SV=1 +MILLNKSMRYYVDFDQWGINAFNSNPNETTKGFNEALIYASKNNFPIVEIPKGNFIIDSVNTLNQRNPEVGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGHIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVKISDCIGDNIWIAAHGMMNYPGMAYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGVSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSTYAIKVMDSNDVTFINNKFSNLYGGLYCERSQSIRIKKNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIVFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGSRILSHPFATFNASSTTLIHNTYDSGTPRLALDDTLIDYK +>tr|A0A837Y204|A0A837Y204_BACAT Uncharacterized protein OS=Bacillus atrophaeus OX=1452 GN=B4144_1968 PE=4 SV=1 +MNMIDKSLRVHVDFEQWGINPEGLNPIETTKGFNDALQSAASNFYSVVEVPKGNYLIDAVNT-SKRLPEFGGGIKIPSNIELILHPEAVFRVNPNGYQGYSCFYIGQAENVTIRGGRIIGDRYEHDYSKINTIQKTHEWGYGIHVHGSRNVLIENVSVSDCIGDNIWIAADGMMN-TDVTYTPSRSVTVRKCRLKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGFAEKGIKYDHPYELTIADCRFKKNGRGSITAHTSGKVIIKDNYCDNVISYGFSTDVSIKGNKIINEGEPKEYGIDSIGVSSTETGNRAKITGNTVRGFKIGIMVRGRGVTAKNNTIGNSSNCAIATHTAEEVFIAKNKIENSNCIQIQVRNSSDVKVNGNTGKGTTSSYALKVIDSKDVTLTGNEFSNIYGGLYCERSQAVRVKSNDFLMRGTGYGIYWDKSSEVFLTRNEIYEPRNIAITGTADIYNIRISENQIYNCKALVAIHLLGGSDHMLRGNEIMFNREADQGYGIYLESTKKVRLIRNDVQGIGDRVLSHPYATFKSSNTTLIHNTYNSGTLRLAVDDIVI--- +>tr|A0A150FBD2|A0A150FBD2_9BACI Beta_helix domain-containing protein OS=Bacillus nakamurai OX=1793963 GN=AXI58_10415 PE=4 SV=1 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGFNRALEYASSNSFFRVYVPKGKYLIDAVNT-TKRLPEFGGGIYVPSNIELILHPEAVFHVLPNDYQGYSCFYVGQASNVTIRGGQIIGDRYEHDYSKINSTQETHEWGYGIHIHGSKNVLIENVSISDCIGDNIWIAAYGMMNTSG-TYTPSRNVTVRKCTLKRGRRNNLATNGCEGFLVDDCDIEEAGGDTIGPQLGIDLEGFGEKGIKYDHPYKLTVRNCRFKNNGRGSITAHTSGKVIIDGNYCDNVISYGYSTDVSIKNNKIINEGSVKTYGIDSVGVSTTESGNRVQIDGNTVSGFEVGICARGKGVTISNNTLERIKACPISTHQAEDVLITDNRMENSDCIQVQVRNSNDVRVVNNKGKGTTTAYASKIMDSTRVSLINNEFVNVYGGVYCERSQSVRLKGNDLILSGSGHGIFWDKDSSVSLHRNEIHEPKNVAIKGTPEKYSCQISENQIYFCKSLIAIHLVGGSEHILKDNEIMFNRSSDQGYGVYLENTNKARLVRNDVHGIGGKLLSHPYCTEKAKNTTLIHNTYNSGTLKTAEGDTIV--- +>tr|A0A109WGG2|A0A109WGG2_9BACI Uncharacterized protein OS=Bacillus sp. SDLI1 OX=1774743 GN=AUL54_20265 PE=4 SV=1 +---MRQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKISAIQKTHEWGYGIHVHGSSNVLIENVQVSDCIGDNIWIAAEGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGEVNLEGNYSDNVISYGYSTDVSVKDNKIINKGKSKKYGIDSVGVSSTESGNRVQIIGNTVRGFEIGICVRGKGVHVADNILENITACPIATHEAEDVFISNNHIENSDCIQVQVRNSKDVRVTNNKGGNTTSAYAIKIMDSNRVSFAINEFANVHGGVYCERSQSVRLKLNDLFLSGSGYGIFWDKDSEVYFNGNEIHNPRNVAIKGTSEKYSCQISENQIYFCKSLIAIHLAGGSEHMLNNNEIMFNRSTDQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>tr|A0A8A5UUR4|A0A8A5UUR4_BACAM Right-handed parallel beta-helix repeat-containing protein OS=Bacillus amyloliquefaciens OX=1390 GN=J4048_10725 PE=4 SV=1 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNITVRKCALLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGEVNLEGNYSDNVISYGYSTDVSVKDNKIINKGNSKKYGIDSVGVSSTESGNRVQISGNTVRGFEIGICVRGKGIDVTDNILENISACPIATHEAEDVFISNNHIENSDCIQVQVRNSKDVRVTNNKGGNTTSAYAIKIMDSNRVSFAINEFANVHGGVYCERSQLVRLKLNDLFLGGSGYGIFWDKDSEVYFNGNEIHNPRNVAIKGTSEKYSCQISKNQIYFCKSLIAIHLTGGSEHMLNNNEIMFNRSTDQGYGVYLENTNKVRLVRNDTRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>tr|A0A4R2A540|A0A4R2A540_9BACI Parallel beta helix pectate lyase-like protein OS=Bacillus sp. BK100 OX=2512181 GN=EV570_101171 PE=4 SV=1 +---MQQPLYYSVDALDWGIDDKGSNAIETTEGINRALKYASSKSFYKVHIPKGTYLIDAVNT-SRRLPEFGGGINIPSNIELILHPEAVFKVLPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKVTSIKRTHEWGYGIHIHGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGQVIIEGNYSDNVISYGFSTDVSIKNNKIINDAETKKYGIDSVGVSSTESGNRVQIEGNTVRGFEIGICARGKGVLISNNTLEGIKTCPIATHQAEDVLITDNRIENSDCIQVQVRNSNDVRVVNNKGKGTISAYAVKIMDSTRISLINNEFVNVYGGIYCERSQSVRLKGNDLLLNGSGYGIFWDKDSSVSLQRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKALIAIQLTGGSEHMLKDNEIMFNRSTDQGYGVYLENTDKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>tr|A0A853LAC0|A0A853LAC0_9BACI SPBc2 prophage-derived uncharacterized protein YorA OS=Bacillus siamensis OX=659243 GN=SRCM100169_02074 PE=4 SV=1 +---MQQPLFYFVDAQDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGTYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIKEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIDGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGIDSVGVSSTESGNRVQIDGNTISGFEVGICVRGQGGTVSNNTLEKIKACPIATHQAEDVLITDNRIENSDCIQVQVRNSNDIRVVNNKGKGTTSAYAAKIMDSTRISLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPDKYSCQISENQIYLCKSLIAVQLTGGSEHILKDNEIMFNRSADQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIYNTYDSGTLKTAEGDIVV--- +>tr|S6FH05|S6FH05_9BACI Putative capsid component phage SPbeta OS=Bacillus velezensis UCMB5033 OX=1338518 GN=yorA PE=4 SV=1 +---MQQPLYYSVDALDWGIDDKGSNAIETTEGINRALKYASSKSFYKVHIPKGTYLIDAVNT-SRRLPEFGGGINVPSNIELVLHPEAIFKVLPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKVTSIKRTHEWGYGIHIHGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGQVIIEGNYSDNVISYGFSTDVSIKNNKIINDAEVKKYGIDSVGVSSTESGNRVQIEGNTVRGFEVGICARGKGVSISNNTLEGIKACPIATHQAEDVLITDNRIENSDCIQVQVRNSNDVRVVNNKGKGTISAYAVKIMDSTRISLINNEFVNVYGGIYCERSQSVRLKGNDLLLNGSGYGIFWDKDSSVSLQRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKALIAIQLTGGSEHILKDNEIMFNRSTDQGYGVYLENTDKVRLVRNDARGIGGKLLSHPYCTDKAKNTTLIHNTFDSGTLKTAEGDIVV--- +>tr|A0A6H3B795|A0A6H3B795_9BACI Uncharacterized protein OS=Bacillus velezensis OX=492670 GN=CHR37_05085 PE=4 SV=1 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGVDSVGVSSTESGNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLITDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSTRISLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKSLIAIQLTGGSEHILKDNEIMFNRSVDQGYGVYLENTDKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>tr|A0A7U4HXJ2|A0A7U4HXJ2_BACIU Uncharacterized protein OS=Bacillus subtilis OX=1423 GN=KS08_10530 PE=4 SV=1 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYACSKSFYKVYVPKGIYLIDAVNT-SKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINEKEIKTYGIDSVGVSSTESGNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLFTDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSSRVSLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPDKYSCQISENQIYFCKSLIAIQLTGGSEHILKDNEIMFNRSADQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIYNTYDSGTLKTAEGDIVV--- +>tr|I2C5Q7|I2C5Q7_BACAM Uncharacterized protein OS=Bacillus amyloliquefaciens Y2 OX=1126211 GN=MUS_2014 PE=4 SV=1 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGGTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGVDSVGVSSTESGNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLITDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSTRISLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKSLIAIQLTGGSEHILKDNEIMFNRSVDQGYGVYLENTDKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>tr|A0A4V7TQN6|A0A4V7TQN6_BACAM Uncharacterized protein OS=Bacillus amyloliquefaciens OX=1390 GN=D2M30_2250 PE=4 SV=1 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGVYLIDAVNTA-KRLPEFGGGINVPSNIELILHPEAIFKVQPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKINAIQKTHEWGYGIHIHGSNNILIDGVHVSDCIGDNIWIAADGMMNTSG-VYTPSSSATVQKCTLLRGRRNNMATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGIDSVGVSSTESSNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLISDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSSRVSLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKSLIAIQLTGGSEHMLKDNEIMFNRSADQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIYNTYDSGTLKTAEGDIVV--- +>tr|A0A8B2V7S0|A0A8B2V7S0_BACAM Uncharacterized protein OS=Bacillus amyloliquefaciens OX=1390 GN=C3733_08035 PE=4 SV=1 +---------YFVDALNWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDSVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVLPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKINAIQKTHEWGYGIHVHGSSNVLIDGVHVSDCIGDNIWIAADGMMNTSGK-YTPSRSVTVQKCTLKRGRRNNLATSGCNGLLVDDCDIEEAGGDTIGPQLGIDLEGYGEDGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSDKVIIEGNYSDHVISYGYSTDVSIKNNKIINENQVKTYGIDSVGVSSTESGNRVQINGNTIRGFAIGVCVRGKGIDVTDNIFENITACPITTHEAEDVYISDNHIENSDCIQVQVRNSKDVRVTNNKGGNTTSSYAIKVMDSNRVSCAINEFANVNGGVYCERSQSVRLKGNDFFLNGSGYGIFWDKDSEMYMNRNEIHNPRNFAIKGTSEKYSCQISENQIYFCKSLIAIHLTGGSEHMLNNNEIMFNRSTDQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDVVV--- +>tr|A0A7T7ZAL2|A0A7T7ZAL2_9CAUD Tail spike OS=Bacillus phage 268TH004 OX=2801523 GN=13 PE=4 SV=1 +---------YELEIDRWGISSGGSNPIETTQGFNDAIQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIYIKNVFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLIRGRRNCLATNGCEGLLVDDCAIEDAGGEGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVESNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGIYWGVNSEVEAKGNTIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGVKLKNNSVEVTNDRGLTSSFYTEKSTDSLVVMNDYNKGVIKSHETDTV---- +>tr|A0A5J6T752|A0A5J6T752_9CAUD Tail spike OS=Bacillus phage 019DV004 OX=2601654 GN=11 PE=4 SV=1 +---------YELEIDRWGISSGGSNPIETTQGFNDAVQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTKTHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLVRGRRNCLATNGCEGLLVDDCAIEDAGGEGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVGNNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGTGMGIYWGINSEVEAKGNIIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKTHETDTV---- +>tr|A0A5J6T3Z8|A0A5J6T3Z8_9CAUD Tail spike OS=Bacillus phage 019DV002 OX=2601653 GN=11 PE=4 SV=1 +---------YELEIDRWGISSGGSNPIETTQGFNDAVQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTKTHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLVRGRRNCLATNGCEGLLVDDCAIEDAGGEGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVGNNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGTGMGIYWGINSEVEAKGNIIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKTHETDTV---- +>tr|A0A5J6T9J0|A0A5J6T9J0_9CAUD Tail spike OS=Bacillus phage 276BB001 OX=2601664 GN=12 PE=4 SV=1 +---------YELEIDRWGISSGGSNPIETTQGFNDAIQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TLYTPARDVTVSKCTLIRGRRNCLATNGCEGLLVDDCAIEDAGGEGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGALVESNTLENISAVAVQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGIYWGVNSEVEAKGNTIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKSHETDTV---- +>tr|A0A5J6T6D8|A0A5J6T6D8_9CAUD Tail spike OS=Bacillus phage 280BB001 OX=2601665 GN=12 PE=4 SV=1 +---------YELEIDRWGISSGGSNPIETTQGFNDAIQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TLYTPARDVTVSKCTLIRGRRNCLATNGCEGLLVDDCAIEDAGGEGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGALVESNTLENISAVAVQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGIYWGVNSEVEAKGNTIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKSHETDTV---- +>tr|A0A5P8PIC1|A0A5P8PIC1_9CAUD Tail spike OS=Bacillus phage 056SW001B OX=2601663 GN=11 PE=4 SV=1 +---------YELEIDRWGISSGGSNPIETTQGFNDAVQYAKSEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIHIKNAFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLVRGRRNCLATNGCEGLLVDDCAIEDAGGEGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKIIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVESNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGVYWGVNSEVEAKGNTIEVGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKSHETDTV---- +>tr|A0A5J6T5S7|A0A5J6T5S7_9CAUD Tail spike OS=Bacillus phage 031MP003 OX=2601657 GN=8 PE=4 SV=1 +---------YELECDRWGIFPDGTNPVETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYTGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNTYN---------------- +>tr|A0A5J6T527|A0A5J6T527_9CAUD Tail spike OS=Bacillus phage 031MP004 OX=2601658 GN=8 PE=4 SV=1 +---------YELECDRWGIFPDGTNPVETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYTGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNTYN---------------- +>tr|A0A5J6T6E0|A0A5J6T6E0_9CAUD Tail spike OS=Bacillus phage 022DV001 OX=2601655 GN=8 PE=4 SV=1 +---------YELECDRWGIFPDGTNPVETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYAGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTIVDGNKYN---------------- +>tr|A0A5J6T8J3|A0A5J6T8J3_9CAUD Tail spike OS=Bacillus phage 055SW001 OX=2601662 GN=8 PE=4 SV=1 +---------YELECDRWGISPDGTNPTETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYAGSTYITARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNKYN---------------- +>tr|A0A7U3TW25|A0A7U3TW25_9CAUD Minor tail protein OS=Bacillus phage 000TH009 OX=2801831 GN=222 PE=4 SV=1 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSTNVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>tr|A0A5J6T602|A0A5J6T602_9CAUD Tail spike OS=Bacillus phage 031MP002 OX=2601656 GN=7 PE=4 SV=1 +---------YELECDRWGISPDGTNPPETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYHEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYAGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTVEEAGG--VGPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGVVKPYGIDSLGVSSTETGNRASIKGNTIRGFNIGINAKGKGILVSKNTIEDVESVGIQVYQATSALVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLHTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNKYN---------------- +>tr|A0A7T8C426|A0A7T8C426_9CAUD Minor tail protein OS=Bacillus phage 000TH008 OX=2801830 GN=222 PE=4 SV=1 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSINVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>tr|A0A076G7N8|A0A076G7N8_9CAUD Tailspike protein OS=Bacillus phage Bobb OX=1527469 PE=4 SV=1 +---------YFIDFEKHGIRSNGTAARETTDGFISALNDAVASGYKTVYVPKGNYLIDGVG--EDKMPEYGGGIQFPSNIEVIFHKEAVFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMVSPFRRTHEWGYGVHIRGCRNILIEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTEKGRRNNIATDGCLGLLIDDCDIIKAGGDTIGPQLGIDLEGYAEDGIKYGHPYEINITNCRFRKNGRGALNINVSAKVHATNNFSDDVFSYGYSSDVSICNNKIINDSGTKKYGIDSIRKSSTETGNRAIISGNHVIGFEIGICARGLGVKISNNYLKDISSIGIYPYLAEEVSVSDN-IIDSNCLHVWVRESKDVKISDNKTKGAANYFAYRVEASSDV-IISDSKSQSKGGIQVLRSRKVVLKDNDLALIGTDYGIHWDKQSEVEVLHNTVRDAAMIAIAGNSELYPSIIKGNNIKDCTYLVGLYVNGGSDHILWDNDVSFTGSANGGYGVQLVGTENAWLMNNKVRVSNGRTLSSSYESRGSQNTMYINNALQTG-------------- +>tr|A0A7T7ZC39|A0A7T7ZC39_9CAUD Minor tail protein OS=Bacillus phage 015DV002 OX=2801832 GN=212 PE=4 SV=1 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KSGVRVSRSTNVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>tr|R4JDQ9|R4JDQ9_9CAUD SPBc2 prophage-derived protein YorA OS=Bacillus phage SIOphi OX=1285382 GN=SIOphi_00245 PE=4 SV=1 +---------YFIDFDQFGIKDDGTDATSTTSGFVAAFKRAVELGHSAVYVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGHIVGDRHEHNYRQVNENRRTHEWGFGIQVRGSKNVTIENVTIEDCTGDNIWVTSKGMMNWPG-VYIPSESVTIRKCRTLRGRRNNIAAGASVGLLIDDCDIIEAGGDEIGPQLGIDLEGYADNSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGHKKFGIDSIRKSTSETANRAVVTGNVIRGFQTGIAARGKTVTVSNNILEDISSIGIYPYLCDQAVVSSN-IIDSDCLHIWVRESKDIKVSDNKGTGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSTNVRIVDNDIDMIGPDYGIYFDKQSEVHLRDNLVKNAAFTAIRGYADQYSSYIKGNIIQDCKYMIAIHIDGGSKHMIKDNDITFRRGSNAGYGVYLIGANDSRLHNNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>tr|A0A7U3TFK2|A0A7U3TFK2_9CAUD Minor tail protein OS=Bacillus phage 015DV004 OX=2801833 GN=228 PE=4 SV=1 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQSNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSTNVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>tr|A0A5J6TBR2|A0A5J6TBR2_9CAUD Tail spike OS=Bacillus phage 035JT001 OX=2601659 GN=8 PE=4 SV=1 +---------YELECDRWGIFPDGTNPESTTRGFNDALTFAAAEGYKEIYIPKGVYKIDCVSRFGSK-PEYGGGIRNPSNLDVDMHTEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEDKTKTHEWGYGVHIRGSKNINIENMFISDCTGDNIWVAANGMMNYEGSTYIPSKDVTVRKCTLMRGRRNGLATNGCEGLLVDDCTIEESGGGGTRPEYGIDLEGFGEGGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRASIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSALVIGNRI-DADCTHIQMLYAEKTTVIGNESEGNTQNFAYKVTYSDRTVFSGNTLYDGDGGLDVGQSTLTKFKGNTLFLTGENFGVHWGSSSDLEVSGNTFHMGSGVAIFGYADLHTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKIARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSAGTLVDGNKYN---------------- +>tr|A0A2I6UI00|A0A2I6UI00_9CAUD Uncharacterized protein OS=Bacillus phage BSP10 OX=2069312 GN=BSP10_173 PE=4 SV=1 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALKDAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAKNYYGIKVEDSSDV-VVNDNKQVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKTSQVKLVKNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>tr|A0A890URD5|A0A890URD5_9CAUD Tailspike OS=Bacillus phage BSTP3 OX=2801528 GN=BSTP3_034 PE=4 SV=1 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALKDAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAKNYYGIKVEDSSDV-VVNDNKQVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKTSQVKLVKNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>tr|U5PXV9|U5PXV9_9CAUD Tailspike OS=Bacillus phage Grass OX=1406785 GN=Grass_33 PE=4 SV=1 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALKEAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFMVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTVPDNRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPAKGMMNWEGSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFSYGFSTDSTISNNTITNETGDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVQVGNNKGKDAENYYGIKVEDSSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKTSQVKLIKNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>tr|S6BUP9|S6BUP9_9CAUD Beta_helix domain-containing protein OS=Bacillus phage phiNIT1 OX=207656 GN=orf587 PE=4 SV=1 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALREAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAENYYGIKVEDSSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKISQVKLVKNWISCAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>tr|A0A384XD57|A0A384XD57_9CAUD Uncharacterized protein OS=Bacillus phage BSP9 OX=2041339 GN=BSP9_162 PE=4 SV=1 +----NSNYMYFVDFEKFGIRSDGTEARATTEGWIAALKEAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAENYYGIKVEASSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKISQVKLVKNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>tr|L0L8C8|L0L8C8_9CAUD Putative Pectin lyase-like protein OS=Bacillus phage phiAGATE OX=1204533 PE=4 SV=1 +---------YFIDFEKHGIKSDGTAARETTDGFTYALNDAVNKGYKTVYVPKGDYLINGVG--EDRMPEYGGGIQFPSNIEVIFHKKAIFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMVSKFRKTHEWGYGVHIRGSRNILVEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTERGRRNNIATDGCLGLLIDDCDIIEAGGDTIGPQLGIDLEGFAEDGIKYGHPYEINVVNNRIRNNGRGSLNINVSAKVHASNNFSDDVFSYGYSSDVSICNNKIINDSGKRKYGIDSIRKSSTETGNRAIITGNHIIGFEIGICARGLGVKIANNYLKDISSIGIYPYLAEEVSVSDN-IVDSNCLHVWVRESKDVKISDNKTKGADNDFAYRVESSSDV-IISDSKSQANGGIQVIRSRKVTLKDNDLTLTGADYGIYWDKQSEVEVLHNTVRDAAMIAIAGNSNLYPSIVKGNNIKDCTYLVGLYMNGGRDHVIWDNDVSFKGSSNGGYGVQLIATTNAWLMDNKVRVSNGRTLSSAYESQSSYKTLYVNNAMQIG-------------- +>tr|A0A1Z1DEW7|A0A1Z1DEW7_9CAUD Tailspike protein OS=Bacillus phage vB_BsuM-Goe3 OX=1933063 GN=Goe3_c03000 PE=4 SV=1 +----NSKYVYDIDFGKFGIKPDCTEAAATTEGFITALEDAVDQGYPKVYIPEGFYLIDAVGT-SGKLPEFGGGLRFPSNIEVIFHEKAVFIVDPNDATGYACFNLENVENVTLRGGVVIGDRYKHTYEGVPDNRKTHEWGYGLQIRGCRNIKVENMTLMDATGDNIWVPAKGMMNWEGSTYIPSEGITIDKCYTLRGRRNNLATNGCLGLNINDCDFVEAGGDTIGPAYGIDLEGFAENSIKYDHPYEINVTNCRFKRNGKGALTINVAGKAHATNNFSDDIISYGFSTDATISNNTITNESEEKEYGIDSIRKSSSETGNRAIITGNHIRGFKSGICARGVGVVASNNYLENISSVGIYAYLAKNVLMADNVI-NSDCLHVWVRESEDVKISNSKGKGAINNWGIKVEASSNVS-LNDNEHDSKGGVQVARSTDVRAWDNRFTLVGNEYGAYWDKTSEVVFEGNHIFNPSTIAIAGYGDTYASSIVRNTIHDCKYLTAIYLSGGSQHFVKGNDIRFRRGANGGYGIKLTGTSGVKVIGNDVRTMDGCSLNASYDSSGSVNTQYANNTYHTG--RMLLHD------ +>tr|A0A516KNA2|A0A516KNA2_9CAUD Putative pectin lyase OS=Bacillus phage vB_BveM-Goe7 OX=2593639 GN=Goe7_c00300 PE=4 SV=1 +----NSKYVYDIDFGKFGIKPDCTEAAATTEGFITALEDAVDQGYPKVYIPEGFYLIDAVGT-SGKLPEFGGGLRFPSNIEVIFHEKAVFIVDPNDATGYACFNLENVENVTLRGGVVIGDRYKHTYEGVPDNRKTHEWGYGLQIRGCRNIKVENMTLMDATGDNIWVPAKGMMNWEGSTYIPSEGITIDKCYTLRGRRNNLATNGCLGLNINDCDFVEAGGDTIGPAYGIDLEGFAENSIKYDHPYEINVTNCRFKRNGKGALTINVAGKAHATNNFSDDIISYGFSTDATISNNTITNESEEKEYGIDSIRKSSSETGNRAIITGNHIRGFKSGICARGVGVVASNNYLENISSVGIYAYLAKNVLMADNVI-NSDCLHVWVRESEDVKISNSKGKGAINNWGIKVEASSNVS-LNDNEHDSKGGVQVARSTDVRAWDNRFTLVGNEYGAYWDKTSEVVFEGNHIFNPSTIAIAGYGDTYASSIVRNTIHDCKYLTAIYLSGGSQHFVKGNDIRFRRGANGGYGIKLTGTSGVKVIGNDVRTMDGCSLNASYDSSGSVNTQYANNTYHTG--RMLLHD------ +>tr|A0A345MJP4|A0A345MJP4_9CAUD NosD domain-containing protein OS=Bacillus phage BSP38 OX=2283013 GN=BSP38_034 PE=4 SV=1 +----NSKYVYFVDFEKFGIKSDGTDAAATTSGWIAALKEAVDLGYPKVYVPAGLYLIDAVGKTDSL-PEYGGGLRFPSNIEVIFHEMALFKVEPNSSTGYACFNLENVENVTLRGGYVIGDRYEHDYTLVPNNRRTHEWGHCLHIRGCRNIYVENMTLMNATGDNIWVPAKGMMNWEGSTYIPSEGITIHKCTTIRGRRNNFATNGCIGLNIDDCDFIEAGGDVIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFTDDVISYGFSTDGTISNNTITNETGHKPFGIDSIRKSSSETGNRTIITGNQIRGFASGICARGVGVIVSNNYLSDISSVGIYPYLSEEVLVSNN-IINSDCLHVWVRESKDVKVNNTKGKGAANNYGIKVEASHDV-VLNDNEHEAKGGIQIARSTNVRVKDNDLNLIGNGNGISWDKTSQVILDGNWINGAVAIAISGYGEVYPTNIMRNTIEDCKYLIGIYLNGGSQHVIKDNDIMFRRGSNGGYGVQLKDTTDVRVYRNDVRTMDGGTLYSSFDSSGALSTKYVGNTMDAG-------------- +>tr|A0A5B9NKS7|A0A5B9NKS7_9CAUD Putative right-handed parallel beta-helix repeat-containing protein OS=Bacillus phage vB_BspS_SplendidRed OX=2591379 GN=SPLENDIDRED_11 PE=4 SV=1 +---MNKELYYHIDLERFGIRDDLTEANATTQGFNAALKDAKEQGYHYFVFPEGKYLINTISNFGGL-PEYGGGIRIPSNIHIIMD-NPYFEAEANDRTGYSIFYLEAVENVEISGGTICGDRYNHDYDLKDDRTKTHEWGFGIHIRGCRRVAIKGLTVKNCTGDNIWIPAKGMMNFPG-DYTPSRDILIQDCDLIHGRRNNLATNGCYGLTVERCDIKEAGGDTIGPQLGIDLEGYGDKGIKYDHPYEITIKNNWIKNNGRGALTAHTSGKVLIEGNFTDAVISYAYSTDVKIKDNFIINEGQEKPYGIDSIGVSSSETANRVNISGNTVSGFKTGICARGSKVKVRNNEVEGATAAAIQIFQCEKAEVSDN-TTDGNAVGLLIQQSKTVEASDNTFRGAENKYGIKIQDSSDIILKDNRIRG-FGGIFCESVQNVVVRDHDINLTGSGYGVYFDAKSCVFLDGVTIYNPENTSVYGLADEYAAIIKGVEVIGCKSIIGIYLHGGINHDIKGNTVRFKRGKDQGYGIYLDGTKGAVLARNDVVSTDGFKLSAAYKTDESEQTTLIEN------------------- +>tr|A0A386K842|A0A386K842_9CAUD Uncharacterized protein OS=Bacillus phage Ray17 OX=2315627 GN=Ray17_11 PE=4 SV=1 +---MSKGLYYHIDLERFGIKDDLTEANATTQGFNAALKDAKDQGYHYFVFPEGKYLINAVSNFGGL-PEYGGGIRIPSNINIIMD-NPYFEAEANDQTGYSIFYLEAVENVKISGGTICGDRYNHDYDLKDDRTKTHEWGFGIHIRGCRRVEIKGLTVKNCTGDNIWIPAKGMMNWP-TDYTPSRDILIQDCDLIQGRRNNLATNGCYGLTVERCDIKEAGGDTIGPQLGIDLEGYGDKGIKYDHPYEITIKNNWIKNNGRGALTAHTSGKVLIEGNFTDAVISYAYSTDVKIKDNFIINEGQEKPYGIDSIGVSSSETANRVNISGNTVSGFKTGICARGSKVKIHGNEVEGATAAAIQIYQCEKVEVSDN-TTDGNAVGLLIQQSKTVEASDNTFRGSENKYGIKIQDSSDIILKDNRIRG-FGGIFCESAQKVIVRDHDIDLTGSGYGVYFDAKSSVFLDGVTIYNPENTPVYGLADEFAAIMKDVEVIGCKSIIGIYMHGGFGHDIKGNTVRFRRGKDQGYGIFLDGTKSAVLTRNDVLSTDGFKLSAAYKTDGSERTTLIEN------------------- +>tr|D0VXF4|D0VXF4_9CAUD Beta_helix domain-containing protein OS=Bacillus phage phiNIT1 OX=207656 PE=4 SV=1 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALREAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALTSTLQGKFMLLIT-SPMMAQLWFSTDSTISNNTITNETGDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAENYYGIKVEDSSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKISQVKLVKNWISCAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>tr|A0A0A0PLR7|A0A0A0PLR7_9CAUD Putative pectin lyase-like protein OS=Bacillus phage Bp8p-T OX=1445811 GN=Bp8pT_172 PE=4 SV=1 +-------------------------------------------------------------------PEYGGGIQFPSNIEVIFHKEAVFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMVSKFRKTHEWGYGVHIRGCRNILVEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTERGRRNNIATDGCLGLLIDDCDIVEAGGDTIGPQLGIDLEGFAEDGIKYGHPYEINITNNRFRENGRGSLNINVSAKVHATNNFSDDVFSYGYSSDVSICNNKIINESGKRKYGIDSIRKSSTETGNRAIITGNHIIGFEIGICARGLGVKIANNYLKDISSIGIYPYLAEEVSVSDN-IIDSNCLHVWVRESKDVKISDNKTKGAANHFAYRVEASSDV-LISDSKSQSKGGIQVIRSRKVILKDNDLSLTGADYGIQWDKQSEVEVLNNTVRDAAMIAIAGNSELYPSVIKGNNIKDCTYLVGLYVNGGSNHILWDNDISFTGTTNGGYGVQLVGTENVWLMNNKVRTSNGRLLSSAYESRNSKKTMYINNALQAG-------------- +>tr|A0A0A0PUI4|A0A0A0PUI4_9CAUD Putative pectin lyase-like protein OS=Bacillus phage Bp8p-C OX=1445810 GN=Bp8pC_172 PE=4 SV=1 +-------------------------------------------------------------------PEYGGGIQFPSNIEVIFHKEAVFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMVSKFRKTHEWGYGVHIRGCRNILVEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTERGRRNNIATDGCLGLLIDDCDIVEAGGDTIGPQLGIDLEGFAEDGIKYGHPYEINITNNRFRENGRGSLNINVSAKVHATNNFSDDVFSYGYSSDVSICNNKIINESGKRKYGIDSIRKSSTETGNRAIITGNHIIGFEIGICARGLGVKIANNYLKDISSIGIYPYLAEEVSVSDN-IIDSNCLHVWVRESKDVKISDNKTKGAANHFAYRVEASSDV-LISDSKSQSKGGIQVIRSRKVILKDNDLSLTGADYGIQWDKQSEVEVLNNTVRDAAMIAIAGNSELYPSVIKGNNIKDCTYLVGLYVNGGSNHILWDNDISFTGTTNGGYGVQLVGTENVWLMNNKVRTSNGRLLSSAYESRNSKKTMYINNALQAG-------------- +>tr|A0A5P8PIG3|A0A5P8PIG3_9CAUD Uncharacterized protein OS=Bacillus phage 049ML003 OX=2601661 GN=42 PE=4 SV=1 +---------YPVNLEEWGINKDFQEPEATTEAFNKAFTYAKNMGYFEVWVPPGNYLIDGVNESNIYATENGGGIHLHSNTHYKLNPESVFKINANNAQGYSVFYIGLAYNVTLEGGQLIGDRHEHDYSTVTQNRNTHEFGFGVNVHGSERVNIVNVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDVIGPQLGIDFEGYAENGIKYAHPYNLQLKNSRFRDNGRGCFTAHAVGKAIISENFFDDRVSYGFGTDISIVDNHIINDGEVRDLAIDSIQPPSYDNANRVKISGNKIKGFKKGMTIRGKEIDVTDNDLNNITETGIHVYLAEEITVNENRV-NSDCVPLNIQISKKVNVSDNTFKGGAEKYGVIVSEVEDISFKDNHI-EAGGGIDAGSAKNVRISKNEIFVKGKLNALRNNAGSTVKVNGLNIYDPAAYPMAGALDIKNV-----SIYGCKAFIAINIKNGRRHKIKNNDIVFERETNGGYGVYLSGTERTKLMDNDVSTSNDFAIGAPFHTEGSMYSTIMHNYYDSG-------------- +>tr|M4ZRV1|M4ZRV1_9CAUD Beta_helix domain-containing protein OS=Bacillus phage PM1 OX=547228 PE=4 SV=1 +---------YPLNLEEWGINKEFQEPEETTAAFNKAFEYAKSMGYFKILVPPGNFLIDGVNESNIYATENGGGIHLHSNTHYLLHPESVFKINANDAQGYSVFYIGLAYNVTLEGGQLIGDRHEHDYSTSTQNRNTHEFGFGVNVHGSERVNIINVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDTIGPQLGIDFEGYAENGVKYAHPYNLQVKDSRFKNNGRGCFTAHAVGKAIISKNFFDDRVSYGFGTDISIVDNHIINDGEVRPLAIDSIQPPSYDNANRVKISGNTIKGFKKGMTIRGKEVDVIDNKLNNITDTGIHVYLAEEITVNENRV-NSDCVPLNIQISEKVNVSDNTFKGGSEKYGVVISEVEDISFKDNHI-EAGGGIDAGVAKNVRISKNEIFVKGKLNALRNNAGSTVKVNGLNIYDPAPMELDGSAGALDIR--NVSIYGCKAFIAINIKNGKSHKIKNNDIIFNRGSNGGYGIHLSGTEKAKLTNNYVSTSDGFAIGSPYHTENSTYSTVMNNYYDSG-------------- +>tr|A0A5P8PHR1|A0A5P8PHR1_9CAUD Beta_helix domain-containing protein OS=Bacillus phage 000TH010 OX=2601652 GN=49 PE=4 SV=1 +---------YPVNLEEWGINKDFQEPEATTEAFNRAFTYAKNMGYFEVWVPPGNYLIDGVNESNVYATENGGGIHLHSNTHYKLNPESVFKINANDAQGYSVFYVGLAYNVTLEGGQLIGDRYEHNYSTVAPNRSTHEFGFGVNVHGSERVNIINVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDIIGPQLGIDFEGYAENGIKYAHPYNLQLKNSRFKDNGRGCFTAHATGKAIISENFFDDRVSYGFGTDISIVDNHIINDGEVRPLAIDSIQPPSYDNANRVKVAGNKIKGFKKGMTIRGKEVDVTDNDLNDVTETGIHVYLAEEITVNENRV-NSDCVPLNIQISKKVNVSDNTFKGGAEKYGVVISEVEDISFKDNHI-EAGGGIDAGSAKNVRISKNEIFVKGKLNALRNNPGSTMKVNGLNIYDPAAYPMELDGSAGSLDIKNVSIYGCKAFIAINIKNGRRHKIKNNDIIFERETNGGYGIYLSGTERTKLMDNDVSTSNDFAIGSPFHTENAMYSTIMHNYYDSG-------------- +>tr|A0A5P8PI75|A0A5P8PI75_9CAUD Beta_helix domain-containing protein OS=Bacillus phage 049ML001 OX=2601660 GN=42 PE=4 SV=1 +---------YSVNLEEWGINKDFQEPEATTEAFNKAFTYAKNMGYFEVWVPPGNYLIDGVNESNIYATENGGGIHLHSNTHYKLNPESVFKINANNAQGYSVFYIGLAYNVTLEGGQLIGDRHEHDYSTVTQNRNTHEFGFGVNVHGSERVNIVNVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDVIGPQLGIDFEGYAENGIKYAHPYNLQLKNSRFRDNGRGCFTAHAVGKAIISENFFDDRVSYGFGTDISIVDNHIINDGEIRALAIDSIQPPSYDNANRVKISGNKIKGFKKGMTIRGKEIDVTDNDLNNITETGIHVYLAEEITVNENRV-NSDCVPLNIQISKKVNVSDNTFKGGAEKYGVIVSEVEDISFKDNHI-EAGGGIDAGSAKNVRISKNEIFVKGKLNALRNNPGSTVKVNGLNIYDPAAYPMAGALDIKNV-----SIYGCKAFIAMNIKNGRRHKIKNNDIVFERETNGGYGVYLSGTERTKLTDNDVSTSNDFAIGAPFHTEGSMYSTIMYNYYDSG-------------- diff --git a/test/unit/data/uniprot.mode5.txt b/test/unit/data/uniprot.mode5.txt new file mode 100644 index 00000000..8e8d2208 --- /dev/null +++ b/test/unit/data/uniprot.mode5.txt @@ -0,0 +1,120 @@ +>O31912 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A6H0H3G5 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A162RH73 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A6M4JNF4 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>O64135 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>O31912 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A857HHC0 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFPIVEVPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGGSKEYGIDSVGVSSTETGNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSAYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVKGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGARVLSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A410R1H8 +MTLLNKSIRYYVDFDQWGINAFNSNPIETTKGFNEALIYASENNFSIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNTELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGVSSTETSNRIQITDNNIQGFKIGMMIRGKGVSVDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSTYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGTRVLSHPYATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A7G5CIE1 +MTLLNKSIRYYVDFDQWGINAFNLNPIETTKGFNEALIYASENNFPIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGFSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVCNNKGKGTTSTYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYFNGTKKVRLIRNDVQGIGTRVLSHPYATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A7G5CIX1 +MTLLNKSIRYYVDFDQWGINAFNLNPIETTKGFNEALIYASENNFPIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGFSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVCNNKGKGTTSTYAIKVMDSNDVKFLNNTFSNLYGGLYCERSQAVRIKLNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYFNGTKKVRLIRNDVQGIGTRVLSHPYATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>G4EVD8 +MTLLNKSIRYYVDFDQWGINAFNLNPIETTKGFNEALIYASENNFPIVEIPKGNFIIDSVNTLNQRNPEIGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGRIIGDRYQHDYSLIDTNRKTHEWGFGIHVHGSKNVLIENVQISDCIGDNIWIAAHGMMNYPGMVYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGFSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVCNNKGKGTTSTYAIKVMDSNDVTFINNKFSNLYGGLYCERSQSIRIKQNDFLLSGKGYGIYWDKDSKVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIMFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGSRILSHPFATFNASSTTLIHNTYDSGTPRLALDDTVIDYK +>A0A7G5CHW7 +MILLNKSMRYYVDFDQWGINAFNSNPNETTKGFNEALIYASKNNFPIVEIPKGNFIIDSVNTLNQRNPEVGGGIKIPSNMELLLDPEAVFQVNPNGYQGYSCFYIGLAENVIIRGGHIIGDRYQHDYSLIDTDRKTHEWGFGIHVHGSKNVLIENVKISDCIGDNIWIAAHGMMNYPGMAYTPSKSVTVRKCELKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGYGENGRKYDHPYELTISDCRFRKNGRGSVTAHTSGKVSIKDNYCDNVISYGYSTDVSIKGNKIINEGESKEYGIDSVGVSSTETSNRIQITDNNIQGFKIGMMIRGKGVSIDNNTVKNASNCAIATHMAEDVSISNNRIQDSDCIQIQVRNSSDIKVSNNKGKGTTSTYAIKVMDSNDVTFINNKFSNLYGGLYCERSQSIRIKKNDFLLSGKGYGIYWDKDSEVFLTRNEIFEPRNVAIMGAADMYNIRISDNQIYNCKAIIAIHLIGGSEHMVRGNEIVFNRDSDQGYGIYLNGTKKVRLIRNDVQGIGSRILSHPFATFNASSTTLIHNTYDSGTPRLALDDTLIDYK +>A0A837Y204 +MNMIDKSLRVHVDFEQWGINPEGLNPIETTKGFNDALQSAASNFYSVVEVPKGNYLIDAVNT-SKRLPEFGGGIKIPSNIELILHPEAVFRVNPNGYQGYSCFYIGQAENVTIRGGRIIGDRYEHDYSKINTIQKTHEWGYGIHVHGSRNVLIENVSVSDCIGDNIWIAADGMMN-TDVTYTPSRSVTVRKCRLKRGRRNNLATNGCEGLLVEDCDIEEAGGDTIGPQLGIDLEGFAEKGIKYDHPYELTIADCRFKKNGRGSITAHTSGKVIIKDNYCDNVISYGFSTDVSIKGNKIINEGEPKEYGIDSIGVSSTETGNRAKITGNTVRGFKIGIMVRGRGVTAKNNTIGNSSNCAIATHTAEEVFIAKNKIENSNCIQIQVRNSSDVKVNGNTGKGTTSSYALKVIDSKDVTLTGNEFSNIYGGLYCERSQAVRVKSNDFLMRGTGYGIYWDKSSEVFLTRNEIYEPRNIAITGTADIYNIRISENQIYNCKALVAIHLLGGSDHMLRGNEIMFNREADQGYGIYLESTKKVRLIRNDVQGIGDRVLSHPYATFKSSNTTLIHNTYNSGTLRLAVDDIVI--- +>A0A150FBD2 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGFNRALEYASSNSFFRVYVPKGKYLIDAVNT-TKRLPEFGGGIYVPSNIELILHPEAVFHVLPNDYQGYSCFYVGQASNVTIRGGQIIGDRYEHDYSKINSTQETHEWGYGIHIHGSKNVLIENVSISDCIGDNIWIAAYGMMNTSG-TYTPSRNVTVRKCTLKRGRRNNLATNGCEGFLVDDCDIEEAGGDTIGPQLGIDLEGFGEKGIKYDHPYKLTVRNCRFKNNGRGSITAHTSGKVIIDGNYCDNVISYGYSTDVSIKNNKIINEGSVKTYGIDSVGVSTTESGNRVQIDGNTVSGFEVGICARGKGVTISNNTLERIKACPISTHQAEDVLITDNRMENSDCIQVQVRNSNDVRVVNNKGKGTTTAYASKIMDSTRVSLINNEFVNVYGGVYCERSQSVRLKGNDLILSGSGHGIFWDKDSSVSLHRNEIHEPKNVAIKGTPEKYSCQISENQIYFCKSLIAIHLVGGSEHILKDNEIMFNRSSDQGYGVYLENTNKARLVRNDVHGIGGKLLSHPYCTEKAKNTTLIHNTYNSGTLKTAEGDTIV--- +>A0A109WGG2 +---MRQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKISAIQKTHEWGYGIHVHGSSNVLIENVQVSDCIGDNIWIAAEGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGEVNLEGNYSDNVISYGYSTDVSVKDNKIINKGKSKKYGIDSVGVSSTESGNRVQIIGNTVRGFEIGICVRGKGVHVADNILENITACPIATHEAEDVFISNNHIENSDCIQVQVRNSKDVRVTNNKGGNTTSAYAIKIMDSNRVSFAINEFANVHGGVYCERSQSVRLKLNDLFLSGSGYGIFWDKDSEVYFNGNEIHNPRNVAIKGTSEKYSCQISENQIYFCKSLIAIHLAGGSEHMLNNNEIMFNRSTDQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>A0A8A5UUR4 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNITVRKCALLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGEVNLEGNYSDNVISYGYSTDVSVKDNKIINKGNSKKYGIDSVGVSSTESGNRVQISGNTVRGFEIGICVRGKGIDVTDNILENISACPIATHEAEDVFISNNHIENSDCIQVQVRNSKDVRVTNNKGGNTTSAYAIKIMDSNRVSFAINEFANVHGGVYCERSQLVRLKLNDLFLGGSGYGIFWDKDSEVYFNGNEIHNPRNVAIKGTSEKYSCQISKNQIYFCKSLIAIHLTGGSEHMLNNNEIMFNRSTDQGYGVYLENTNKVRLVRNDTRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>A0A4R2A540 +---MQQPLYYSVDALDWGIDDKGSNAIETTEGINRALKYASSKSFYKVHIPKGTYLIDAVNT-SRRLPEFGGGINIPSNIELILHPEAVFKVLPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKVTSIKRTHEWGYGIHIHGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGQVIIEGNYSDNVISYGFSTDVSIKNNKIINDAETKKYGIDSVGVSSTESGNRVQIEGNTVRGFEIGICARGKGVLISNNTLEGIKTCPIATHQAEDVLITDNRIENSDCIQVQVRNSNDVRVVNNKGKGTISAYAVKIMDSTRISLINNEFVNVYGGIYCERSQSVRLKGNDLLLNGSGYGIFWDKDSSVSLQRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKALIAIQLTGGSEHMLKDNEIMFNRSTDQGYGVYLENTDKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>A0A853LAC0 +---MQQPLFYFVDAQDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGTYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIKEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIDGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGIDSVGVSSTESGNRVQIDGNTISGFEVGICVRGQGGTVSNNTLEKIKACPIATHQAEDVLITDNRIENSDCIQVQVRNSNDIRVVNNKGKGTTSAYAAKIMDSTRISLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPDKYSCQISENQIYLCKSLIAVQLTGGSEHILKDNEIMFNRSADQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIYNTYDSGTLKTAEGDIVV--- +>S6FH05 +---MQQPLYYSVDALDWGIDDKGSNAIETTEGINRALKYASSKSFYKVHIPKGTYLIDAVNT-SRRLPEFGGGINVPSNIELVLHPEAIFKVLPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKVTSIKRTHEWGYGIHIHGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGQVIIEGNYSDNVISYGFSTDVSIKNNKIINDAEVKKYGIDSVGVSSTESGNRVQIEGNTVRGFEVGICARGKGVSISNNTLEGIKACPIATHQAEDVLITDNRIENSDCIQVQVRNSNDVRVVNNKGKGTISAYAVKIMDSTRISLINNEFVNVYGGIYCERSQSVRLKGNDLLLNGSGYGIFWDKDSSVSLQRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKALIAIQLTGGSEHILKDNEIMFNRSTDQGYGVYLENTDKVRLVRNDARGIGGKLLSHPYCTDKAKNTTLIHNTFDSGTLKTAEGDIVV--- +>A0A6H3B795 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGVDSVGVSSTESGNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLITDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSTRISLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKSLIAIQLTGGSEHILKDNEIMFNRSVDQGYGVYLENTDKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>A0A7U4HXJ2 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYACSKSFYKVYVPKGIYLIDAVNT-SKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINEKEIKTYGIDSVGVSSTESGNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLFTDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSSRVSLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPDKYSCQISENQIYFCKSLIAIQLTGGSEHILKDNEIMFNRSADQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIYNTYDSGTLKTAEGDIVV--- +>I2C5Q7 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDAVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVQPNDYQGYSCFYIGQASNVTIRGGQIIGDRHEHDYSKITSIKKTHEWGFGIHVNGSSNVLIENVQVSDCIGDNIWIAADGMMNTSG-TYTPSKNVTVRKCTLLRGRRNNLATNGCEGLLVDDCDIEEAGGGTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGVDSVGVSSTESGNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLITDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSTRISLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKSLIAIQLTGGSEHILKDNEIMFNRSVDQGYGVYLENTDKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDIVV--- +>A0A4V7TQN6 +---MQQPLYYFVDALDWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGVYLIDAVNTA-KRLPEFGGGINVPSNIELILHPEAIFKVQPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKINAIQKTHEWGYGIHIHGSNNILIDGVHVSDCIGDNIWIAADGMMNTSG-VYTPSSSATVQKCTLLRGRRNNMATNGCEGLLVDDCDIEEAGGDTIGPQLGIDLEGFGENGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSGKVIIEGNYSDHVISYGYSTDVSIKNNKIINENEIKTYGIDSVGVSSTESSNRVQIDGNTISGFEVGICVRGKGGTVSNNTFEKIKACPIATHQAEDFLISDNRIENSDCVQVQVRNSNDIKVVNTKGKGTSSSYAAKIMDSSRVSLVNNEFANVYGGIYCERSQSVRLKGNDLLLSGSGYGIFWDKDSSVSLHRNEIHEPRNVAIKGTPEKYSCQISENQIYFCKSLIAIQLTGGSEHMLKDNEIMFNRSADQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIYNTYDSGTLKTAEGDIVV--- +>A0A8B2V7S0 +---------YFVDALNWGIDDKGSNAIETTEGLNRALEYASSKSFYKVHIPKGIYLIDSVNT-TKRLPEFGGGINVPSNIELILHPEAIFKVLPNDSQGYSCFYIGQASNVTIRGGQIIGDRYEHDYSKINAIQKTHEWGYGIHVHGSSNVLIDGVHVSDCIGDNIWIAADGMMNTSGK-YTPSRSVTVQKCTLKRGRRNNLATSGCNGLLVDDCDIEEAGGDTIGPQLGIDLEGYGEDGIKYDHPYKLTVRNCRFKNNGRGSVTAHTSDKVIIEGNYSDHVISYGYSTDVSIKNNKIINENQVKTYGIDSVGVSSTESGNRVQINGNTIRGFAIGVCVRGKGIDVTDNIFENITACPITTHEAEDVYISDNHIENSDCIQVQVRNSKDVRVTNNKGGNTTSSYAIKVMDSNRVSCAINEFANVNGGVYCERSQSVRLKGNDFFLNGSGYGIFWDKDSEMYMNRNEIHNPRNFAIKGTSEKYSCQISENQIYFCKSLIAIHLTGGSEHMLNNNEIMFNRSTDQGYGVYLENTNKVRLVRNDVRGIGGKLLSHPYCTDKAKNTTLIHNTYDSGTLKTAEGDVVV--- +>A0A7T7ZAL2 +---------YELEIDRWGISSGGSNPIETTQGFNDAIQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIYIKNVFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLIRGRRNCLATNGCEGLLVDDCAIEDAGGEgGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVESNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGIYWGVNSEVEAKGNTIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGVKLKNNSVEVTNDRGLTSSFYTEKSTDSLVVMNDYNKGVIKSHETDTV---- +>A0A5J6T752 +---------YELEIDRWGISSGGSNPIETTQGFNDAVQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTKTHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLVRGRRNCLATNGCEGLLVDDCAIEDAGGEgGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVGNNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGTGMGIYWGINSEVEAKGNIIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKTHETDTV---- +>A0A5J6T3Z8 +---------YELEIDRWGISSGGSNPIETTQGFNDAVQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTKTHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLVRGRRNCLATNGCEGLLVDDCAIEDAGGEgGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVGNNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGTGMGIYWGINSEVEAKGNIIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKTHETDTV---- +>A0A5J6T9J0 +---------YELEIDRWGISSGGSNPIETTQGFNDAIQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TLYTPARDVTVSKCTLIRGRRNCLATNGCEGLLVDDCAIEDAGGEgGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGALVESNTLENISAVAVQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGIYWGVNSEVEAKGNTIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKSHETDTV---- +>A0A5J6T6D8 +---------YELEIDRWGISSGGSNPIETTQGFNDAIQYAKTEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIHIKNVFVADCTGDNIWIAAHGMMNWT-TLYTPARDVTVSKCTLIRGRRNCLATNGCEGLLVDDCAIEDAGGEgGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKVIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGALVESNTLENISAVAVQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGIYWGVNSEVEAKGNTIEAGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKSHETDTV---- +>A0A5P8PIC1 +---------YELEIDRWGISSGGSNPIETTQGFNDAVQYAKSEGYAEIFVPKGHYLIDCVSKFGSR-PEYGGGIRLVSDLNVTLHPEATFKVLANDATGYSLFYLELIENVTIKGGRIYGDRYEHTYTYYNDNTETHEWGYGIHVRGSRNIHIKNAFVADCTGDNIWIAAHGMMNWT-TPYTPARDVTVSKCTLVRGRRNCLATNGCEGLLVDDCAIEDAGGEgGTRPQYGIDLEGFGESGIKYDHPYKLVVRNCKFKGNALGDISSFTAGKIIIEGNTCENVISYGYSTDILIENNLIINEGEVKPYGIDSLGVSSTETGNRATIKGNTIRGFNIGINAKGKGVLVESNTLENISAVAIQVYQATDALIANNRV-DSDCIHFQALLAENTLFAGNKSEGNSKDYAYKITNSKGITFTGNELTEGYGGYYVQGSLRSKIISNTLQLVGAGMGVYWGVNSEVEAKGNTIEVGSGVPIMGYADLYKAIIKDNTVKGCQAVYAVYLKGGKRHNIESNILEIARNADYGYGVYIEGTSGAKLKGNSVEVTNDRGLTSSFYTEKSTGSLVVMNDYNKGVIKSHETDTV---- +>A0A5J6T5S7 +---------YELECDRWGIFPDGTNPVETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYTGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGgtrPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNTYN---------------- +>A0A5J6T527 +---------YELECDRWGIFPDGTNPVETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYTGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGgtrPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNTYN---------------- +>A0A5J6T6E0 +---------YELECDRWGIFPDGTNPVETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYAGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGgtrPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTIVDGNKYN---------------- +>A0A5J6T8J3 +---------YELECDRWGISPDGTNPTETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYAGSTYITARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTIEEAGG--VGgtrPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRVSIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSSLVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLYTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNKYN---------------- +>A0A7U3TW25 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQdVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGvHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSTNVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>A0A5J6T602 +---------YELECDRWGISPDGTNPPETTKGFNDALNYAAAEGYREIYIPKGVYKIDCVSNFGSR-PEYGGGIRNPSNLDVDMHPEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYHEEKTKTHEWGYGIHIRGSKNINIENVFVSDCTGDNIWIAANGMMNYAGSTYIPARDVTIKKCTLMRGRRNCLATNGCEGLLVDDCTVEEAGG--VGgtrPEYGIDLEGFGENGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGVVKPYGIDSLGVSSTETGNRASIKGNTIRGFNIGINAKGKGILVSKNTIEDVESVGIQVYQATSALVIGNRI-DADCTHIKMLYAKKTTVIGNESEGNTDNFAYQVTYSERTVFSGNTLYDGDGGLSVGNSTLTKFKGNTLFITGENYGVHWDASSDLEVSDNTFHMGSGVAIMGYADLHTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKVARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSVGTLVDGNKYN---------------- +>A0A7T8C426 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQdVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGvHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSINVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>A0A076G7N8 +---------YFIDFEKHGIRSNGTAARETTDGFISALNDAVASGYKTVYVPKGNYLIDGVG--EDKMPEYGGGIQFPSNIEVIFHKEAVFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMnVSPFRRTHEWGYGVHIRGCRNILIEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTEKGRRNNIATDGCLGLLIDDCDIIKAGGDTIGPQLGIDLEGYAEDGIKYGHPYEINITNCRFRKNGRGALNINVSAKVHATNNFSDDVFSYGYSSDVSICNNKIINDSGTvKKYGIDSIRKSSTETGNRAIISGNHVIGFEIGICARGLGVKISNNYLKDISSIGIYPYLAEEVSVSDN-IIDSNCLHVWVRESKDVKISDNKTKGAANYFAYRVEASSDV-IISDSKSQSKGGIQVLRSRKVVLKDNDLALIGTDYGIHWDKQSEVEVLHNTVRDAAMIAIAGNSELYPSIIKGNNIKDCTYLVGLYVNGGSDHILWDNDVSFkgTGSANGGYGVQLVGTENAWLMNNKVRVSNGRTLSSSYESRGSQNTMYINNALQTG-------------- +>A0A7T7ZC39 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQdVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGvHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KSGVRVSRSTNVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>R4JDQ9 +---------YFIDFDQFGIKDDGTDATSTTSGFVAAFKRAVELGHSAVYVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQPNDSTGYACFNLEGVENVTIRGGHIVGDRHEHNYRQdVNENRRTHEWGFGIQVRGSKNVTIENVTIEDCTGDNIWVTSKGMMNWPG-VYIPSESVTIRKCRTLRGRRNNIAAGASVGLLIDDCDIIEAGGDEIGPQLGIDLEGYADNSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGvHKKFGIDSIRKSTSETANRAVVTGNVIRGFQTGIAARGKTVTVSNNILEDISSIGIYPYLCDQAVVSSN-IIDSDCLHIWVRESKDIKVSDNKGTGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSTNVRIVDNDIDMIGPDYGIYFDKQSEVHLRDNLVKNAAFTAIRGYADQYSSYIKGNIIQDCKYMIAIHIDGGSKHMIKDNDITFRRGSNAGYGVYLIGANDSRLHNNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>A0A7U3TFK2 +---------YFIDFEQFGIKGDGTDATSTTNGFVAAFKRAVELGYSAVFVPEGTYLIDAVG-VGDYLPEYGGGLQFPSNIEVILHEKALFKVQSNDSTGYACFNLEGVENVTIRGGRIVGDRYEHNYRQdVNENRRTHEWGFGIQVRGSKNITIENVTIEDCTGDNIWVTSKGMMNWPG-EYIPSKSVTIRKCQTYRGRRNNIAAGASVGLLIDDCDIIEAGGDTIGPQLGIDLEGYADKSIKYQHPYEINVINCRFKDNGRGSMNINVSGKVNAIGNFCDDYIGYGFSTDVTISNNVITNETGvHKKFGIDSIRKSTSETANRAVIVGNVIRGFQTGIAARGKTVTVSDNILEDISSIGIYPYLCEQAVVSDN-IIDSDCLHIWVRESKDIKVSDNKGIGAANNVSIKVDASKDVLLSDNEVSG-KGGVRVSRSTNVRIVDNDIELIGADYGIYFDKQSEVHLRDNLIKNAAFTAIMGYADQYSSYIRGNIIQDCKYMIAVHIDGGAKHMIKDNDITFRRGSNAGYGIYLIGANDSRLHSNDIRVMDGFGLINSFYTIQSTNTKLIGNTYDTG-------------- +>A0A5J6TBR2 +---------YELECDRWGIFPDGTNPESTTRGFNDALTFAAAEGYKEIYIPKGVYKIDCVSRFGSK-PEYGGGIRNPSNLDVDMHTEATFLVLENDAVGYSLFYINLAENITMKGGRIIGDRYKHTYTYYEDKTKTHEWGYGVHIRGSKNINIENMFISDCTGDNIWVAANGMMNYEGSTYIPSKDVTVRKCTLMRGRRNGLATNGCEGLLVDDCTIEESGGaGGTRPEYGIDLEGFGEGGIKYDHPYKLIIRNCRIKNNGLGAISSFTAGKVIIEGNEVDDVISYGYSTDVTITNNQIINEGEIKPYGIDSLGVSSTETGNRASIKGNTIRGFNIGINAKGKGILVSKNTIEDVESIGIQVYQATSALVIGNRI-DADCTHIQMLYAEKTTVIGNESEGNTQNFAYKVTYSDRTVFSGNTLYDGDGGLDVGQSTLTKFKGNTLFLTGENFGVHWGSSSDLEVSGNTFHMGSGVAIFGYADLHTNIIKDNVIHDSKATYAIYLKGGSFHAVERNTVKIARNADFGYGIYIEGTTGVRMTGNDVAVTNGRDLTAPITTEKSAGTLVDGNKYN---------------- +>A0A2I6UI00 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALKDAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTdgVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGiDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAKNYYGIKVEDSSDV-VVNDNKQVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKTSQVKLVKsNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>A0A890URD5 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALKDAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTdgVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGiDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAKNYYGIKVEDSSDV-VVNDNKQVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKTSQVKLVKsNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>U5PXV9 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALKEAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFMVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTdgVPDNRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPAKGMMNWEGSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFSYGFSTDSTISNNTITNETGiDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVQVGNNKGKDAENYYGIKVEDSSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKTSQVKLIKsNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>S6BUP9 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALREAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTdgVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGvDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAENYYGIKVEDSSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKISQVKLVKsNWISCAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>A0A384XD57 +----NSNYMYFVDFEKFGIRSDGTEARATTEGWIAALKEAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTdgVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFSDDVFNYGFSTDSTISNNTITNETGiDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAENYYGIKVEASSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKISQVKLVKsNWISGAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>L0L8C8 +---------YFIDFEKHGIKSDGTAARETTDGFTYALNDAVNKGYKTVYVPKGDYLINGVG--EDRMPEYGGGIQFPSNIEVIFHKKAIFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMnVSKFRKTHEWGYGVHIRGSRNILVEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTERGRRNNIATDGCLGLLIDDCDIIEAGGDTIGPQLGIDLEGFAEDGIKYGHPYEINVVNNRIRNNGRGSLNINVSAKVHASNNFSDDVFSYGYSSDVSICNNKIINDSGKvRKYGIDSIRKSSTETGNRAIITGNHIIGFEIGICARGLGVKIANNYLKDISSIGIYPYLAEEVSVSDN-IVDSNCLHVWVRESKDVKISDNKTKGADNDFAYRVESSSDV-IISDSKSQANGGIQVIRSRKVTLKDNDLTLTGADYGIYWDKQSEVEVLHNTVRDAAMIAIAGNSNLYPSIVKGNNIKDCTYLVGLYMNGGRDHVIWDNDVSFKgvGSSNGGYGVQLIATTNAWLMDNKVRVSNGRTLSSAYESQSSYKTLYVNNAMQIG-------------- +>A0A1Z1DEW7 +----NSKYVYDIDFGKFGIKPDCTEAAATTEGFITALEDAVDQGYPKVYIPEGFYLIDAVGT-SGKLPEFGGGLRFPSNIEVIFHEKAVFIVDPNDATGYACFNLENVENVTLRGGVVIGDRYKHTYvqEGVPDNRKTHEWGYGLQIRGCRNIKVENMTLMDATGDNIWVPAKGMMNWEGSTYIPSEGITIDKCYTLRGRRNNLATNGCLGLNINDCDFVEAGGDTIGPAYGIDLEGFAENSIKYDHPYEINVTNCRFKRNGKGALTINVAGKAHATNNFSDDIISYGFSTDATISNNTITNESEElKEYGIDSIRKSSSETGNRAIITGNHIRGFKSGICARGVGVVASNNYLENISSVGIYAYLAKNVLMADNVI-NSDCLHVWVRESEDVKISNSKGKGAINNWGIKVEASSNVS-LNDNEHDSKGGVQVARSTDVRAWDNRFTLVGNEYGAYWDKTSEVrVFEGNHIFNPSTIAIAGYGDTYASSIVRNTIHDCKYLTAIYLSGGSQHFVKGNDIRFRRGANGGYGIKLTGTSGVKVIGNDVRTMDGCSLNASYDSSGSVNTQYANNTYHTG--RMLLHD------ +>A0A516KNA2 +----NSKYVYDIDFGKFGIKPDCTEAAATTEGFITALEDAVDQGYPKVYIPEGFYLIDAVGT-SGKLPEFGGGLRFPSNIEVIFHEKAVFIVDPNDATGYACFNLENVENVTLRGGVVIGDRYKHTYvqEGVPDNRKTHEWGYGLQIRGCRNIKVENMTLMDATGDNIWVPAKGMMNWEGSTYIPSEGITIDKCYTLRGRRNNLATNGCLGLNINDCDFVEAGGDTIGPAYGIDLEGFAENSIKYDHPYEINVTNCRFKRNGKGALTINVAGKAHATNNFSDDIISYGFSTDATISNNTITNESEElKEYGIDSIRKSSSETGNRAIITGNHIRGFKSGICARGVGVVASNNYLENISSVGIYAYLAKNVLMADNVI-NSDCLHVWVRESEDVKISNSKGKGAINNWGIKVEASSNVS-LNDNEHDSKGGVQVARSTDVRAWDNRFTLVGNEYGAYWDKTSEVrVFEGNHIFNPSTIAIAGYGDTYASSIVRNTIHDCKYLTAIYLSGGSQHFVKGNDIRFRRGANGGYGIKLTGTSGVKVIGNDVRTMDGCSLNASYDSSGSVNTQYANNTYHTG--RMLLHD------ +>A0A345MJP4 +----NSKYVYFVDFEKFGIKSDGTDAAATTSGWIAALKEAVDLGYPKVYVPAGLYLIDAVGKTDSL-PEYGGGLRFPSNIEVIFHEMALFKVEPNSSTGYACFNLENVENVTLRGGYVIGDRYEHDYTLdgVPNNRRTHEWGHCLHIRGCRNIYVENMTLMNATGDNIWVPAKGMMNWEGSTYIPSEGITIHKCTTIRGRRNNFATNGCIGLNIDDCDFIEAGGDVIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALNINVTGKVHATNNFTDDVISYGFSTDGTISNNTITNETGvHKPFGIDSIRKSSSETGNRTIITGNQIRGFASGICARGVGVIVSNNYLSDISSVGIYPYLSEEVLVSNN-IINSDCLHVWVRESKDVKVNNTKGKGAANNYGIKVEASHDV-VLNDNEHEAKGGIQIARSTNVRVKDNDLNLIGNGNGISWDKTSQVkILDGNWINGAVAIAISGYGEVYPTNIMRNTIEDCKYLIGIYLNGGSQHVIKDNDIMFRRGSNGGYGVQLKDTTDVRVYRNDVRTMDGGTLYSSFDSSGALSTKYVGNTMDAG-------------- +>A0A5B9NKS7 +---MNKELYYHIDLERFGIRDDLTEANATTQGFNAALKDAKEQGYHYFVFPEGKYLINTISNFGGL-PEYGGGIRIPSNIHIIMD-NPYFEAEANDRTGYSIFYLEAVENVEISGiGTICGDRYNHDYvrDLKDDRTKTHEWGFGIHIRGCRRVAIKGLTVKNCTGDNIWIPAKGMMNFPG-DYTPSRDILIQDCDLIHGRRNNLATNGCYGLTVERCDIKEAGGDTIGPQLGIDLEGYGDKGIKYDHPYEITIKNNWIKNNGRGALTAHTSGKVLIEGNFTDAVISYAYSTDVKIKDNFIINEtGQEKPYGIDSIGVSSSETANRVNISGNTVSGFKTGICARGSKVKVRNNEVEGATAAAIQIFQCEKAEVSDN-TTDGNAVGLLIQQSKTVEASDNTFRGAENKYGIKIgQDSSDIILKDNRIRG-FGGIFCESVQNVVVRDHDINLTGSGYGVYFDAKSCVFLDGVTIYNPENTSVYGLADEYAAIIKGVEVIGCKSIIGIYLHGGINHDIKGNTVRFKRGKDQGYGIYLDGTKGAVLARNDVVSTDGFKLSAAYKTDESEQTTLIEN------------------- +>A0A386K842 +---MSKGLYYHIDLERFGIKDDLTEANATTQGFNAALKDAKDQGYHYFVFPEGKYLINAVSNFGGL-PEYGGGIRIPSNINIIMD-NPYFEAEANDQTGYSIFYLEAVENVKISGiGTICGDRYNHDYvrDLKDDRTKTHEWGFGIHIRGCRRVEIKGLTVKNCTGDNIWIPAKGMMNWP-TDYTPSRDILIQDCDLIQGRRNNLATNGCYGLTVERCDIKEAGGDTIGPQLGIDLEGYGDKGIKYDHPYEITIKNNWIKNNGRGALTAHTSGKVLIEGNFTDAVISYAYSTDVKIKDNFIINEtGQEKPYGIDSIGVSSSETANRVNISGNTVSGFKTGICARGSKVKIHGNEVEGATAAAIQIYQCEKVEVSDN-TTDGNAVGLLIQQSKTVEASDNTFRGSENKYGIKIgQDSSDIILKDNRIRG-FGGIFCESAQKVIVRDHDIDLTGSGYGVYFDAKSSVFLDGVTIYNPENTPVYGLADEFAAIMKDVEVIGCKSIIGIYMHGGFGHDIKGNTVRFRRGKDQGYGIFLDGTKSAVLTRNDVLSTDGFKLSAAYKTDGSERTTLIEN------------------- +>D0VXF4 +----NSNYMYFVDFEKFGIRSDGTEARATTDGWIAALREAVELGYHTVYVPEGLYLIDAVSTVGSL-PEYGGGLMFPSNIEVIFHERALFQVAPNSSTGYACFNLENVENVTLRGGTIIGDRYEHDYVTdgVPDKRKTHEWGHGIHIRGCRNITVENATVMNCTGDNIWVPSKGMMNWEDSTYIPSEGITIRKCILIRGRRNNLATNGCLGMNVDDCDFIEAGGDTIGPAFGIDLEGFAENSIKYDHPYEINITNCRFKRNGKGALTSTLQGKFMLLIT-SPMMAQLWFSTDSTISNNTITNETGvDKPYGIDSIRKSSSETGNRTIITGNQIRGFATGICARGVGVIVSQNYLEDISSVGINPYLSEDVMVANNTI-NSDCLHVWVRNSVDVKVGNNKGKGAENYYGIKVEDSSDV-VVNDNKHVAKGGIQVARSTNVRIKDNDLTLIGNGNGISWDKISQVKLVKsNWISCAVAAAISGYADAYSTIISYNILEDCKYLIAIYLNGGAHHMLKGNDIMFRRGANGGYGVQLVNTTQARLISNDVRTMDGCTLHASYDSTGSTYTKYAYNTY----------------- +>A0A0A0PLR7 +-------------------------------------------------------------------PEYGGGIQFPSNIEVIFHKEAVFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMnVSKFRKTHEWGYGVHIRGCRNILVEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTERGRRNNIATDGCLGLLIDDCDIVEAGGDTIGPQLGIDLEGFAEDGIKYGHPYEINITNNRFRENGRGSLNINVSAKVHATNNFSDDVFSYGYSSDVSICNNKIINESGKvRKYGIDSIRKSSTETGNRAIITGNHIIGFEIGICARGLGVKIANNYLKDISSIGIYPYLAEEVSVSDN-IIDSNCLHVWVRESKDVKISDNKTKGAANHFAYRVEASSDV-LISDSKSQSKGGIQVIRSRKVILKDNDLSLTGADYGIQWDKQSEVEVLNNTVRDAAMIAIAGNSELYPSVIKGNNIKDCTYLVGLYVNGGSNHILWDNDISFrgTGTTNGGYGVQLVGTENVWLMNNKVRTSNGRLLSSAYESRNSKKTMYINNALQAG-------------- +>A0A0A0PUI4 +-------------------------------------------------------------------PEYGGGIQFPSNIEVIFHKEAVFKVEPNSSTGYACFNLENVDNVILRGGCVVGERFEHDYDMnVSKFRKTHEWGYGVHIRGCRNILVEDMHISDCTGDCIWVPAHGMMNWGDTVYIPSESITIRKCRTERGRRNNIATDGCLGLLIDDCDIVEAGGDTIGPQLGIDLEGFAEDGIKYGHPYEINITNNRFRENGRGSLNINVSAKVHATNNFSDDVFSYGYSSDVSICNNKIINESGKvRKYGIDSIRKSSTETGNRAIITGNHIIGFEIGICARGLGVKIANNYLKDISSIGIYPYLAEEVSVSDN-IIDSNCLHVWVRESKDVKISDNKTKGAANHFAYRVEASSDV-LISDSKSQSKGGIQVIRSRKVILKDNDLSLTGADYGIQWDKQSEVEVLNNTVRDAAMIAIAGNSELYPSVIKGNNIKDCTYLVGLYVNGGSNHILWDNDISFrgTGTTNGGYGVQLVGTENVWLMNNKVRTSNGRLLSSAYESRNSKKTMYINNALQAG-------------- +>A0A5P8PIG3 +---------YPVNLEEWGINKDFQEPEATTEAFNKAFTYAKNMGYFEVWVPPGNYLIDGVNESNIYATENGGGIHLHSNTHYKLNPESVFKINANNAQGYSVFYIGLAYNVTLEGGQLIGDRHEHDYSTVTQNRNTHEFGFGVNVHGSERVNIVNVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDVIGPQLGIDFEGYAENGIKYAHPYNLQLKNSRFRDNGRGCFTAHAVGKAIISENFFDDRVSYGFGTDISIVDNHIINDGEVRDLAIDSIQPPSYDNANRVKISGNKIKGFKKGMTIRGKEIDVTDNDLNNITETGIHVYLAEEITVNENRV-NSDCVPLNIQISKKVNVSDNTFKGGAEKYGVIVSgEVEDISFKDNHI-EAGGGIDAGSAKNVRIlSKNEIFVKGKLNALRNNAGSTVKVNGLNIYDPAAYPMeldgsAGALDIKNV-----SIYGCKAFIAINIKNGRRHKIKNNDIVFERETNGGYGVYLSGTERTKLMDNDVSTSNDFAIGAPFHTEGSMYSTIMHNYYDSG-------------- +>M4ZRV1 +---------YPLNLEEWGINKEFQEPEETTAAFNKAFEYAKSMGYFKILVPPGNFLIDGVNESNIYATENGGGIHLHSNTHYLLHPESVFKINANDAQGYSVFYIGLAYNVTLEGGQLIGDRHEHDYSTSTQNRNTHEFGFGVNVHGSERVNIINVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDTIGPQLGIDFEGYAENGVKYAHPYNLQVKDSRFKNNGRGCFTAHAVGKAIISKNFFDDRVSYGFGTDISIVDNHIINDGEVRPLAIDSIQPPSYDNANRVKISGNTIKGFKKGMTIRGKEVDVIDNKLNNITDTGIHVYLAEEITVNENRV-NSDCVPLNIQISEKVNVSDNTFKGGSEKYGVVISgEVEDISFKDNHI-EAGGGIDAGVAKNVRIlSKNEIFVKGKLNALRNNAGSTVKVNGLNIYDPAayPMELDGSAGALDIR--NVSIYGCKAFIAINIKNGKSHKIKNNDIIFNRGSNGGYGIHLSGTEKAKLTNNYVSTSDGFAIGSPYHTENSTYSTVMNNYYDSG-------------- +>A0A5P8PHR1 +---------YPVNLEEWGINKDFQEPEATTEAFNRAFTYAKNMGYFEVWVPPGNYLIDGVNESNVYATENGGGIHLHSNTHYKLNPESVFKINANDAQGYSVFYVGLAYNVTLEGGQLIGDRYEHNYSTVAPNRSTHEFGFGVNVHGSERVNIINVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDIIGPQLGIDFEGYAENGIKYAHPYNLQLKNSRFKDNGRGCFTAHATGKAIISENFFDDRVSYGFGTDISIVDNHIINDGEVRPLAIDSIQPPSYDNANRVKVAGNKIKGFKKGMTIRGKEVDVTDNDLNDVTETGIHVYLAEEITVNENRV-NSDCVPLNIQISKKVNVSDNTFKGGAEKYGVVISgEVEDISFKDNHI-EAGGGIDAGSAKNVRIlSKNEIFVKGKLNALRNNPGSTMKVNGLNIYDPAAYPMELDGSAGSLDIKNVSIYGCKAFIAINIKNGRRHKIKNNDIIFERETNGGYGIYLSGTERTKLMDNDVSTSNDFAIGSPFHTENAMYSTIMHNYYDSG-------------- +>A0A5P8PI75 +---------YSVNLEEWGINKDFQEPEATTEAFNKAFTYAKNMGYFEVWVPPGNYLIDGVNESNIYATENGGGIHLHSNTHYKLNPESVFKINANNAQGYSVFYIGLAYNVTLEGGQLIGDRHEHDYSTVTQNRNTHEFGFGVNVHGSERVNIVNVRSRDMTGDNILITNKGNMNYPGQTYIPSKNVTVENCYLETARRNNLSAVGCDGVLIDNCDFIAAGGDVIGPQLGIDFEGYAENGIKYAHPYNLQLKNSRFRDNGRGCFTAHAVGKAIISENFFDDRVSYGFGTDISIVDNHIINDGEIRALAIDSIQPPSYDNANRVKISGNKIKGFKKGMTIRGKEIDVTDNDLNNITETGIHVYLAEEITVNENRV-NSDCVPLNIQISKKVNVSDNTFKGGAEKYGVIVSgEVEDISFKDNHI-EAGGGIDAGSAKNVRIlSKNEIFVKGKLNALRNNPGSTVKVNGLNIYDPAAYPMeldgsAGALDIKNV-----SIYGCKAFIAMNIKNGRRHKIKNNDIVFERETNGGYGVYLSGTERTKLTDNDVSTSNDFAIGAPFHTEGSMYSTIMYNYYDSG-------------- diff --git a/test/unit/test_feature_batch.py b/test/unit/test_feature_batch.py index 76338c50..e1f6bb6f 100644 --- a/test/unit/test_feature_batch.py +++ b/test/unit/test_feature_batch.py @@ -119,6 +119,10 @@ def result_to_msa( del query_db, result_db msa_db.write_text(database.name, encoding="utf-8") + # The fixture's hits carry no insertions and single-token headers, so both + # result2msa passes format them identically and the stitch is a no-op. + result_to_a3m = result_to_msa + def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: output_dir.mkdir(parents=True, exist_ok=True) database_name = msa_db.read_text(encoding="utf-8") @@ -176,18 +180,52 @@ def search( super().search(query_db, database, result_db, work_dir, settings) -class FullHeaderAlignedFastaMmseqs(FakeMmseqsProcess): +class TwoPassMmseqs(FakeMmseqsProcess): + """Formats one hit the way the real pinned MMseqs2 build does, in both passes. + + The hit carries a one-residue insertion (X, between C and D). Mode 2 keeps the + full UniProt header and drops the insertion; mode 5 keeps the insertion and cuts + the header to the accession. Measured, not assumed: see msa_formats. + + This replaces a fixture that fed mode 2 a query row WITH a gap column, on the + belief that mode 2 carries insertions that way. The real build never emits one + -- every row comes back at query width -- so that path never ran on real data. + """ + + def result_to_msa(self, query_db, database, result_db, msa_db) -> None: + del query_db, database, result_db + msa_db.write_text("headers", encoding="utf-8") + + def result_to_a3m(self, query_db, database, result_db, msa_db) -> None: + del query_db, database, result_db + msa_db.write_text("insertions", encoding="utf-8") + def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: - del msa_db output_dir.mkdir(parents=True, exist_ok=True) + insertions = msa_db.read_text(encoding="utf-8") == "insertions" for index, (query_id, sequence) in enumerate(self._queries[query_db]): assert sequence == "ACDE" + hit = ( + ">P12345\nACxDE\n" + if insertions + else ">sp|P12345|KINASE_HUMAN Protein kinase OS=Homo sapiens " + "OX=9606 GN=KIN1\nACDE\n" + ) + (output_dir / f"{index}.fasta").write_text( + f">{query_id}\nACDE\n{hit}", encoding="utf-8" + ) + + +class ReorderedPassesMmseqs(TwoPassMmseqs): + """The two passes disagree about which hit is which, as a future MMseqs2 might.""" + + def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: + output_dir.mkdir(parents=True, exist_ok=True) + insertions = msa_db.read_text(encoding="utf-8") == "insertions" + for index, (query_id, _) in enumerate(self._queries[query_db]): + first, second = ("ACDE", "ACDQ") if insertions else ("ACDQ", "ACDE") (output_dir / f"{index}.fasta").write_text( - f">{query_id} query description\n" - "AC-DE\n" - ">sp|P12345|KINASE_HUMAN Protein kinase OS=Homo sapiens " - "OX=9606 GN=KIN1\n" - "ACXDE\n", + f">{query_id}\nACDE\n>sp|P1|A_HUMAN\n{first}\n>sp|P2|B_YEAST\n{second}\n", encoding="utf-8", ) @@ -247,6 +285,31 @@ def test_subprocess_adapter_requests_aligned_fasta_output(tmp_path): assert command[command.index("--msa-format-mode") + 1] == "2" +def test_subprocess_adapter_requests_a3m_for_the_insertion_pass(tmp_path): + # Mode 5 is the only result2msa format that keeps insertions. + binary = tmp_path / "mmseqs" + arguments = Path(f"{binary}.arguments") + binary.write_text( + '#!/bin/sh\nprintf \'%s\\n\' "$@" > "${0}.arguments"\n', + encoding="utf-8", + ) + binary.chmod(0o755) + database = DatabaseSpec( + name="uniprot", path=tmp_path / "uniprot", identifier="fixture" + ) + + SubprocessMmseqsProcess(binary).result_to_a3m( + tmp_path / "query", + database, + tmp_path / "result", + tmp_path / "msa", + ) + + command = arguments.read_text(encoding="utf-8").splitlines() + assert command[0] == "result2msa" + assert command[command.index("--msa-format-mode") + 1] == "5" + + def test_gpu_search_does_not_pass_ignored_sensitivity_option(tmp_path): binary = tmp_path / "mmseqs" arguments = Path(f"{binary}.arguments") @@ -570,10 +633,15 @@ def test_downstream_af3_failure_preserves_a_valid_msa_bundle(tmp_path): assert bundle.exists() -def test_aligned_fasta_conversion_preserves_taxon_header_and_insertions(tmp_path): +def test_stitched_alignment_keeps_taxon_header_and_insertions(tmp_path): + """Both halves reach AlphaFold 3 -- which neither result2msa pass gives alone. + + The header decides species pairing; the insertion is what mode 2 used to + discard for 86% of real uniprot hits. + """ batch = FeatureBatch( settings=_settings(tmp_path), - mmseqs_process=FullHeaderAlignedFastaMmseqs(), + mmseqs_process=TwoPassMmseqs(), af3_pipeline=PassthroughAf3Pipeline(), ) @@ -591,6 +659,78 @@ def test_aligned_fasta_conversion_preserves_taxon_header_and_insertions(tmp_path assert "\nACxDE\n" in paired_msa +def test_passes_that_disagree_fail_the_request_rather_than_mislabel_hits(tmp_path): + """A positional join that silently went wrong would label P1's sequence as P2's. + + On the paired database that means pairing chains by the wrong species: a wrong + answer that looks entirely plausible. It has to fail, loudly and per request, + and publish nothing. + """ + settings = _settings(tmp_path) + batch = FeatureBatch( + settings=settings, + mmseqs_process=ReorderedPassesMmseqs(), + af3_pipeline=PassthroughAf3Pipeline(), + ) + + result = batch.generate([FeatureRequest(name="alpha", sequence="ACDE")]) + + assert [failure.name for failure in result.failures] == ["alpha"] + assert "no longer in the same order" in result.failures[0].error + assert not (settings.msa_output_dir / "alpha_mmseqs_msa.json").exists() + assert not (tmp_path / "features" / "alpha_af3_input.json").exists() + + +def test_bundle_records_how_many_rows_each_database_contributed(tmp_path): + """AlphaFold 2 searches templates from uniref90 alone and caps each database + separately, so the merged alignment is only usable if its boundaries survive.""" + settings = _settings(tmp_path) + FeatureBatch( + settings=settings, + mmseqs_process=FakeMmseqsProcess(), + af3_pipeline=PassthroughAf3Pipeline(), + ).generate([FeatureRequest(name="alpha", sequence="ACDEFG")]) + + bundle = json.loads( + (settings.msa_output_dir / "alpha_mmseqs_msa.json").read_text(encoding="utf-8") + ) + assert bundle["schemaVersion"] == 3 + spans = bundle["unpairedDatabaseRows"] + assert [span["name"] for span in spans] == ["uniref90", "mgnify", "small_bfd"] + # The fixture gives each database one distinct hit, and the spans must account + # for every row of the merged alignment except the query. + assert [span["rows"] for span in spans] == [1, 1, 1] + assert sum(span["rows"] for span in spans) == bundle["unpairedDepth"] - 1 + + # And each span really is that database's rows, in order. + rows = bundle["unpairedMsa"].splitlines()[3::2] + assert [row[0] for row in rows] == ["V", "R", "N"] + + +def test_bundle_whose_row_spans_do_not_add_up_is_searched_again(tmp_path): + """A wrong count does not fail when sliced -- it hands AlphaFold 2 another + database's rows as uniref90. So a bundle that does not add up is not reused.""" + settings = _settings(tmp_path) + request = FeatureRequest(name="alpha", sequence="ACDEFG") + FeatureBatch( + settings=settings, + mmseqs_process=FakeMmseqsProcess(), + af3_pipeline=PassthroughAf3Pipeline(), + ).generate([request]) + bundle_path = settings.msa_output_dir / "alpha_mmseqs_msa.json" + bundle = json.loads(bundle_path.read_text(encoding="utf-8")) + bundle["unpairedDatabaseRows"][0]["rows"] += 1 + bundle_path.write_text(json.dumps(bundle), encoding="utf-8") + + searching = FakeMmseqsProcess() + result = MsaBatch( + settings=_msa_settings(settings), mmseqs_process=searching + ).generate([request]) + + assert [artifact.name for artifact in result.written] == ["alpha"] + assert result.reused == () + + def test_matching_artifact_is_reused_without_external_search(tmp_path): settings = _settings(tmp_path) pipeline = _native_pipeline_with_no_template_hits(tmp_path) diff --git a/test/unit/test_feature_batch_rna.py b/test/unit/test_feature_batch_rna.py index 5202e432..37feb58e 100644 --- a/test/unit/test_feature_batch_rna.py +++ b/test/unit/test_feature_batch_rna.py @@ -29,6 +29,7 @@ FeatureRequest, MsaBatch, MsaBatchSettings, + SearchedMsas, SubprocessMmseqsProcess, feature_requests_from_fastas, ) @@ -137,6 +138,10 @@ def result_to_msa(self, query_db, database, result_db, msa_db) -> None: del query_db, result_db msa_db.write_text(database.name, encoding="utf-8") + # The fixture's hits carry no insertions and single-token headers, so both + # result2msa passes format them identically and the stitch is a no-op. + result_to_a3m = result_to_msa + def unpack_msa(self, query_db: Path, msa_db: Path, output_dir: Path) -> None: output_dir.mkdir(parents=True, exist_ok=True) database_name = msa_db.read_text(encoding="utf-8") @@ -245,17 +250,28 @@ def test_rna_databases_are_the_three_alphafold3_searches_in_its_merge_order(): # -------------------------------------------------------------------------------- -def test_protein_cache_signature_is_exactly_what_it_was_before_rna_existed(tmp_path): - """Pinned literally: changing it silently invalidates every cached protein MSA.""" +def test_protein_cache_signature_is_pinned(tmp_path): + """Pinned literally: changing it silently invalidates every cached protein MSA. + + It last moved, deliberately, when insertions were recovered (schema 4 -> 5, + and ``msa_format`` added). Bundles written before that came from mode 2 alone + and carry no insertions -- 86% of uniprot hits lost theirs on a real query -- + so reusing them would have kept the defect. The only cache that existed at + the time was two bundles of e2e test data. Move it again only as deliberately. + """ batch = MsaBatch( settings=_msa_settings(_settings(tmp_path)), mmseqs_process=FakeMmseqsProcess(), ) assert batch._cache_signature(PROTEIN) == { - "schema_version": 4, + "schema_version": 5, "mmseqs_identity": "mmseqs-fixture-1", "search_mode": "gpu", + "msa_format": { + "headers": "result2msa mode 2", + "sequences": "result2msa mode 5", + }, "e_value": 1e-4, "unpaired_databases": [ { @@ -306,12 +322,12 @@ def test_a_protein_bundle_records_no_molecule_type_so_old_bundles_still_match(tm ) protein = batch._msa_payload( - FeatureRequest(name="alpha", sequence="ACDE"), ">query\nACDE\n", ">query\nACDE\n" + FeatureRequest(name="alpha", sequence="ACDE"), + SearchedMsas(unpaired=">query\nACDE\n", paired=">query\nACDE\n"), ) rna = batch._msa_payload( FeatureRequest(name="beta", sequence="ACGU", molecule_type=RNA), - ">query\nACGU\n", - "", + SearchedMsas(unpaired=">query\nACGU\n", paired=""), ) assert "moleculeType" not in protein @@ -323,6 +339,7 @@ def test_a_protein_bundle_records_no_molecule_type_so_old_bundles_still_match(tm "pairedMsa", "unpairedDepth", "pairedDepth", + "unpairedDatabaseRows", "provenance", ] assert rna["moleculeType"] == RNA @@ -763,7 +780,9 @@ def test_an_rna_query_reaches_mmseqs_spelled_as_dna(tmp_path, monkeypatch): batch = MsaBatch(settings=settings, mmseqs_process=process) monkeypatch.setattr( - feature_batch_module, "_aligned_fasta_to_a3m", lambda fasta, query, kind: fasta + feature_batch_module, + "_stitched_to_a3m", + lambda records, query, kind: "".join(f">{d}\n{s}\n" for d, s in records), ) batch._search_chunk(["ACGUUU"], RNA) @@ -781,7 +800,9 @@ def test_a_protein_query_is_handed_to_mmseqs_unchanged(tmp_path, monkeypatch): batch = MsaBatch(settings=settings, mmseqs_process=process) monkeypatch.setattr( - feature_batch_module, "_aligned_fasta_to_a3m", lambda fasta, query, kind: fasta + feature_batch_module, + "_stitched_to_a3m", + lambda records, query, kind: "".join(f">{d}\n{s}\n" for d, s in records), ) batch._search_chunk(["ACDEFGU"], PROTEIN) diff --git a/test/unit/test_light_import_invariant.py b/test/unit/test_light_import_invariant.py index ce1181ea..c6bfd6df 100644 --- a/test/unit/test_light_import_invariant.py +++ b/test/unit/test_light_import_invariant.py @@ -54,3 +54,48 @@ def test_the_light_path_pulls_in_neither_alphafold_nor_jax(module): "MMseqs2 search; importing JAX there preallocates GPU memory. Import it " "inside the function that needs it instead." ) + + +# Importing the module was never the hard part. Converting a search result used +# `alphafold3.cpp.msa_conversion`, so the stage imported cleanly in the AlphaFold 2 +# image -- which installs AlphaPulldown without the `alphafold3` extra -- and then +# died on the first result. Exercise the conversion itself, not just the import. +RESULT_PROBE = """ +import importlib, sys +feature_batch = importlib.import_module("alphapulldown.feature_batch") +from alphapulldown.utils.msa_formats import stitch_headers_and_insertions +headers = [ + ("query_0", "MKTAYIAKQRQ"), + ("sp|P00001|EXACT_HUMAN exact OS=Homo sapiens OX=9606", "MKTAYIAKQRQ"), + ("tr|P00003|DELETE_YEAST deletion OS=Saccharomyces OX=4932", "MKT---AKQRQ"), +] +insertions = [ + ("query_0", "MKTAYIAKQRQ"), + ("P00001", "MKTAYIAKQRQ"), + ("P00003", "MKT---AKwwQRQ"), +] +a3m = feature_batch._stitched_to_a3m( + stitch_headers_and_insertions(headers, insertions), "MKTAYIAKQRQ" +) +assert "sp|P00001|EXACT_HUMAN" in a3m, "full headers must survive conversion" +assert "MKT---AKwwQRQ" in a3m, "deletions and insertions must survive conversion" +leaked = sorted( + name for name in sys.modules + if any(name == f or name.startswith(f + ".") for f in {forbidden!r}) +) +print(",".join(leaked)) +""" + + +def test_converting_a_search_result_pulls_in_neither_alphafold_nor_jax(): + completed = subprocess.run( + [sys.executable, "-c", RESULT_PROBE.format(forbidden=FORBIDDEN)], + capture_output=True, + text=True, + ) + assert completed.returncode == 0, completed.stderr[-2000:] + leaked = [name for name in completed.stdout.strip().split(",") if name] + assert not leaked, ( + f"converting a search result now imports {leaked}. The MSA stage has to " + "run in the AlphaFold 2 image, which has no AlphaFold 3 at all." + ) diff --git a/test/unit/test_msa_formats.py b/test/unit/test_msa_formats.py new file mode 100644 index 00000000..4eb140f5 --- /dev/null +++ b/test/unit/test_msa_formats.py @@ -0,0 +1,171 @@ +"""Joining two MMseqs2 formats into one A3M with headers AND insertions.""" + +from __future__ import annotations + +from pathlib import Path +import re +import subprocess +import sys + +import pytest + +from alphapulldown.utils.msa_formats import ( + StitchMismatch, + stitch_headers_and_insertions, + strip_insertions, +) + + +def test_conversion_does_not_import_alphafold(): + """The whole point: this must work in the AlphaFold 2 image. + + Checked in a subprocess, because the test session may already have imported + AlphaFold for other modules and would mask exactly what is being measured. + """ + probe = ( + "import sys;" + "from alphapulldown.utils.msa_formats import stitch_headers_and_insertions as f;" + "f([('q', 'MKTAYI')], [('q', 'MKTAYI')]);" + "print(','.join(n for n in sys.modules if n.startswith('alphafold')))" + ) + completed = subprocess.run( + [sys.executable, "-c", probe], capture_output=True, text=True, check=True + ) + assert completed.stdout.strip() == "" + + +def test_strip_insertions_leaves_one_column_per_query_position(): + # Lowercase residues are insertions; gaps and match residues are columns. + assert strip_insertions("MKTwwAY-I") == "MKTAY-I" + + +def test_stitch_takes_headers_from_one_pass_and_insertions_from_the_other(): + headers = [("query", "MKTAYI"), ("sp|P1|A_HUMAN full header", "MKTAYI")] + insertions = [("query", "MKTAYI"), ("P1", "MKTwwAYI")] + assert stitch_headers_and_insertions(headers, insertions) == [ + ("query", "MKTAYI"), + ("sp|P1|A_HUMAN full header", "MKTwwAYI"), + ] + + +def test_stitch_refuses_rows_that_disagree(): + """A silent positional join here would pair a header with another hit's + sequence -- for the paired database, pairing chains by the wrong species.""" + headers = [("query", "MKTAYI"), ("sp|P1|A_HUMAN", "MKTAYI")] + reordered = [("query", "MKTAYI"), ("P2", "MKTAYQ")] + with pytest.raises(StitchMismatch, match="no longer in the same order"): + stitch_headers_and_insertions(headers, reordered) + + +def test_stitch_refuses_differing_row_counts(): + with pytest.raises(StitchMismatch, match="different row counts"): + stitch_headers_and_insertions([("query", "MKT")], []) + + +def _read_records(path: Path) -> list[tuple[str, str]]: + records, description, parts = [], None, [] + for line in path.read_text(encoding="utf-8").splitlines(): + if line.startswith(">"): + if description is not None: + records.append((description, "".join(parts))) + description, parts = line[1:], [] + elif description is not None: + parts.append(line) + if description is not None: + records.append((description, "".join(parts))) + return records + + +REAL_MODE2 = Path(__file__).parent / "data" / "small_bfd.mode2.txt" +REAL_MODE5 = Path(__file__).parent / "data" / "small_bfd.mode5.txt" + + +@pytest.mark.skipif( + not (REAL_MODE2.exists() and REAL_MODE5.exists()), + reason="real MMseqs2 output fixtures are not checked in", +) +def test_stitch_holds_on_real_mmseqs_output(): + """The synthetic cases prove the logic; this proves the assumption. + + Fixtures are the two passes over one real search of a 586-residue query + against small_bfd, produced by the pinned MMseqs2 build. + + Note which database this is. How much a header loses in mode 5 depends on the + FASTA it was built from: small_bfd headers are a single token + (``A0A163VT74_9BACL``) and survive intact, so the stitch changes only the + sequences here. It is uniprot that loses the species -- + ``sp|P83570|GWA_SEPOF …`` becomes a bare ``P83570`` -- and uniprot is exactly + where species decides chain pairing. The insertion half of the join is what + this fixture exercises; ``test_stitch_recovers_uniprot_species_headers`` + covers the other half. + """ + headers = _read_records(REAL_MODE2) + insertions = _read_records(REAL_MODE5) + stitched = stitch_headers_and_insertions(headers, insertions) + + assert len(stitched) == len(headers) > 1 + assert [description for description, _ in stitched] == [ + description for description, _ in headers + ] + assert [sequence for _, sequence in stitched] == [ + sequence for _, sequence in insertions + ] + # The point of the exercise: insertions the header pass discarded are back. + recovered = sum( + 1 for _, sequence in stitched for residue in sequence if residue.islower() + ) + assert recovered > 0, "insertions must survive the stitch" + assert not any( + residue.islower() for _, sequence in headers for residue in sequence + ), "the header pass is expected to carry no insertions at all" + + +UNIPROT_MODE2 = Path(__file__).parent / "data" / "uniprot.mode2.txt" +UNIPROT_MODE5 = Path(__file__).parent / "data" / "uniprot.mode5.txt" + + +@pytest.mark.skipif( + not (UNIPROT_MODE2.exists() and UNIPROT_MODE5.exists()), + reason="real uniprot MMseqs2 output fixtures are not checked in", +) +def test_stitch_recovers_uniprot_species_headers(): + """The half that decides whether multimer pairing works at all. + + AlphaFold 2 reads the species mnemonic out of ``sp|ACC|NAME_SPECIES``. Mode 5 + reduces that to ``ACC``, so an alignment built from it alone would pair no + chains; the stitched alignment must carry the parseable form. + """ + headers = _read_records(UNIPROT_MODE2) + insertions = _read_records(UNIPROT_MODE5) + stitched = stitch_headers_and_insertions(headers, insertions) + + # Mirrors alphafold.data.msa_identifiers._UNIPROT_PATTERN, which is what + # actually decides whether a row can be paired. Reproduced rather than + # imported because this module must stay free of AlphaFold; the authoritative + # check against the real function belongs with the AF2 finalizer tests. + uniprot = re.compile( + r"^(?:tr|sp)\|[A-Za-z0-9]{6,10}(?:_\d)?\|[A-Za-z0-9]+_([A-Za-z0-9]{1,5})" + r"(?:_\d+)?$" + ) + + def species(records): + found = set() + for description, _ in records: + match = uniprot.match(description.split()[0]) + if match: + found.add(match.group(1)) + return found + + stitched_species = species(stitched) + assert len(stitched_species) > 1, ( + "the stitched alignment must yield species mnemonics; without them " + "AlphaFold 2 pairs no chains at all" + ) + assert species(insertions) == set(), ( + "the insertion pass is expected to yield none, which is why it is stitched" + ) + assert species(headers) == stitched_species + assert ( + sum(1 for _, sequence in stitched for residue in sequence if residue.islower()) + > 0 + ) diff --git a/workflows/mmseqs2-gpu.md b/workflows/mmseqs2-gpu.md index ff2547ce..5dedb163 100644 --- a/workflows/mmseqs2-gpu.md +++ b/workflows/mmseqs2-gpu.md @@ -70,9 +70,23 @@ knob and does not include one in cache provenance. ## MSA and template behavior For each chunk, one query database is reused for UniRef90, MGnify, small BFD, -and paired UniProt searches. Aligned FASTA is converted to A3M while retaining -insertions and complete UniProt descriptions, including taxonomy metadata. -Unpaired hits from all three databases are merged and deduplicated. +and paired UniProt searches. Each search result is formatted twice, because no +single `result2msa` format carries both things an alignment needs: mode 2 keeps +complete UniProt descriptions, including the species AlphaFold pairs chains by, +but drops every insertion; mode 5 keeps the insertions but cuts the header to +the accession. The two are joined row by row, and the join is verified on every +row rather than trusted. The second pass costs about 16 ms per hit. + +MSA bundles written before this (bundle schema 2, provenance schema 4) came +from mode 2 alone and carry no insertions, so the deletion matrix AlphaFold +derived from them was all zeros; against a real query, 81.7% of small BFD hits +and 86.4% of UniProt hits had insertions that were lost. The provenance change +means such bundles are never reused: they are searched again. + +Unpaired hits from all three databases are merged and deduplicated, and the +bundle records how many rows each database contributed. AlphaFold 3 does not +need that, but an AlphaFold 2 consumer does: it builds its template profile from +UniRef90 alone and caps each database separately. The finalizer passes that merged unpaired MSA to native AF3 with `templates` unset. This matches AF3's own pipeline: it merges UniRef90, small-BFD, and MGnify From 328aad9c5d6c32d4e13a86998e7dd3df83e26c49 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 09:41:40 +0200 Subject: [PATCH 03/17] feat: build AlphaFold 2 features from local MMseqs2 MSA bundles The local MMseqs2 search stage was AlphaFold 3 only. It is backend-neutral -- one MSA bundle per chain -- so AlphaFold 2 support is a second finalizer that turns a bundle into a pickled MonomericObject, the form AF2 inference reads. Both CPU and GPU search feed it. finalize_batch_features.py now takes --data_pipeline=alphafold2 and selects it; --use_mmseqs2 keeps meaning the remote ColabFold API. It builds features as alphafold.data.pipeline.DataPipeline.process does from jackhmmer: uniref90 capped at 10000 and mgnify at 501, counting the query as AF2 does; merge order uniref90, BFD, MGnify (row order decides what AF2 samples); templates searched from uniref90 alone, never the merged alignment, via the bundle's per-database row spans; the paired UniProt alignment truncated to 50000 and exposed as *_all_seq. The recipe is AF2's reduced_dbs set -- there is no BFD/UniRef30 HHblits arm -- and the module says where it cannot be exact. The paired features come from an independent UniProt search whose headers carry the species AF2 pairs chains by. The remote path has no such search and copies the unpaired features into *_all_seq instead. Accession identifiers are parsed offline from the headers; nothing on this path queries UniProt over the network. A local pickle carries the 21 keys a native one does plus the two accession arrays. AF2 pairing takes its key set from the first chain, so an extra key crashes in one order only (#619); pair_and_merge backfills identifier arrays first, and a test pairs a local chain with an older pickle in both orders. Another asserts which rows pair -- two chains' HUMAN hits on one row -- through AF2's own pairing code. The template stack is built from explicit settings rather than global FLAGS, and the legacy script now delegates to the same builder. Metadata records only the template resources that ran: the jackhmmer and HHblits flags default to whatever is on PATH, and recording them would claim tools that never touched this MSA. make_features' template defaults are extracted and shared, so the two paths cannot drift. An end-to-end test runs nothing faked: real MMseqs2 through create_batch_msas, then this finalizer with real hmmsearch against a seqres backed by the real 3L4Q mmCIF, and checks the pickle for the template, the recovered insertion and the parsed species. Its query is an NS1 homolog, not NS1: AF2 discards a template identical to its query without a warning. Co-Authored-By: Claude Opus 5 (1M context) --- alphapulldown/af2_feature_finalizer.py | 451 ++++++++++++++++++ alphapulldown/feature_batch.py | 110 +++-- alphapulldown/objects.py | 28 +- .../scripts/create_individual_features.py | 54 ++- .../scripts/finalize_batch_features.py | 106 +++- test/integration/test_mmseqs2_af2.py | 210 ++++++++ test/unit/test_af2_feature_finalizer.py | 355 ++++++++++++++ test/unit/test_af2_msa_inputs.py | 100 ++++ 8 files changed, 1322 insertions(+), 92 deletions(-) create mode 100644 alphapulldown/af2_feature_finalizer.py create mode 100644 test/integration/test_mmseqs2_af2.py create mode 100644 test/unit/test_af2_feature_finalizer.py create mode 100644 test/unit/test_af2_msa_inputs.py diff --git a/alphapulldown/af2_feature_finalizer.py b/alphapulldown/af2_feature_finalizer.py new file mode 100644 index 00000000..4d05f34b --- /dev/null +++ b/alphapulldown/af2_feature_finalizer.py @@ -0,0 +1,451 @@ +"""AlphaFold 2 features from a local MMseqs2 MSA bundle. + +The search stage (``feature_batch.MsaBatch``) is backend-neutral: it writes one MSA +bundle per chain. This module turns a bundle into what the AlphaFold 2 backend +reads -- a pickled ``alphapulldown.objects.MonomericObject`` -- building it the way +``alphafold.data.pipeline.DataPipeline.process`` builds features from jackhmmer, +so the result drops into existing AlphaFold 2 inference unchanged. + +What is reproduced from native AlphaFold 2: + +- per-database caps, counting the query row as AlphaFold 2 does: uniref90 at + 10 000 and mgnify at 501, small BFD uncapped (``pipeline.py``: jackhmmer's + ``max_sto_sequences``, which stops at that many sequence names, query first) +- merge order uniref90, BFD, MGnify (``pipeline.py:265``). Row order matters: + AlphaFold 2 deduplicates in that order and samples its MSA from the top +- templates searched from uniref90 ALONE, never from the merged alignment +- the paired UniProt alignment truncated to 50 000 rows, as + ``MonomericObject.all_seq_msa_features`` does, and exposed as ``*_all_seq`` + +Where it cannot be exact, and why that is acceptable: + +- The database recipe is uniref90, MGnify, small BFD and UniProt -- AlphaFold 2's + ``reduced_dbs`` set. There is no BFD/UniRef30 HHblits arm, so these features are + comparable to ``--db_preset=reduced_dbs``, not ``full_dbs``. +- The bundle deduplicated rows across databases before this module sees them, so + the caps apply to each database's rows after that deduplication. Native + AlphaFold 2 caps raw hits first. The mgnify cap can therefore admit a few more + unique rows than native, and a sequence both MGnify and small BFD found counts + against MGnify's cap. Both effects touch only rows duplicated across databases. +- The template profile is built from the uniref90 A3M with insertions removed. + jackhmmer's Stockholm carries insert columns; A3M insertions are per row and not + aligned to each other, so they cannot be turned back into columns faithfully. + Match columns -- which decide the profile's states -- are identical. + +And one deliberate improvement: UniProt accession identifiers are filled from the +alignment headers, where native features leave them empty. Nothing here ever +queries UniProt over the network; see :func:`_no_network`. +""" + +from __future__ import annotations + +import copy +import dataclasses +from datetime import date +import json +import lzma +import os +from pathlib import Path +import pickle +import tempfile +from typing import Any, Mapping, Sequence + +from alphapulldown.feature_batch import ( + PROTEIN, + UNPAIRED_DATABASE_NAMES, + FeatureArtifact, + FeatureBatchResult, + FeatureFailure, + FeatureRequest, + SearchedMsas, + _fasta_records, + _validate_feature_requests, + read_msa_bundle, + searched_msas_from_payload, +) + + +# AlphaFold 2's own caps, counting the query row the way it does. +AF2_MAX_SEQUENCES = {"uniref90": 10_000, "mgnify": 501} +# pipeline.py:265 -- make_msa_features((uniref90_msa, bfd_msa, mgnify_msa)). +AF2_MERGE_ORDER = ("uniref90", "small_bfd", "mgnify") +# MonomericObject.all_seq_msa_features truncates the UniProt alignment here. +PAIRED_MAX_SEQUENCES = 50_000 +TEMPLATE_SEARCHERS = ("hmmsearch", "hhsearch") +# Bump when the construction below changes, so features an older construction +# built are regenerated rather than reused. +_AF2_FEATURE_SCHEMA = 1 + + +@dataclasses.dataclass(frozen=True, slots=True) +class Af2MsaInputs: + """The three alignments AlphaFold 2 features are built from.""" + + # Becomes msa / deletion_matrix_int: all three databases, capped, in AF2 order. + main_a3m: str + # uniref90 alone: what the template profile is built from. + template_a3m: str + # UniProt: becomes *_all_seq, which pairs chains by species. + paired_a3m: str + + +def _a3m(records: Sequence[tuple[str, str]]) -> str: + return "".join(f">{description}\n{sequence}\n" for description, sequence in records) + + +def af2_msa_inputs(msas: SearchedMsas) -> Af2MsaInputs: + """Cut a bundle's alignments into the shapes native AlphaFold 2 would have.""" + query, by_database = msas.rows_by_database() + missing = [name for name in UNPAIRED_DATABASE_NAMES if name not in by_database] + if missing: + raise ValueError( + "MSA bundle does not say which rows came from " + + ", ".join(missing) + + "; AlphaFold 2 needs each database's rows separately" + ) + + def capped(name: str) -> list[tuple[str, str]]: + rows = by_database[name] + cap = AF2_MAX_SEQUENCES.get(name) + # AlphaFold 2 counts the query toward its cap, so a cap of N keeps N - 1 hits. + return rows if cap is None else rows[: cap - 1] + + blocks = {name: capped(name) for name in AF2_MERGE_ORDER} + paired_records = _fasta_records(msas.paired) + if not paired_records: + raise ValueError( + "MSA bundle has no paired UniProt alignment; AlphaFold 2 multimer " + "pairing needs one" + ) + return Af2MsaInputs( + main_a3m=_a3m( + [query, *(row for name in AF2_MERGE_ORDER for row in blocks[name])] + ), + template_a3m=_a3m([query, *blocks["uniref90"]]), + paired_a3m=_a3m(paired_records[:PAIRED_MAX_SEQUENCES]), + ) + + +def _no_network(accessions: Sequence[str]) -> dict[str, str]: + """Resolve nothing, rather than ask UniProt. + + The shared identifier helper falls back to UniProt REST lookups for + accessions whose header carries no species. A local batch of thousands of + chains must not start doing that unannounced -- and it has no need to: the + UniProt database's canonical ``sp|ACC|NAME_SPECIES`` headers carry the species + already, and AlphaFold 2 reads it from them directly. Anything unparseable + stays unresolved, exactly as it would in native features. + """ + del accessions + return {} + + +def _offline_accessions(a3m: str, *, rows: int): + """Accession per alignment row, deduplicated exactly as make_msa_features is.""" + from alphapulldown.utils.mmseqs_species_identifiers import ( + build_mmseq_identifier_features, + ) + + identifiers = build_mmseq_identifier_features( + a3m, species_resolver=_no_network, expected_rows=rows + ) + accessions = identifiers["msa_uniprot_accession_identifiers"] + if len(accessions) != rows: + raise ValueError( + f"accession identifiers cover {len(accessions)} rows but the MSA has " + f"{rows}; they would index the wrong sequences" + ) + return accessions + + +@dataclasses.dataclass(frozen=True, slots=True) +class Af2TemplateStackSettings: + """Everything the AlphaFold 2 template searcher and featurizer are built from. + + Explicit values rather than global flags, so a caller states what it uses + instead of depending on some earlier call having rewritten FLAGS. + """ + + template_mmcif_dir: str + max_template_date: str + kalign_binary_path: str + obsolete_pdbs_path: str | None = None + use_hhsearch: bool = False + # hmmsearch against PDB seqres, the default. + hmmsearch_binary_path: str | None = None + hmmbuild_binary_path: str | None = None + pdb_seqres_database_path: str | None = None + # hhsearch against PDB70, under --use_hhsearch. + hhsearch_binary_path: str | None = None + pdb70_database_path: str | None = None + + @property + def searcher_name(self) -> str: + return "hhsearch" if self.use_hhsearch else "hmmsearch" + + +def build_af2_template_stack(settings: Af2TemplateStackSettings): + """The AlphaFold 2 template searcher and featurizer, as native features use.""" + from alphafold.data import templates + from alphafold.data.tools import hhsearch, hmmsearch + + if settings.use_hhsearch: + searcher = hhsearch.HHSearch( + binary_path=settings.hhsearch_binary_path, + databases=[settings.pdb70_database_path], + ) + featurizer = templates.HhsearchHitFeaturizer( + mmcif_dir=settings.template_mmcif_dir, + max_template_date=settings.max_template_date, + max_hits=20, + kalign_binary_path=settings.kalign_binary_path, + release_dates_path=None, + obsolete_pdbs_path=settings.obsolete_pdbs_path, + ) + return searcher, featurizer + featurizer = templates.HmmsearchHitFeaturizer( + mmcif_dir=settings.template_mmcif_dir, + max_template_date=settings.max_template_date, + max_hits=20, + kalign_binary_path=settings.kalign_binary_path, + obsolete_pdbs_path=settings.obsolete_pdbs_path, + release_dates_path=None, + ) + searcher = hmmsearch.Hmmsearch( + binary_path=settings.hmmsearch_binary_path, + hmmbuild_binary_path=settings.hmmbuild_binary_path, + database_path=settings.pdb_seqres_database_path, + ) + return searcher, featurizer + + +@dataclasses.dataclass(frozen=True, slots=True) +class Af2FeatureFinalizationSettings: + """CPU AlphaFold 2 finalization settings and complete template provenance.""" + + output_dir: Path + msa_input_dir: Path + max_template_date: str + template_seqres_database_id: str + template_mmcif_database_id: str + # hmmsearch against PDB seqres, or hhsearch against PDB70 (--use_hhsearch). + # The two find different templates, so which one ran is part of the identity. + template_searcher: str = "hmmsearch" + compress: bool = False + base_metadata: Mapping[str, Any] = dataclasses.field(default_factory=dict) + + +class Af2FeatureFinalizer: + """Turn persisted MSA bundles into AlphaFold 2 feature pickles on CPU.""" + + def __init__( + self, + *, + settings: Af2FeatureFinalizationSettings, + template_searcher: Any, + template_featurizer: Any, + ): + if not isinstance(settings, Af2FeatureFinalizationSettings): + raise TypeError( + "Af2FeatureFinalizer settings must be Af2FeatureFinalizationSettings" + ) + self._settings = settings + self._template_searcher = template_searcher + self._template_featurizer = template_featurizer + + def generate(self, requests: Sequence[FeatureRequest]) -> FeatureBatchResult: + requests = tuple(requests) + self._validate(requests) + self._settings.output_dir.mkdir(parents=True, exist_ok=True) + written = [] + reused = [] + failures = [] + for request in requests: + try: + if request.molecule_type != PROTEIN: + raise ValueError( + f"{request.name!r} is {request.molecule_type}: AlphaFold 2 " + "has no MSA features for anything but protein chains" + ) + payload = read_msa_bundle(self._settings.msa_input_dir, request) + msas = searched_msas_from_payload(payload) + provenance = self._provenance(payload) + cached = self._read_matching_artifact(request, provenance) + if cached is not None: + reused.append(FeatureArtifact(name=request.name, path=cached)) + continue + feature_dict = self._feature_dict(request, af2_msa_inputs(msas)) + path = self._publish(request, feature_dict, provenance) + written.append(FeatureArtifact(name=request.name, path=path)) + except Exception as exc: + failures.append(FeatureFailure(name=request.name, error=str(exc))) + return FeatureBatchResult( + written=tuple(written), reused=tuple(reused), failures=tuple(failures) + ) + + def _validate(self, requests: Sequence[FeatureRequest]) -> None: + _validate_feature_requests(requests) + for field_name in ( + "max_template_date", + "template_seqres_database_id", + "template_mmcif_database_id", + ): + if not str(getattr(self._settings, field_name)).strip(): + raise ValueError(f"{field_name} requires a non-empty value") + if self._settings.template_searcher not in TEMPLATE_SEARCHERS: + raise ValueError( + "template_searcher must be one of " + f"{', '.join(TEMPLATE_SEARCHERS)}, not " + f"{self._settings.template_searcher!r}" + ) + + def _feature_dict( + self, request: FeatureRequest, inputs: Af2MsaInputs + ) -> dict[str, Any]: + from alphafold.data import msa_pairing, parsers, pipeline + + from alphapulldown.objects import add_template_feature_defaults + from alphapulldown.utils.template_reuse import ( + search_templates, + stockholm_from_a3m, + ) + + sequence = request.sequence + features = dict( + pipeline.make_sequence_features( + sequence=sequence, description=request.name, num_res=len(sequence) + ) + ) + + main = pipeline.make_msa_features([parsers.parse_a3m(inputs.main_a3m)]) + main["msa_uniprot_accession_identifiers"] = _offline_accessions( + inputs.main_a3m, rows=main["msa"].shape[0] + ) + features.update(main) + + features.update( + search_templates( + self._template_searcher, + self._template_featurizer, + query_sequence=sequence, + stockholm_msa=stockholm_from_a3m(inputs.template_a3m), + ) + ) + + # The paired alignment is searched separately against UniProt, whose + # headers carry the species AlphaFold 2 pairs chains by. It is not a copy + # of the unpaired features, which is what the remote path makes do with. + paired = pipeline.make_msa_features([parsers.parse_a3m(inputs.paired_a3m)]) + paired["msa_uniprot_accession_identifiers"] = _offline_accessions( + inputs.paired_a3m, rows=paired["msa"].shape[0] + ) + pairable = msa_pairing.MSA_FEATURES + ( + "msa_species_identifiers", + "msa_uniprot_accession_identifiers", + ) + features.update( + {f"{key}_all_seq": value for key, value in paired.items() if key in pairable} + ) + + add_template_feature_defaults(features, sequence) + return features + + def _provenance(self, msa_payload: Mapping[str, Any]) -> dict[str, Any]: + """Everything that decides the pickle's content, for cache reuse.""" + return { + "af2_feature_schema": _AF2_FEATURE_SCHEMA, + "mmseqs2": msa_payload["provenance"], + "af2_templates": self._template_signature(), + } + + def _template_signature(self) -> dict[str, Any]: + # Software versions, not base_metadata's wall-clock date, which would miss + # on every run -- the same choice the AlphaFold 3 finalizer makes. + return { + "max_template_date": self._settings.max_template_date, + "pdb_seqres_database_id": self._settings.template_seqres_database_id, + "mmcif_database_id": self._settings.template_mmcif_database_id, + "template_searcher": self._settings.template_searcher, + "software": dict(self._settings.base_metadata.get("software", {})), + } + + def _read_matching_artifact( + self, request: FeatureRequest, provenance: Mapping[str, Any] + ) -> Path | None: + from alphapulldown.utils.lightweight_pickles import load_lightweight_pickle + + path = self._artifact_path(request.name) + if not path.exists(): + return None + try: + monomer = load_lightweight_pickle(path) + except Exception: + return None + if getattr(monomer, "sequence", None) != request.sequence: + return None + if getattr(monomer, "local_msa_provenance", None) != provenance: + return None + return path + + def _publish( + self, + request: FeatureRequest, + feature_dict: dict[str, Any], + provenance: Mapping[str, Any], + ) -> Path: + from alphapulldown.objects import MonomericObject + + monomer = MonomericObject(request.name, request.sequence) + monomer.feature_dict = feature_dict + monomer.skip_msa = False + # Carried on the object so a later run can tell, from the pickle alone, + # whether it was built from the same search and template settings. + monomer.local_msa_provenance = dict(provenance) + + metadata = copy.deepcopy(dict(self._settings.base_metadata)) + other = metadata.setdefault("other", {}) + # The same keys the AlphaFold 3 finalizer writes, so one reader serves both. + # The search mode, cpu or gpu, is inside the provenance. + other["msa_backend"] = "mmseqs2-gpu" + other["mmseqs2_gpu"] = provenance["mmseqs2"] + other["af2_templates"] = provenance["af2_templates"] + metadata_suffix = ".json.xz" if self._settings.compress else ".json" + _write_atomic( + self._settings.output_dir + / f"{request.name}_feature_metadata_{date.today()}{metadata_suffix}", + json.dumps(metadata).encode("utf-8"), + ) + # The pickle is the output a workflow waits for, so it is published last: + # its existence implies its metadata exists too. + path = self._artifact_path(request.name) + _write_atomic(path, pickle.dumps(monomer)) + return path + + def _artifact_path(self, name: str) -> Path: + suffix = ".pkl.xz" if self._settings.compress else ".pkl" + return self._settings.output_dir / f"{name}{suffix}" + + +def _write_atomic(path: Path, content: bytes) -> None: + """Publish a file whole or not at all, compressed when its name says .xz.""" + descriptor, temporary_name = tempfile.mkstemp( + prefix=f".{path.name}.", suffix=".tmp", dir=path.parent + ) + temporary_path = Path(temporary_name) + try: + with os.fdopen(descriptor, "wb") as raw_handle: + if path.suffix == ".xz": + with lzma.open(raw_handle, "wb") as handle: + handle.write(content) + else: + raw_handle.write(content) + raw_handle.flush() + os.fsync(raw_handle.fileno()) + os.replace(temporary_path, path) + directory_fd = os.open(path.parent, os.O_RDONLY) + try: + os.fsync(directory_fd) + finally: + os.close(directory_fd) + finally: + temporary_path.unlink(missing_ok=True) diff --git a/alphapulldown/feature_batch.py b/alphapulldown/feature_batch.py index 213d71e3..a0d1bf12 100644 --- a/alphapulldown/feature_batch.py +++ b/alphapulldown/feature_batch.py @@ -306,6 +306,26 @@ class SearchedMsas: # the merged alignment is unusable to it unless these boundaries are kept. unpaired_rows: tuple[tuple[str, int], ...] = () + def rows_by_database( + self, + ) -> tuple[tuple[str, str], dict[str, list[tuple[str, str]]]]: + """The query record, and each database's own rows, recovered from the spans.""" + records = _fasta_records(self.unpaired) + if not records: + raise ValueError("MSA bundle has an empty unpaired alignment") + query, hits = records[0], records[1:] + by_database: dict[str, list[tuple[str, str]]] = {} + start = 0 + for name, count in self.unpaired_rows: + by_database[name] = hits[start : start + count] + start += count + if start != len(hits): + raise ValueError( + f"MSA bundle row spans cover {start} rows but the alignment has " + f"{len(hits)} besides the query" + ) + return query, by_database + @dataclasses.dataclass(frozen=True, slots=True) class MsaBatchResult: @@ -619,7 +639,7 @@ def generate(self, requests: Sequence[FeatureRequest]) -> MsaBatchResult: path, payload = cached reused.append(MsaArtifact(name=request.name, path=path)) msa_by_sequence.setdefault( - _request_key(request), _searched_msas_from_payload(payload) + _request_key(request), searched_msas_from_payload(payload) ) sequence_to_requests: dict[tuple[str, str], list[FeatureRequest]] = {} @@ -748,7 +768,7 @@ def _read_matching_msa( # Raises on a bundle whose row spans are missing or do not add up, so a # damaged one is re-searched instead of handed on to a consumer that # would slice it at the wrong rows. - _searched_msas_from_payload(payload) + searched_msas_from_payload(payload) return path, payload except ( KeyError, @@ -1140,44 +1160,7 @@ def _validate(self, requests: Sequence[FeatureRequest]) -> None: raise ValueError(f"{field_name} requires a non-empty value") def _read_msa(self, request: FeatureRequest) -> dict[str, Any]: - path = self._settings.msa_input_dir / f"{request.name}_mmseqs_msa.json" - try: - encoded = path.read_text(encoding="utf-8") - except OSError as exc: - raise RuntimeError(f"Cannot read MMseqs2 MSA bundle {path}: {exc}") from exc - try: - try: - payload = json.loads(encoded) - except (TypeError, ValueError, json.JSONDecodeError) as exc: - raise _InvalidMsaBundle( - f"Cannot parse MMseqs2 MSA bundle {path}: {exc}" - ) from exc - if not isinstance(payload, dict): - raise _InvalidMsaBundle( - f"MMseqs2 MSA bundle {path} is not a JSON object" - ) - if payload.get("sequence") != request.sequence: - raise _InvalidMsaBundle( - f"MMseqs2 MSA bundle sequence does not match {request.name!r}" - ) - if payload.get("moleculeType", PROTEIN) != request.molecule_type: - raise _InvalidMsaBundle( - "MMseqs2 MSA bundle molecule type does not match " - f"{request.name!r}" - ) - if not isinstance(payload.get("provenance"), dict): - raise _InvalidMsaBundle( - f"MMseqs2 MSA bundle lacks provenance for {request.name!r}" - ) - for key in ("unpairedMsa", "pairedMsa"): - if not isinstance(payload.get(key), str): - raise _InvalidMsaBundle( - f"MMseqs2 MSA bundle lacks {key} for {request.name!r}" - ) - return payload - except _InvalidMsaBundle: - path.unlink(missing_ok=True) - raise + return read_msa_bundle(self._settings.msa_input_dir, request) def _read_matching_artifact( self, request: FeatureRequest, msa_payload: Mapping[str, Any] @@ -1493,7 +1476,52 @@ def _merge_a3ms( return text, tuple(contributed) -def _searched_msas_from_payload(payload: Mapping[str, Any]) -> SearchedMsas: +def read_msa_bundle(msa_input_dir: Path, request: FeatureRequest) -> dict[str, Any]: + """Read one request's MSA bundle, deleting it if it is unsafe to use. + + Shared by every finalizer, so each backend refuses the same damaged bundles. + """ + path = msa_input_dir / f"{request.name}_mmseqs_msa.json" + try: + encoded = path.read_text(encoding="utf-8") + except OSError as exc: + raise RuntimeError(f"Cannot read MMseqs2 MSA bundle {path}: {exc}") from exc + try: + try: + payload = json.loads(encoded) + except (TypeError, ValueError, json.JSONDecodeError) as exc: + raise _InvalidMsaBundle( + f"Cannot parse MMseqs2 MSA bundle {path}: {exc}" + ) from exc + if not isinstance(payload, dict): + raise _InvalidMsaBundle( + f"MMseqs2 MSA bundle {path} is not a JSON object" + ) + if payload.get("sequence") != request.sequence: + raise _InvalidMsaBundle( + f"MMseqs2 MSA bundle sequence does not match {request.name!r}" + ) + if payload.get("moleculeType", PROTEIN) != request.molecule_type: + raise _InvalidMsaBundle( + "MMseqs2 MSA bundle molecule type does not match " + f"{request.name!r}" + ) + if not isinstance(payload.get("provenance"), dict): + raise _InvalidMsaBundle( + f"MMseqs2 MSA bundle lacks provenance for {request.name!r}" + ) + for key in ("unpairedMsa", "pairedMsa"): + if not isinstance(payload.get(key), str): + raise _InvalidMsaBundle( + f"MMseqs2 MSA bundle lacks {key} for {request.name!r}" + ) + return payload + except _InvalidMsaBundle: + path.unlink(missing_ok=True) + raise + + +def searched_msas_from_payload(payload: Mapping[str, Any]) -> SearchedMsas: """Read a bundle back, refusing row spans that do not describe its alignment. The spans are what a consumer slices by, so a wrong count does not fail -- it diff --git a/alphapulldown/objects.py b/alphapulldown/objects.py index d9e61b23..40409060 100644 --- a/alphapulldown/objects.py +++ b/alphapulldown/objects.py @@ -44,6 +44,22 @@ def _query_only_stockholm(sequence: str, query_id: str = "query") -> str: ) +def add_template_feature_defaults( + feature_dict: Dict[str, Any], sequence: str +) -> None: + """Fill the two template features native AlphaFold 2 features lack. + + The mmseqs2 path produces ``template_confidence_scores`` and + ``template_release_date``; jackhmmer features do not. Every AlphaFold 2 + feature source adds them here, so pickles from any source carry the same + keys and a multimer built from mixed sources does not fail on a missing one. + """ + if feature_dict.get("template_confidence_scores") is None: + feature_dict["template_confidence_scores"] = np.array([[1] * len(sequence)]) + if feature_dict.get("template_release_date") is None: + feature_dict["template_release_date"] = np.array(["none"]) + + def _ensure_identifier_feature_arrays( feature_dict: Dict[str, np.ndarray], feature_groups: Tuple[Tuple[str, Tuple[str, ...]], ...], @@ -226,16 +242,8 @@ def make_features( fasta_file, self._uniprot_runner, msa_output_dir, use_precomputed_msa ) self.feature_dict.update(pairing_results) - - # Add extra features to make it compatible with pickle features obtaiend from mmseqs2 - template_confidence_scores = self.feature_dict.get('template_confidence_scores', None) - template_release_date = self.feature_dict.get('template_release_date', None) - if template_confidence_scores is None: - self.feature_dict.update( - {'template_confidence_scores': np.array([[1] * len(self.sequence)])} - ) - if template_release_date is None: - self.feature_dict.update({"template_release_date" : np.array(['none'])}) + + add_template_feature_defaults(self.feature_dict, self.sequence) # post processing if (not save_msa) and (not use_precomputed_msa): diff --git a/alphapulldown/scripts/create_individual_features.py b/alphapulldown/scripts/create_individual_features.py index 8d433acd..f1c3f8ac 100644 --- a/alphapulldown/scripts/create_individual_features.py +++ b/alphapulldown/scripts/create_individual_features.py @@ -21,13 +21,15 @@ from colabfold.utils import DEFAULT_API_SERVER # AlphaFold2 imports -from alphafold.data import templates from alphafold.data.pipeline import DataPipeline as AF2DataPipeline -from alphafold.data.tools import hmmsearch, hhsearch # AlphaPulldown helpers from alphapulldown.utils.create_custom_template_db import create_db from alphapulldown.objects import MonomericObject +from alphapulldown.af2_feature_finalizer import ( + Af2TemplateStackSettings, + build_af2_template_stack, +) from alphapulldown.utils.file_handling import ( iter_seqs, parse_csv_file, @@ -395,29 +397,35 @@ def get_af3_feature_metadata(chain_kinds, *, skip_msa, flag_values=None): # =================== AlphaFold 2 Feature Creation =================== +def af2_template_stack_settings(): + """The AF2 template stack as this run's flags describe it, mutating nothing. + + Paths not given explicitly come from --data_dir, the same defaults + create_arguments() would have written into FLAGS. + """ + def path(flag_name, database_key): + explicit = getattr(FLAGS, flag_name) + if explicit: + return explicit + return get_database_path(database_key) if FLAGS.data_dir else None + + return Af2TemplateStackSettings( + template_mmcif_dir=path("template_mmcif_dir", "template_mmcif_dir"), + max_template_date=FLAGS.max_template_date, + kalign_binary_path=FLAGS.kalign_binary_path, + obsolete_pdbs_path=path("obsolete_pdbs_path", "obsolete_pdbs"), + use_hhsearch=FLAGS.use_hhsearch, + hmmsearch_binary_path=FLAGS.hmmsearch_binary_path, + hmmbuild_binary_path=FLAGS.hmmbuild_binary_path, + pdb_seqres_database_path=path("pdb_seqres_database_path", "pdb_seqres"), + hhsearch_binary_path=FLAGS.hhsearch_binary_path, + pdb70_database_path=path("pdb70_database_path", "pdb70"), + ) + + def _create_af2_template_stack(): """Create the AF2 template searcher and featurizer.""" - if FLAGS.use_hhsearch: - template_searcher = hhsearch.HHSearch( - binary_path=FLAGS.hhsearch_binary_path, databases=[FLAGS.pdb70_database_path] - ) - template_featuriser = templates.HhsearchHitFeaturizer( - mmcif_dir=FLAGS.template_mmcif_dir, max_template_date=FLAGS.max_template_date, - max_hits=20, kalign_binary_path=FLAGS.kalign_binary_path, - release_dates_path=None, obsolete_pdbs_path=FLAGS.obsolete_pdbs_path - ) - else: - template_featuriser = templates.HmmsearchHitFeaturizer( - mmcif_dir=FLAGS.template_mmcif_dir, max_template_date=FLAGS.max_template_date, - max_hits=20, kalign_binary_path=FLAGS.kalign_binary_path, - obsolete_pdbs_path=FLAGS.obsolete_pdbs_path, release_dates_path=None - ) - template_searcher = hmmsearch.Hmmsearch( - binary_path=FLAGS.hmmsearch_binary_path, - hmmbuild_binary_path=FLAGS.hmmbuild_binary_path, - database_path=FLAGS.pdb_seqres_database_path - ) - return template_searcher, template_featuriser + return build_af2_template_stack(af2_template_stack_settings()) def create_pipeline_af2(): diff --git a/alphapulldown/scripts/finalize_batch_features.py b/alphapulldown/scripts/finalize_batch_features.py index 6ac0024c..51937d2e 100644 --- a/alphapulldown/scripts/finalize_batch_features.py +++ b/alphapulldown/scripts/finalize_batch_features.py @@ -1,17 +1,27 @@ #!/usr/bin/env python3 -"""CPU-only native AF3 template search and feature finalization stage.""" +"""CPU-only template search and feature finalization for local MMseqs2 bundles. + +Reads the MSA bundles the search stage wrote and publishes standard features for +either backend: AlphaFold 3 input JSON, or AlphaFold 2 MonomericObject pickles. +""" from __future__ import annotations import os -# AF3 imports JAX transitively; this CPU stage must never initialize a GPU. +# AF3 imports JAX transitively, and so does alphapulldown.objects via ColabFold; +# this CPU stage must never initialize a GPU. os.environ["JAX_PLATFORMS"] = "cpu" from pathlib import Path from absl import app, flags, logging +from alphapulldown.af2_feature_finalizer import ( + Af2FeatureFinalizationSettings, + Af2FeatureFinalizer, + build_af2_template_stack, +) from alphapulldown.feature_batch import ( MOLECULE_TYPES, PROTEIN, @@ -24,6 +34,7 @@ define_template_provenance_flags, required_template_flag_names, ) +from alphapulldown.utils import save_meta_data flags.DEFINE_string("msa_input_dir", None, "Directory containing MMseqs2 MSA bundles.") @@ -34,14 +45,86 @@ def main(argv) -> None: del argv - if FLAGS.data_pipeline != "alphafold3": - raise ValueError("MMseqs2 MSA finalization requires --data_pipeline=alphafold3") if FLAGS.keep_msas or FLAGS.skip_msa or FLAGS.path_to_mmt or FLAGS.use_mmseqs2: raise ValueError( "MMseqs2 MSA finalization cannot be combined with --keep_msas, " "--skip_msa, --path_to_mmt, or --use_mmseqs2" ) + if FLAGS.data_pipeline == "alphafold2": + result = _finalize_alphafold2() + backend = "AF2" + else: + result = _finalize_alphafold3() + backend = "AF3" + logging.info( + "%s feature finalization: %d written, %d reused, %d failed", + backend, + len(result.written), + len(result.reused), + len(result.failures), + ) + if result.failures: + detail = ", ".join( + f"{failure.name} ({failure.error})" for failure in result.failures + ) + raise RuntimeError( + f"{backend} feature finalization failed for {len(result.failures)} " + f"chain(s): {detail}" + ) + + +def af2_template_metadata(stack) -> dict: + """Provenance for the resources an AlphaFold 2 finalization actually uses. + + Not the run's whole flag set: the jackhmmer and HHblits binary flags default to + whatever is on PATH, so recording them would claim this MSA came from tools + that never touched it. The MSA's own provenance is the bundle's, added by the + finalizer. Only the template stack, which does run here, is recorded. + """ + used = { + "template_mmcif_dir": stack.template_mmcif_dir, + "obsolete_pdbs_path": stack.obsolete_pdbs_path, + "kalign_binary_path": stack.kalign_binary_path, + "max_template_date": stack.max_template_date, + "data_pipeline": "alphafold2", + } + if stack.use_hhsearch: + used["hhsearch_binary_path"] = stack.hhsearch_binary_path + used["pdb70_database_path"] = stack.pdb70_database_path + else: + used["hmmsearch_binary_path"] = stack.hmmsearch_binary_path + used["hmmbuild_binary_path"] = stack.hmmbuild_binary_path + used["pdb_seqres_database_path"] = stack.pdb_seqres_database_path + return save_meta_data.get_meta_dict(used) + +def _finalize_alphafold2(): + # Explicit settings, as for AlphaFold 3 below: paths come from --data_dir + # without create_arguments() rewriting the global FLAGS. + stack = legacy_features.af2_template_stack_settings() + template_searcher, template_featurizer = build_af2_template_stack(stack) + # Every molecule type the search stage can produce is read, so an RNA chain + # fails here by name, with the reason, rather than as a missing bundle. + requests = feature_requests_from_fastas( + FLAGS.fasta_paths, molecule_types=MOLECULE_TYPES + ) + return Af2FeatureFinalizer( + settings=Af2FeatureFinalizationSettings( + output_dir=Path(FLAGS.output_dir), + msa_input_dir=Path(FLAGS.msa_input_dir), + max_template_date=FLAGS.max_template_date, + template_seqres_database_id=FLAGS.template_seqres_database_id, + template_mmcif_database_id=FLAGS.template_mmcif_database_id, + template_searcher=stack.searcher_name, + compress=FLAGS.compress_features, + base_metadata=af2_template_metadata(stack), + ), + template_searcher=template_searcher, + template_featurizer=template_featurizer, + ).generate(requests) + + +def _finalize_alphafold3(): # No create_arguments() here: it worked by mutating the global FLAGS and the two # calls below then read that mutation back, so this stage depended on call order # across a script boundary. The settings resolve the same paths explicitly. @@ -59,7 +142,7 @@ def main(argv) -> None: skip_msa=True, flag_values=settings.flag_values_with_resolved_paths(FLAGS.flag_values_dict()), ) - result = FeatureFinalizer( + return FeatureFinalizer( settings=FeatureFinalizationSettings( output_dir=Path(FLAGS.output_dir), msa_input_dir=Path(FLAGS.msa_input_dir), @@ -71,19 +154,6 @@ def main(argv) -> None: ), af3_pipeline=pipeline, ).generate(requests) - logging.info( - "AF3 feature finalization: %d written, %d reused, %d failed", - len(result.written), - len(result.reused), - len(result.failures), - ) - if result.failures: - detail = ", ".join( - f"{failure.name} ({failure.error})" for failure in result.failures - ) - raise RuntimeError( - f"AF3 feature finalization failed for {len(result.failures)} chain(s): {detail}" - ) if __name__ == "__main__": diff --git a/test/integration/test_mmseqs2_af2.py b/test/integration/test_mmseqs2_af2.py new file mode 100644 index 00000000..b93b9dfa --- /dev/null +++ b/test/integration/test_mmseqs2_af2.py @@ -0,0 +1,210 @@ +"""Local MMseqs2 to AlphaFold 2 features, end to end, with nothing faked. + +A real MMseqs2 search over a small UniProt-headed database, through the real +``create_batch_msas.py``; then the real ``finalize_batch_features.py +--data_pipeline=alphafold2``, running real hmmsearch against a PDB seqres whose +entry is backed by a real mmCIF (3L4Q, influenza NS1 bound to p85beta). The +pickle it publishes is then loaded and checked for what the two stages exist to +deliver: a real template, recovered insertions, and parseable species. + +Opt-in: needs MMSEQS_INTEGRATION_BINARY and the AlphaFold 2 template tools. +""" + +from __future__ import annotations + +import os +from pathlib import Path +import pickle +import random +import shutil +import subprocess +import sys + +import pytest + +pytestmark = [pytest.mark.integration, pytest.mark.external_tools] + +pytest.importorskip("alphafold.data.pipeline", reason="needs AlphaFold 2") + +TEMPLATES = Path(__file__).resolve().parents[1] / "test_data" / "templates" + +# 3L4Q chain A without its His tag: the NS1 effector domain. +NS1 = ( + "SDEALKMTMASVPASRYLTDMTLEEMSRDWSMLIPKQKVAGPLCIRMDQAIMDKNIILKANFSVIFDRLETLIL" + "LRAFTEEGAIVGEISPLPSLPGHTAEDVKNAVGVLIGGLEWNDNTVRVSETLQRFAWRSSNENGRPPLTPKQ" + "KREMAGTIRSEV" +) +NS1_WITH_TAG = "HHHHHH" + NS1 +P85B = ( + "YQQDQIVKEDSVEAVGAQLKVYHQQYQDKSREYDQLYEEYTRTSQELQMKRTAIEAFNETIKIFEEQGQTQEKSS" + "KEYLERFRREGNEKEMQRILLNSERLKSRIAEIHESRTKLEQELRAQASDNREIDKRMNSLKPDLMQLRKIRDQ" + "YLVWLTQKGARQKKINEWLGI" +) +SPECIES = ("HUMAN", "MOUSE", "CHICK", "PIG", "BOVIN", "RAT") + + +def _mutated(sequence: str, count: int, seed: int) -> str: + rng = random.Random(seed) + residues = list(sequence) + for position in rng.sample(range(len(residues)), count): + residues[position] = "W" if residues[position] != "W" else "F" + return "".join(residues) + + +# The query is an NS1 HOMOLOG, about 90% identical, not NS1 itself. AlphaFold 2 +# rightly discards a template identical to its query -- a DuplicateError it drops +# without so much as a warning -- so a query copied from 3L4Q would find no +# template at all, and that is not the case features exist for. +QUERY = _mutated(NS1, 16, seed=11) + + +def _tool(name: str) -> str: + path = shutil.which(name) or str(Path(sys.executable).parent / name) + if not Path(path).exists(): + pytest.skip(f"{name} is not installed") + return path + + +def _run(*command, env=None): + completed = subprocess.run( + [str(part) for part in command], + capture_output=True, + text=True, + env=env, + timeout=600, + ) + if completed.returncode: + raise AssertionError( + f"{command[0]} failed ({completed.returncode}):\n" + f"{completed.stdout[-3000:]}\n{completed.stderr[-3000:]}" + ) + return completed + + +def _homologs() -> str: + """Query homologs under UniProt headers: substitutions, and one insertion.""" + rng = random.Random(3) + residues = "ACDEFGHIKLMNPQRSTVWY" + records = [] + for index, species in enumerate(SPECIES): + sequence = list(QUERY) + for _ in range(8): + position = rng.randrange(len(sequence)) + sequence[position] = rng.choice(residues) + if index == 0: + # Well inside the domain, so the alignment has to open an insertion. + sequence[60:60] = list("WWWWW") + accession = f"P{index:05d}" + records.append( + f">sp|{accession}|NS1_{species} Non-structural protein 1 " + f"OS=Influenza OX={1000 + index}\n{''.join(sequence)}\n" + ) + return "".join(records) + + +@pytest.fixture +def mmseqs_binary() -> Path: + configured = os.environ.get("MMSEQS_INTEGRATION_BINARY") + if not configured: + pytest.skip("set MMSEQS_INTEGRATION_BINARY to run against real MMseqs2") + binary = Path(configured) + if not binary.is_file(): + pytest.fail(f"MMSEQS_INTEGRATION_BINARY does not exist: {binary}") + return binary + + +def test_local_mmseqs2_to_alphafold2_features_end_to_end(tmp_path, mmseqs_binary): + hmmsearch, hmmbuild, kalign = (_tool(n) for n in ("hmmsearch", "hmmbuild", "kalign")) + env = {**os.environ, "OPENBLAS_NUM_THREADS": "1", "OMP_NUM_THREADS": "1"} + + # A padded MMseqs2 database standing in for all four protein databases. + target_fasta = tmp_path / "homologs.fasta" + target_fasta.write_text(_homologs(), encoding="utf-8") + target_db, padded_db = tmp_path / "homologs", tmp_path / "homologs_gpu" + _run(mmseqs_binary, "createdb", target_fasta, target_db, "--threads", "1") + _run(mmseqs_binary, "makepaddedseqdb", target_db, padded_db, "--threads", "1") + + # A PDB seqres whose NS1 entry is backed by the real 3L4Q mmCIF. + template_root = tmp_path / "pdb" + mmcif_dir = template_root / "mmcif_files" + mmcif_dir.mkdir(parents=True) + shutil.copy(TEMPLATES / "3L4Q.cif", mmcif_dir / "3l4q.cif") + seqres = template_root / "pdb_seqres.txt" + seqres.write_text( + f">3l4q_A mol:protein length:{len(NS1_WITH_TAG)} NS1\n{NS1_WITH_TAG}\n" + f">3l4q_C mol:protein length:{len(P85B)} P85B\n{P85B}\n", + encoding="utf-8", + ) + obsolete = template_root / "obsolete.dat" + obsolete.write_text("", encoding="utf-8") + + query_fasta = tmp_path / "ns1.fasta" + query_fasta.write_text(f">ns1\n{QUERY}\n", encoding="utf-8") + msa_dir = tmp_path / "msas" + database_flags = [ + flag + for name in ("uniref90", "mgnify", "small_bfd", "uniprot") + for flag in ( + f"--mmseqs_{name}_database_path={padded_db}", + f"--mmseqs_{name}_database_id=homologs-v1", + ) + ] + + _run( + sys.executable, "-m", "alphapulldown.scripts.create_batch_msas", + f"--fasta_paths={query_fasta}", + f"--msa_output_dir={msa_dir}", + f"--summary_path={tmp_path / 'summary.json'}", + f"--mmseqs_binary_path={mmseqs_binary}", + f"--mmseqs_temp_dir={tmp_path / 'work'}", + "--mmseqs_batch_max_sequences=4", + "--mmseqs_batch_max_residues=10000", + "--mmseqs_threads=2", + f"--mmseqs_use_gpu={'true' if os.environ.get('MMSEQS_INTEGRATION_GPU') == '1' else 'false'}", + *database_flags, + env=env, + ) + assert (msa_dir / "ns1_mmseqs_msa.json").exists() + + features_dir = tmp_path / "features" + _run( + sys.executable, "-m", "alphapulldown.scripts.finalize_batch_features", + "--data_pipeline=alphafold2", + f"--fasta_paths={query_fasta}", + f"--msa_input_dir={msa_dir}", + f"--output_dir={features_dir}", + f"--data_dir={tmp_path}", + "--max_template_date=2050-01-01", + "--template_seqres_database_id=seqres-3l4q", + "--template_mmcif_database_id=mmcif-3l4q", + f"--pdb_seqres_database_path={seqres}", + f"--template_mmcif_dir={mmcif_dir}", + f"--obsolete_pdbs_path={obsolete}", + f"--hmmsearch_binary_path={hmmsearch}", + f"--hmmbuild_binary_path={hmmbuild}", + f"--kalign_binary_path={kalign}", + env=env, + ) + + with open(features_dir / "ns1.pkl", "rb") as handle: + monomer = pickle.load(handle) + features = monomer.feature_dict + + assert type(monomer).__module__ == "alphapulldown.objects" + assert monomer.sequence == QUERY + + # A real template, found by real hmmsearch from the uniref90 profile. + assert b"3l4q_A" in list(features["template_domain_names"]) + assert features["template_aatype"].shape[1] == len(QUERY) + + # The inserted homolog's five residues reach the deletion matrix. + assert features["deletion_matrix_int"].sum() >= 5 + + # Species parsed from the UniProt headers, for pairing. + species = {value.decode() for value in features["msa_species_identifiers_all_seq"]} + assert set(SPECIES) <= species + + # Provenance records what built it, and not the tools that did not run. + metadata = next(features_dir.glob("ns1_feature_metadata_*.json")).read_text() + assert "jackhmmer" not in metadata and "hhblits" not in metadata + assert '"msa_backend": "mmseqs2-gpu"' in metadata diff --git a/test/unit/test_af2_feature_finalizer.py b/test/unit/test_af2_feature_finalizer.py new file mode 100644 index 00000000..7b937b3a --- /dev/null +++ b/test/unit/test_af2_feature_finalizer.py @@ -0,0 +1,355 @@ +"""AlphaFold 2 features from a local MMseqs2 bundle, through AlphaFold 2's own code. + +Every property asserted here is one that fails silently when wrong: a feature key +another source lacks crashes multimer pairing only when that chain happens to come +first; a template profile built from the merged alignment returns different hits +without complaint; a species lost from a header simply pairs nothing. +""" + +from __future__ import annotations + +import json +from pathlib import Path +import pickle + +import numpy as np +import pytest + +pipeline = pytest.importorskip( + "alphafold.data.pipeline", reason="needs the AlphaFold 2 data pipeline" +) +from alphafold.common import residue_constants # noqa: E402 + +from alphapulldown.af2_feature_finalizer import ( # noqa: E402 + Af2FeatureFinalizationSettings, + Af2FeatureFinalizer, +) +from alphapulldown.feature_batch import PROTEIN, RNA, FeatureRequest # noqa: E402 + + +FIXTURES = Path(__file__).resolve().parents[1] / "test_data" / "features" / "af2_features" + +# Measured on a natively generated (jackhmmer) pickle from the shared feature +# store. Local features must carry every one of these, or a multimer mixing the +# two sources fails on the missing key. +NATIVE_KEYS = { + "aatype", "between_segment_residues", "deletion_matrix_int", + "deletion_matrix_int_all_seq", "domain_name", "msa", "msa_all_seq", + "msa_species_identifiers", "msa_species_identifiers_all_seq", "num_alignments", + "residue_index", "seq_length", "sequence", "template_aatype", + "template_all_atom_masks", "template_all_atom_positions", + "template_confidence_scores", "template_domain_names", "template_release_date", + "template_sequence", "template_sum_probs", +} +ACCESSION_KEYS = { + "msa_uniprot_accession_identifiers", + "msa_uniprot_accession_identifiers_all_seq", +} + +QUERY = "MKTAYIAKQRQISFVKSHFSRQ" + + +class RecordingSearcher: + """Stands in for hmmsearch and remembers the profile it was handed.""" + + input_format = "sto" + output_format = "sto" + + def __init__(self): + self.queries: list[str] = [] + + def query(self, text): + self.queries.append(text) + return "RAW_HITS" + + def get_template_hits(self, output_string, input_sequence): + return [] + + +class NoHitFeaturizer: + """What AlphaFold 2's HmmsearchHitFeaturizer returns when nothing is found.""" + + def get_templates(self, query_sequence, hits): + num_res = len(query_sequence) + + class Result: + features = { + "template_aatype": np.zeros( + (1, num_res, len(residue_constants.restypes_with_x_and_gap)), + np.float32, + ), + "template_all_atom_masks": np.zeros( + (1, num_res, residue_constants.atom_type_num), np.float32 + ), + "template_all_atom_positions": np.zeros( + (1, num_res, residue_constants.atom_type_num, 3), np.float32 + ), + "template_domain_names": np.array([b""], dtype=object), + "template_sequence": np.array([b""], dtype=object), + "template_sum_probs": np.array([0], dtype=np.float32), + } + + return Result() + + +def _a3m(records): + return "".join(f">{description}\n{sequence}\n" for description, sequence in records) + + +def _write_bundle(msa_dir: Path, name: str, sequence: str, *, uniref90, mgnify, + small_bfd, paired) -> None: + msa_dir.mkdir(parents=True, exist_ok=True) + unpaired = [("query", sequence), *uniref90, *mgnify, *small_bfd] + paired_records = [("query", sequence), *paired] + (msa_dir / f"{name}_mmseqs_msa.json").write_text( + json.dumps( + { + "schemaVersion": 3, + "name": name, + "sequence": sequence, + "unpairedMsa": _a3m(unpaired), + "pairedMsa": _a3m(paired_records), + "unpairedDepth": len(unpaired), + "pairedDepth": len(paired_records), + "unpairedDatabaseRows": [ + {"name": "uniref90", "rows": len(uniref90)}, + {"name": "mgnify", "rows": len(mgnify)}, + {"name": "small_bfd", "rows": len(small_bfd)}, + ], + "provenance": {"schema_version": 5, "fixture": name}, + } + ), + encoding="utf-8", + ) + + +def _mutate(sequence: str, position: int, residue: str) -> str: + return sequence[:position] + residue + sequence[position + 1 :] + + +def _insert(sequence: str, position: int, insertion: str) -> str: + return sequence[:position] + insertion + sequence[position:] + + +def _standard_bundle(msa_dir: Path, name: str = "alpha", sequence: str = QUERY): + """Rows named by database, one uniref90 hit with an insertion, UniProt species.""" + _write_bundle( + msa_dir, + name, + sequence, + uniref90=[ + ("UniRef90_U1 uniref hit", _mutate(sequence, 3, "W")), + # A three-residue insertion before position 5 -- lowercase, as stitched. + # It also carries its own substitution: a row whose match columns equal + # the query's is a duplicate of it, and AlphaFold 2 drops it as one. + ("UniRef90_U2 inserted", _insert(_mutate(sequence, 11, "W"), 5, "ggg")), + ], + mgnify=[("MGYP000000001", _mutate(sequence, 7, "W"))], + small_bfd=[("BFD_B1", _mutate(sequence, 9, "W"))], + paired=[ + ("sp|P12345|KIN1_HUMAN kinase OS=Homo sapiens OX=9606", _mutate(sequence, 2, "V")), + ("tr|Q67890|Q67890_MOUSE kinase OS=Mus musculus OX=10090", _mutate(sequence, 4, "V")), + ], + ) + + +def _finalizer(tmp_path: Path, **overrides): + settings = dict( + output_dir=tmp_path / "features", + msa_input_dir=tmp_path / "msas", + max_template_date="2050-01-01", + template_seqres_database_id="pdb-seqres-2050", + template_mmcif_database_id="mmcif-2050", + ) + settings.update(overrides) + searcher = RecordingSearcher() + finalizer = Af2FeatureFinalizer( + settings=Af2FeatureFinalizationSettings(**settings), + template_searcher=searcher, + template_featurizer=NoHitFeaturizer(), + ) + return finalizer, searcher + + +def _features(tmp_path: Path, name: str = "alpha") -> dict: + with open(tmp_path / "features" / f"{name}.pkl", "rb") as handle: + return pickle.load(handle).feature_dict + + +def _generate(tmp_path, name="alpha", sequence=QUERY, **overrides): + finalizer, searcher = _finalizer(tmp_path, **overrides) + result = finalizer.generate([FeatureRequest(name=name, sequence=sequence)]) + assert result.failures == (), result.failures + return result, searcher + + +def test_features_carry_the_native_key_set_plus_accession_identifiers(tmp_path): + _standard_bundle(tmp_path / "msas") + _generate(tmp_path) + assert set(_features(tmp_path)) == NATIVE_KEYS | ACCESSION_KEYS + + +def test_insertions_reach_the_deletion_matrix(tmp_path): + """The point of recovering insertions: native features have them, and until + now every local MMseqs2 alignment produced an all-zero deletion matrix.""" + _standard_bundle(tmp_path / "msas") + _generate(tmp_path) + features = _features(tmp_path) + + deletions = features["deletion_matrix_int"] + assert deletions.shape == features["msa"].shape + assert deletions.sum() == 3, "three inserted residues, counted once" + # Recorded against the residue that follows the insertion. + row = int(np.nonzero(deletions.sum(axis=1))[0][0]) + assert deletions[row, 5] == 3 + + +def test_rows_follow_alphafold2s_merge_order(tmp_path): + _standard_bundle(tmp_path / "msas") + _generate(tmp_path) + msa = _features(tmp_path)["msa"] + mutated_at = [int(np.nonzero(row != msa[0])[0][0]) if (row != msa[0]).any() else None + for row in msa] + # query, uniref90 (3, 11), then BFD (9) before MGnify (7), as AlphaFold 2 merges. + assert mutated_at == [None, 3, 11, 9, 7] + + +def test_templates_are_searched_from_uniref90_alone(tmp_path): + _standard_bundle(tmp_path / "msas") + _, searcher = _generate(tmp_path) + [profile] = searcher.queries + assert "UniRef90_U1" in profile + assert "MGYP000000001" not in profile and "BFD_B1" not in profile + + +def test_pairing_features_come_from_uniprot_with_parsed_species(tmp_path): + _standard_bundle(tmp_path / "msas") + _generate(tmp_path) + features = _features(tmp_path) + + assert list(features["msa_species_identifiers_all_seq"]) == [b"", b"HUMAN", b"MOUSE"] + assert list(features["msa_uniprot_accession_identifiers_all_seq"]) == [ + b"", b"P12345", b"Q67890", + ] + # Not a copy of the unpaired features, which is what the remote path uses. + assert features["msa_all_seq"].shape[0] == 3 + assert features["msa"].shape[0] == 5 + + +def test_no_network_is_ever_touched(tmp_path, monkeypatch): + """A batch of thousands of chains must not start calling UniProt REST.""" + import urllib.request + + def refuse(*args, **kwargs): + raise AssertionError("the local AlphaFold 2 path queried the network") + + monkeypatch.setattr(urllib.request, "urlopen", refuse) + _write_bundle( + tmp_path / "msas", + "alpha", + QUERY, + uniref90=[("UniRef90_A0A0A0A0A0 no species in this header", _mutate(QUERY, 3, "W"))], + mgnify=[], + small_bfd=[], + # A bare accession: exactly the case the shared helper would look up. + paired=[("P12345", _mutate(QUERY, 2, "V"))], + ) + _generate(tmp_path) + + +def test_published_pickle_is_a_monomeric_object_and_is_reused(tmp_path): + from alphapulldown.objects import MonomericObject + + _standard_bundle(tmp_path / "msas") + first, searcher = _generate(tmp_path) + assert [artifact.name for artifact in first.written] == ["alpha"] + with open(tmp_path / "features" / "alpha.pkl", "rb") as handle: + monomer = pickle.load(handle) + assert isinstance(monomer, MonomericObject) + assert monomer.sequence == QUERY and monomer.skip_msa is False + assert list((tmp_path / "features").glob("alpha_feature_metadata_*.json")) + + again, searcher_again = _generate(tmp_path) + assert [artifact.name for artifact in again.reused] == ["alpha"] + assert searcher_again.queries == [], "a reused artifact must not search again" + + +def test_changed_template_settings_are_not_served_from_cache(tmp_path): + _standard_bundle(tmp_path / "msas") + _generate(tmp_path) + moved, _ = _generate(tmp_path, max_template_date="2020-01-01") + assert [artifact.name for artifact in moved.written] == ["alpha"] + + +def test_compressed_output_round_trips(tmp_path): + import lzma + + _standard_bundle(tmp_path / "msas") + _generate(tmp_path, compress=True) + with lzma.open(tmp_path / "features" / "alpha.pkl.xz", "rb") as handle: + assert pickle.load(handle).sequence == QUERY + + +def test_rna_is_refused_by_name(tmp_path): + finalizer, _ = _finalizer(tmp_path) + result = finalizer.generate( + [FeatureRequest(name="trna", sequence="ACGU", molecule_type=RNA)] + ) + assert [failure.name for failure in result.failures] == ["trna"] + assert "protein" in result.failures[0].error + + +def _local_monomer(tmp_path: Path, name: str, sequence: str): + _standard_bundle(tmp_path / "msas", name, sequence) + _generate(tmp_path, name=name, sequence=sequence) + with open(tmp_path / "features" / f"{name}.pkl", "rb") as handle: + return pickle.load(handle) + + +def _native_like_monomer(): + """An older pickle with 21 keys and no accession identifiers at all.""" + with open(FIXTURES / "protein" / "P61626.pkl", "rb") as handle: + return pickle.load(handle) + + +@pytest.mark.parametrize("local_first", (True, False)) +def test_local_chain_pairs_with_a_pickle_from_another_source(tmp_path, local_first): + """AlphaFold 2 pairing takes its key set from the FIRST chain and indexes every + other chain with it, so an extra key crashes only in one order (issue #619). + Both orders, through the real pairing code.""" + from alphapulldown.objects import MultimericObject + + local = _local_monomer(tmp_path, "alpha", QUERY) + native = _native_like_monomer() + chains = [local, native] if local_first else [native, local] + + merged = MultimericObject(interactors=chains, pair_msa=True).feature_dict + + total = len(local.sequence) + len(native.sequence) + assert merged["aatype"].shape == (total,) + assert merged["msa"].shape[1] == total + + +def test_two_local_chains_pair_the_species_they_share(tmp_path): + """Which rows pair, not merely that pairing ran: HUMAN and MOUSE occur in both + chains' UniProt alignments, so those rows line up in the paired block.""" + from alphapulldown.objects import MultimericObject + + first = _local_monomer(tmp_path, "alpha", QUERY) + second_sequence = _mutate(QUERY, 12, "L") + second = _local_monomer(tmp_path, "beta", second_sequence) + + merged = MultimericObject(interactors=[first, second], pair_msa=True).feature_dict + + # The merged multimer MSA is in the model's residue order, not HHblits'. + to_id = residue_constants.restype_order_with_x + human_row = [to_id[r] for r in _mutate(QUERY, 2, "V") + _mutate(second_sequence, 2, "V")] + mouse_row = [to_id[r] for r in _mutate(QUERY, 4, "V") + _mutate(second_sequence, 4, "V")] + # An unpaired row carries one chain's residues and gaps across the other, so + # both chains' hits can only sit on one row if pairing put them there. + rows = [list(row) for row in merged["msa"]] + assert human_row in rows, "the HUMAN hits of both chains must share one row" + assert mouse_row in rows, "the MOUSE hits of both chains must share one row" + # And a hit present in only one chain's alignment is never paired. + unpaired_hit_a = [to_id[r] for r in _mutate(QUERY, 3, "W") + second_sequence] + assert unpaired_hit_a not in rows diff --git a/test/unit/test_af2_msa_inputs.py b/test/unit/test_af2_msa_inputs.py new file mode 100644 index 00000000..0e4d9454 --- /dev/null +++ b/test/unit/test_af2_msa_inputs.py @@ -0,0 +1,100 @@ +"""Cutting an MSA bundle into the alignments AlphaFold 2 builds features from. + +No AlphaFold import: this is string slicing, and it has to be right in every +environment -- a wrong cut does not fail, it hands AlphaFold 2 another database's +rows or a template profile built from the wrong alignment. +""" + +from __future__ import annotations + +import pytest + +from alphapulldown import af2_feature_finalizer +from alphapulldown.af2_feature_finalizer import af2_msa_inputs +from alphapulldown.feature_batch import SearchedMsas + + +QUERY = "MKTAYI" + + +def _msas(uniref90=2, mgnify=2, small_bfd=2, paired=3) -> SearchedMsas: + """Distinguishable rows: U/M/B for each database, P for UniProt.""" + + def rows(prefix, count): + return [(f"{prefix}{index}", f"{prefix}KTAYI") for index in range(count)] + + unpaired = [("query", QUERY), *rows("U", uniref90), *rows("M", mgnify)] + unpaired += rows("B", small_bfd) + return SearchedMsas( + unpaired="".join(f">{d}\n{s}\n" for d, s in unpaired), + paired="".join( + f">{d}\n{s}\n" for d, s in [("query", QUERY), *rows("P", paired)] + ), + unpaired_rows=( + ("uniref90", uniref90), + ("mgnify", mgnify), + ("small_bfd", small_bfd), + ), + ) + + +def _names(a3m: str) -> list[str]: + return [line[1:] for line in a3m.splitlines() if line.startswith(">")] + + +def test_main_alignment_follows_alphafold2_merge_order(): + # The bundle merges uniref90, mgnify, small_bfd; AlphaFold 2 merges uniref90, + # BFD, MGnify (pipeline.py:265). Order decides what its MSA sampling sees first. + inputs = af2_msa_inputs(_msas()) + assert _names(inputs.main_a3m) == ["query", "U0", "U1", "B0", "B1", "M0", "M1"] + + +def test_templates_come_from_uniref90_alone(): + inputs = af2_msa_inputs(_msas()) + assert _names(inputs.template_a3m) == ["query", "U0", "U1"] + + +def test_caps_count_the_query_row_as_alphafold2_does(monkeypatch): + # jackhmmer's max_sto_sequences stops at that many sequence NAMES, query first, + # so a cap of 3 means the query plus two hits. + monkeypatch.setattr( + af2_feature_finalizer, "AF2_MAX_SEQUENCES", {"uniref90": 3, "mgnify": 2} + ) + inputs = af2_msa_inputs(_msas(uniref90=5, mgnify=5, small_bfd=5)) + + assert _names(inputs.template_a3m) == ["query", "U0", "U1"] + assert _names(inputs.main_a3m) == [ + "query", "U0", "U1", "B0", "B1", "B2", "B3", "B4", "M0", + ] + + +def test_paired_alignment_is_uniprot_truncated_like_all_seq_msa_features(monkeypatch): + monkeypatch.setattr(af2_feature_finalizer, "PAIRED_MAX_SEQUENCES", 3) + inputs = af2_msa_inputs(_msas(paired=10)) + assert _names(inputs.paired_a3m) == ["query", "P0", "P1"] + + +def test_real_defaults_are_alphafold2s(): + assert af2_feature_finalizer.AF2_MAX_SEQUENCES == { + "uniref90": 10_000, + "mgnify": 501, + } + assert af2_feature_finalizer.PAIRED_MAX_SEQUENCES == 50_000 + + +def test_a_bundle_without_row_spans_is_refused(): + """Without spans there is no uniref90 to build templates from -- and no way to + fake one, since the merged alignment has lost the boundaries.""" + msas = _msas() + spanless = SearchedMsas(unpaired=msas.unpaired, paired=msas.paired) + with pytest.raises(ValueError): + af2_msa_inputs(spanless) + + +def test_a_bundle_with_no_paired_alignment_is_refused(): + msas = _msas() + unpaired_only = SearchedMsas( + unpaired=msas.unpaired, paired="", unpaired_rows=msas.unpaired_rows + ) + with pytest.raises(ValueError, match="paired"): + af2_msa_inputs(unpaired_only) From a6d0716a0f9048fabeb3732aa25a1074e61771da Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 09:42:44 +0200 Subject: [PATCH 04/17] test: assemble local AlphaFold 2 chains as a homomer, unpaired, and chopped Covers the multimer paths the heteromer test does not: identical entities merged into a dense MSA, pair_msa=False block-diagonalising instead of pairing, and a chopped local chain after a full one -- issue #619's order -- which needs the accession identifiers carried through the slice, row-aligned. Co-Authored-By: Claude Opus 5 (1M context) --- test/unit/test_af2_feature_finalizer.py | 54 +++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/unit/test_af2_feature_finalizer.py b/test/unit/test_af2_feature_finalizer.py index 7b937b3a..dcf0e60e 100644 --- a/test/unit/test_af2_feature_finalizer.py +++ b/test/unit/test_af2_feature_finalizer.py @@ -353,3 +353,57 @@ def test_two_local_chains_pair_the_species_they_share(tmp_path): # And a hit present in only one chain's alignment is never paired. unpaired_hit_a = [to_id[r] for r in _mutate(QUERY, 3, "W") + second_sequence] assert unpaired_hit_a not in rows + + +def test_a_homomer_of_a_local_chain_assembles(tmp_path): + """Two copies of one chain: AF2 merges identical entities into a dense MSA + instead of pairing them, a different code path from the heteromer.""" + from alphapulldown.objects import MultimericObject + + first = _local_monomer(tmp_path, "alpha", QUERY) + with open(tmp_path / "features" / "alpha.pkl", "rb") as handle: + second = pickle.load(handle) + + merged = MultimericObject(interactors=[first, second], pair_msa=True).feature_dict + + assert merged["aatype"].shape == (2 * len(QUERY),) + assert merged["msa"].shape[1] == 2 * len(QUERY) + + +def test_local_chains_assemble_without_pairing(tmp_path): + """pair_msa=False skips species pairing and block-diagonalises the MSAs.""" + from alphapulldown.objects import MultimericObject + + first = _local_monomer(tmp_path, "alpha", QUERY) + second = _local_monomer(tmp_path, "beta", _mutate(QUERY, 12, "L")) + + merged = MultimericObject(interactors=[first, second], pair_msa=False).feature_dict + + to_id = residue_constants.restype_order_with_x + # Unpaired, a HUMAN hit shares a row with no other chain's residues. + human_row = [to_id[r] for r in _mutate(QUERY, 2, "V") + _mutate(QUERY, 2, "V")] + assert human_row not in [list(row) for row in merged["msa"]] + assert merged["msa"].shape[1] == 2 * len(QUERY) + + +def test_a_chopped_local_chain_pairs_with_a_full_one(tmp_path): + """Issue #619's shape: a full chain first, a chopped chain second. The chopped + chain must keep the accession identifiers, row-aligned, or pairing crashes.""" + from alphapulldown.objects import ChoppedObject, MultimericObject + + full = _local_monomer(tmp_path, "alpha", QUERY) + source = _local_monomer(tmp_path, "beta", _mutate(QUERY, 12, "L")) + region = (3, 15) + chopped = ChoppedObject( + source.description, source.sequence, source.feature_dict, [region] + ) + chopped.prepare_final_sliced_feature_dict() + assert ( + chopped.feature_dict["msa_uniprot_accession_identifiers_all_seq"].shape[0] + == chopped.feature_dict["msa_all_seq"].shape[0] + ) + + merged = MultimericObject(interactors=[full, chopped], pair_msa=True).feature_dict + + region_length = region[1] - region[0] + 1 + assert merged["aatype"].shape == (len(QUERY) + region_length,) From 5933582bef84c151f597222e7f1c070ec2a2bbb4 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 09:43:40 +0200 Subject: [PATCH 05/17] docs: local MMseqs2 features now serve AlphaFold 2 as well Both READMEs said AlphaFold 2 feature generation was untouched by the local MMseqs2 path; it now has a finalizer. Document how to run it, what it reproduces from native AlphaFold 2, and where it differs: the reduced_dbs recipe, caps after deduplication, a template profile without insert columns, accessions filled in. Also say that alignments now keep their insertions and that earlier bundles are searched again, and that AlphaFold 2 features are not yet benchmarked. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 28 ++++++++++++++++------- docs/mmseqs2_rna.md | 55 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6dbf591f..1426ec7c 100644 --- a/README.md +++ b/README.md @@ -677,16 +677,17 @@ batch_max_tokens: 0 # optional cap on summed residues per batch (0 = no cap) -### Batched local MMseqs2-GPU features (AlphaFold 3) +### Batched local MMseqs2 features (AlphaFold 2 and 3)
-Faster AlphaFold 3 MSAs using local MMseqs2 instead of jackhmmer/HHblits +Faster MSAs using local MMseqs2 instead of jackhmmer/HHblits -Off by default. Proteins are split into bounded GPU shards searched with MMseqs2, and a -separate CPU stage runs AlphaFold 3's own template search and writes one standard AF3 -JSON per chain — so template work can use CPU and big-memory partitions in parallel. -AlphaFold 2 feature generation and the remote `--use_mmseqs2` path are unchanged. RNA -chains are supported once the RNA databases are configured. +Off by default. Proteins are split into bounded shards searched with MMseqs2, on GPU or +CPU, and a separate CPU stage turns each chain's alignment into standard features: an +AF3 JSON, or an AF2 `MonomericObject` pickle with `--data_pipeline alphafold2`. The +search is shared, so template work can use CPU and big-memory partitions in parallel. +The remote `--use_mmseqs2` path is unchanged. RNA chains are supported for AlphaFold 3 +once the RNA databases are configured. ```yaml mmseqs2_features: @@ -708,7 +709,18 @@ proteins it was ~90% of jackhmmer's unpaired depth overall, but only 54–68% on shallowest families. Whether that costs accuracy is untested, so treat it as opt-in and spot-check your own targets. -Databases, RNA, tuning, caching and caveats: [docs/mmseqs2_rna.md](docs/mmseqs2_rna.md). +**For AlphaFold 2 this is the `reduced_dbs` recipe** — UniRef90, MGnify, small BFD and +UniProt, with no BFD/UniRef30 HHblits arm — built the way native AF2 builds features: +its per-database caps and merge order, templates searched from UniRef90 alone, and +species pairing from an independent UniProt search. The pickles carry the same feature +keys as native ones. They have not been benchmarked against native AF2 features yet. + +Alignments now keep their insertions. MSA bundles written before this change carried +none, so AlphaFold saw an all-zero deletion matrix; they are searched again rather than +reused. + +Databases, RNA, AlphaFold 2, tuning, caching and caveats: +[docs/mmseqs2_rna.md](docs/mmseqs2_rna.md).
diff --git a/docs/mmseqs2_rna.md b/docs/mmseqs2_rna.md index 94f74c85..7378aad0 100644 --- a/docs/mmseqs2_rna.md +++ b/docs/mmseqs2_rna.md @@ -1,9 +1,10 @@ -# Local MMseqs2 features (AlphaFold 3) +# Local MMseqs2 features (AlphaFold 2 and 3) An alternative to the per-protein jackhmmer/HHblits MSA search: proteins are split into -bounded shards searched with MMseqs2, and a separate CPU stage runs AlphaFold 3's own -template search and writes one standard AF3 JSON per chain. Off by default. Existing -AlphaFold 2 feature generation and the remote `--use_mmseqs2` path are untouched. +bounded shards searched with MMseqs2, and a separate CPU stage turns each chain's +alignment into standard features — an AF3 JSON with AlphaFold 3's own template search, +or an AF2 `MonomericObject` pickle; see [AlphaFold 2](#alphafold-2) below. Off by +default. Native feature generation and the remote `--use_mmseqs2` path are untouched. RNA chains can use the same path once the RNA databases are configured; see [RNA chains](#rna-chains) below. @@ -131,6 +132,52 @@ Useful flags: `--mmseqs_rna_e_value` (default `1e-3`) and `--mmseqs__max_sequences` (default `10000` per RNA database), both matching AlphaFold 3's own settings. +## AlphaFold 2 + +The search is the same; only finalization differs. Pass `--data_pipeline alphafold2` to +`finalize_batch_features.py` and it writes `.pkl` (or `.pkl.xz` with +`--compress_features`), the pickle the AlphaFold 2 backend reads: + +```bash +python -m alphapulldown.scripts.finalize_batch_features \ + --data_pipeline alphafold2 --fasta_paths complex.fasta \ + --msa_input_dir msas/ --output_dir features/ --data_dir /db/alphafold2 \ + --max_template_date 2026-08-01 \ + --template_seqres_database_id pdb-seqres-2026-08 --template_mmcif_database_id pdb-mmcif-2026-08 +``` + +Templates come from the AlphaFold 2 database tree under `--data_dir` (`pdb_seqres`, +`pdb_mmcif`), searched with hmmsearch, or with hhsearch against PDB70 under +`--use_hhsearch`. The MSA databases are the MMseqs2 ones the search stage used. + +The features are built the way native AlphaFold 2 builds them from jackhmmer: + +- uniref90 capped at 10 000 rows and MGnify at 501, counting the query as AlphaFold 2 + does; small BFD uncapped +- merged in AlphaFold 2's order, UniRef90, BFD, MGnify — row order matters, since it + samples its MSA from the top +- templates searched from UniRef90 **alone**, never from the merged alignment; the + bundle records which rows each database contributed so this is possible +- pairing features (`*_all_seq`) from the separate UniProt search, whose headers carry + the species AlphaFold 2 pairs chains by + +What differs, and why: + +- **The recipe is `reduced_dbs`.** There is no BFD/UniRef30 HHblits arm, so compare + against `--db_preset reduced_dbs`, not `full_dbs`. +- **Caps apply after cross-database deduplication**, where native AlphaFold 2 caps raw + hits first. This only affects rows two databases both found. +- **The template profile has no insert columns.** A3M insertions are per row and not + aligned to each other, so they cannot be turned back into Stockholm columns; the match + columns, which decide the profile's states, are the same. +- **Accession identifiers are filled in** from the UniProt headers, where native + features leave them empty. Nothing on this path queries UniProt over the network. + +The pickles carry the same feature keys as native ones plus those two accession arrays, +and assemble into multimers alongside pickles from other sources. RNA and DNA chains are +refused: AlphaFold 2 has no MSA features for them. These features have not yet been +benchmarked against native AlphaFold 2 features. + ## The binary Both maintained prediction images bundle the same pinned MMseqs2-GPU build at From 223e9b1a8ced52e8c09ba91df817388d93288068 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 10:39:59 +0200 Subject: [PATCH 06/17] test: edge cases for local MMseqs2 AlphaFold 2 features, end to end Four separate MMseqs2 databases for UniRef90, MGnify, small BFD and UniProt, one real pass through both CLIs, nothing faked. Covers the cases that fail silently: 600 MGnify hits against AlphaFold 2's 501 cap (it bites: exactly 551 rows), an orphan with no hits anywhere, a chain with no template, a homolog that finds the real 3L4Q template, X residues, one sequence under two names, UniProt hits whose headers carry no species, and a 20-residue peptide -- all with the same keys. build_edge_case_features is importable, so the same pickles can be written somewhere durable and folded on a GPU. Co-Authored-By: Claude Opus 5 (1M context) --- .../test_mmseqs2_af2_edge_cases.py | 288 ++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 test/integration/test_mmseqs2_af2_edge_cases.py diff --git a/test/integration/test_mmseqs2_af2_edge_cases.py b/test/integration/test_mmseqs2_af2_edge_cases.py new file mode 100644 index 00000000..c4b13d6d --- /dev/null +++ b/test/integration/test_mmseqs2_af2_edge_cases.py @@ -0,0 +1,288 @@ +"""Edge cases for local MMseqs2 AlphaFold 2 features, end to end, nothing faked. + +Four separate MMseqs2 databases stand in for UniRef90, MGnify, small BFD and +UniProt, so every stage and every cap is exercised on its own database. One real +pass through ``create_batch_msas.py`` and ``finalize_batch_features.py +--data_pipeline=alphafold2`` covers all the cases at once, as a workflow shard +would; each test then checks one case's pickle. + +The cases are the ones that fail silently when wrong: a cap that never bites, an +orphan chain whose empty alignment breaks a later stage, a template search that +finds nothing, residues the pipeline does not know, headers with no species. + +``build_edge_case_features`` is importable, so the same features can be written +somewhere durable and folded on a GPU. + +Opt-in: needs MMSEQS_INTEGRATION_BINARY and the AlphaFold 2 template tools. +""" + +from __future__ import annotations + +import os +from pathlib import Path +import pickle +import random +import shutil +import subprocess +import sys + +import numpy as np +import pytest + +pytestmark = [pytest.mark.integration, pytest.mark.external_tools] + +TEMPLATES = Path(__file__).resolve().parents[1] / "test_data" / "templates" +RESIDUES = "ACDEFGHIKLMNPQRSTVWY" + +# 3L4Q chain A, NS1 effector domain, His tag removed. +NS1 = ( + "SDEALKMTMASVPASRYLTDMTLEEMSRDWSMLIPKQKVAGPLCIRMDQAIMDKNIILKANFSVIFDRLETLIL" + "LRAFTEEGAIVGEISPLPSLPGHTAEDVKNAVGVLIGGLEWNDNTVRVSETLQRFAWRSSNENGRPPLTPKQ" + "KREMAGTIRSEV" +) +MGNIFY_HITS = 600 # past AlphaFold 2's 501 cap, which counts the query +AF2_MGNIFY_CAP = 501 +SPECIES = ("HUMAN", "MOUSE", "RAT", "BOVIN", "PIG", "CHICK", "DANRE", "XENLA") + + +def _random_protein(rng: random.Random, length: int) -> str: + return "".join(rng.choice(RESIDUES) for _ in range(length)) + + +def _homolog(rng: random.Random, sequence: str, fraction: float = 0.15) -> str: + """About 85% identical: found easily, never mistaken for the query itself.""" + residues = list(sequence) + for position in rng.sample(range(len(residues)), max(1, int(len(residues) * fraction))): + residues[position] = rng.choice(RESIDUES.replace(residues[position], "")) + return "".join(residues) + + +def _mutated(sequence: str, count: int, seed: int) -> str: + rng = random.Random(seed) + residues = list(sequence) + for position in rng.sample(range(len(residues)), count): + residues[position] = "W" if residues[position] != "W" else "F" + return "".join(residues) + + +def _cases(): + """Query sequences, each unrelated to the others, and where their hits live.""" + rng = random.Random(20260911) + deep = _random_protein(rng, 120) + x_query = list(_random_protein(rng, 110)) + for position in (10, 55, 90): + x_query[position] = "X" + return { + "deep": deep, + "deep_copy": deep, # same sequence, second name + "shallow": _random_protein(rng, 100), + "orphan": _random_protein(rng, 90), + "notemplate": _random_protein(rng, 130), + "templated": _mutated(NS1, 16, seed=11), # NS1 homolog: 3L4Q is a template + "xresidues": "".join(x_query), + "nospecies": _random_protein(rng, 115), + "peptide": _random_protein(rng, 20), + } + + +def _databases(cases): + """FASTA text per database: which hits each case gets, and where.""" + rng = random.Random(7) + uniref90, mgnify, small_bfd, uniprot = [], [], [], [] + + def uniref(name, sequence, count): + for index in range(count): + uniref90.append((f"UniRef90_U{name}{index:04d} {name} homolog", + _homolog(rng, sequence))) + + def uniprot_hits(name, sequence, count, *, with_species=True): + for index in range(count): + accession = f"Q{abs(hash((name, index))) % 10**5:05d}" + header = ( + f"sp|{accession}|{name.upper()[:5]}_{SPECIES[index % len(SPECIES)]} " + f"{name} OS=Organism OX={9000 + index}" + if with_species + # A UniParc-style header: no species anywhere in it. + else f"UPI{index:010d} {name} unassigned" + ) + uniprot.append((header, _homolog(rng, sequence))) + + uniref("deep", cases["deep"], 30) + for index in range(MGNIFY_HITS): + mgnify.append((f"MGYP{index:012d}", _homolog(rng, cases["deep"]))) + for index in range(20): + small_bfd.append((f"BFD_deep_{index:04d}", _homolog(rng, cases["deep"]))) + uniprot_hits("deep", cases["deep"], 8) + + uniref("shallow", cases["shallow"], 1) + uniref("notemplate", cases["notemplate"], 12) + uniprot_hits("notemplate", cases["notemplate"], 4) + uniref("templated", cases["templated"], 12) + uniprot_hits("templated", cases["templated"], 6) + uniref("xresidues", cases["xresidues"], 10) + uniprot_hits("xresidues", cases["xresidues"], 3) + uniref("nospecies", cases["nospecies"], 6) + uniprot_hits("nospecies", cases["nospecies"], 5, with_species=False) + uniref("peptide", cases["peptide"], 3) + # "orphan" gets nothing, anywhere. + return {"uniref90": uniref90, "mgnify": mgnify, "small_bfd": small_bfd, + "uniprot": uniprot} + + +def _run(*command, env=None): + completed = subprocess.run( + [str(part) for part in command], capture_output=True, text=True, env=env, + timeout=1200, + ) + if completed.returncode: + raise AssertionError( + f"{command[:4]} failed ({completed.returncode}):\n" + f"{completed.stdout[-3000:]}\n{completed.stderr[-4000:]}" + ) + return completed + + +def build_edge_case_features(workdir: Path, mmseqs: Path, *, tools: dict, python=None, + use_gpu: bool = False) -> dict[str, Path]: + """Build every case's AlphaFold 2 pickle through the real CLIs; return the paths.""" + python = python or sys.executable + env = {**os.environ, "OPENBLAS_NUM_THREADS": "1", "OMP_NUM_THREADS": "1"} + cases = _cases() + workdir.mkdir(parents=True, exist_ok=True) + + database_flags = [] + for name, records in _databases(cases).items(): + fasta = workdir / f"{name}.fasta" + fasta.write_text("".join(f">{h}\n{s}\n" for h, s in records), encoding="utf-8") + plain, padded = workdir / f"{name}_db", workdir / f"{name}_gpu" + _run(mmseqs, "createdb", fasta, plain, "--threads", "2") + _run(mmseqs, "makepaddedseqdb", plain, padded, "--threads", "2") + database_flags += [f"--mmseqs_{name}_database_path={padded}", + f"--mmseqs_{name}_database_id={name}-edge-v1", + # High enough that AlphaFold 2's own cap is what bites. + f"--mmseqs_{name}_max_sequences=2000"] + + template_root = workdir / "pdb" + mmcif_dir = template_root / "mmcif_files" + mmcif_dir.mkdir(parents=True, exist_ok=True) + shutil.copy(TEMPLATES / "3L4Q.cif", mmcif_dir / "3l4q.cif") + seqres = template_root / "pdb_seqres.txt" + seqres.write_text(f">3l4q_A mol:protein length:{len(NS1) + 6} NS1\nHHHHHH{NS1}\n", + encoding="utf-8") + (template_root / "obsolete.dat").write_text("", encoding="utf-8") + + queries = workdir / "queries.fasta" + queries.write_text("".join(f">{n}\n{s}\n" for n, s in cases.items()), encoding="utf-8") + msa_dir, features_dir = workdir / "msas", workdir / "features" + + _run(python, "-m", "alphapulldown.scripts.create_batch_msas", + f"--fasta_paths={queries}", f"--msa_output_dir={msa_dir}", + f"--summary_path={workdir / 'summary.json'}", + f"--mmseqs_binary_path={mmseqs}", f"--mmseqs_temp_dir={workdir / 'work'}", + "--mmseqs_batch_max_sequences=32", "--mmseqs_batch_max_residues=100000", + "--mmseqs_threads=2", f"--mmseqs_use_gpu={'true' if use_gpu else 'false'}", + *database_flags, env=env) + _run(python, "-m", "alphapulldown.scripts.finalize_batch_features", + "--data_pipeline=alphafold2", f"--fasta_paths={queries}", + f"--msa_input_dir={msa_dir}", f"--output_dir={features_dir}", + f"--data_dir={workdir}", "--max_template_date=2050-01-01", + "--template_seqres_database_id=seqres-edge", "--template_mmcif_database_id=mmcif-edge", + f"--pdb_seqres_database_path={seqres}", f"--template_mmcif_dir={mmcif_dir}", + f"--obsolete_pdbs_path={template_root / 'obsolete.dat'}", + f"--hmmsearch_binary_path={tools['hmmsearch']}", + f"--hmmbuild_binary_path={tools['hmmbuild']}", + f"--kalign_binary_path={tools['kalign']}", env=env) + return {name: features_dir / f"{name}.pkl" for name in cases} + + +def _tool(name: str) -> str: + path = shutil.which(name) or str(Path(sys.executable).parent / name) + if not Path(path).exists(): + pytest.skip(f"{name} is not installed") + return path + + +@pytest.fixture(scope="module") +def features(tmp_path_factory): + pytest.importorskip("alphafold.data.pipeline", reason="needs AlphaFold 2") + configured = os.environ.get("MMSEQS_INTEGRATION_BINARY") + if not configured: + pytest.skip("set MMSEQS_INTEGRATION_BINARY to run against real MMseqs2") + tools = {name: _tool(name) for name in ("hmmsearch", "hmmbuild", "kalign")} + paths = build_edge_case_features( + tmp_path_factory.mktemp("edge"), Path(configured), tools=tools, + use_gpu=os.environ.get("MMSEQS_INTEGRATION_GPU") == "1", + ) + loaded = {} + for name, path in paths.items(): + with open(path, "rb") as handle: + loaded[name] = pickle.load(handle) + return loaded + + +def _msa_rows(monomer) -> int: + return int(monomer.feature_dict["msa"].shape[0]) + + +def test_deep_alignment_hits_alphafold2s_mgnify_cap(features): + """600 MGnify hits were found; AlphaFold 2 keeps 501 counting the query.""" + deep = features["deep"].feature_dict + rows = _msa_rows(features["deep"]) + # query + 30 uniref90 + 20 BFD + 500 MGnify, all distinct by construction. + assert rows == 1 + 30 + 20 + (AF2_MGNIFY_CAP - 1), rows + assert deep["num_alignments"][0] == rows + + +def test_the_same_sequence_under_two_names_gets_two_identical_pickles(features): + np.testing.assert_array_equal(features["deep"].feature_dict["msa"], + features["deep_copy"].feature_dict["msa"]) + assert features["deep_copy"].description == "deep_copy" + + +def test_a_shallow_alignment_is_kept_as_it_is(features): + assert _msa_rows(features["shallow"]) == 2 + + +def test_an_orphan_chain_gets_query_only_features(features): + orphan = features["orphan"].feature_dict + assert orphan["msa"].shape[0] == 1 + assert orphan["msa_all_seq"].shape[0] == 1 + assert orphan["deletion_matrix_int"].sum() == 0 + + +def test_no_template_gives_alphafold2s_empty_template(features): + templates = features["notemplate"].feature_dict + assert list(templates["template_domain_names"]) == [b""] + assert templates["template_aatype"].shape == (1, len(features["notemplate"].sequence), 22) + assert not templates["template_all_atom_masks"].any() + + +def test_a_homolog_of_a_known_structure_finds_its_template(features): + assert b"3l4q_A" in list(features["templated"].feature_dict["template_domain_names"]) + + +def test_unknown_residues_survive_as_alphafold2s_unknown(features): + monomer = features["xresidues"] + aatype = monomer.feature_dict["aatype"].argmax(axis=1) + unknown = 20 # residue_constants.restype_order_with_x["X"] + assert [int(aatype[i]) for i in (10, 55, 90)] == [unknown] * 3 + assert _msa_rows(monomer) > 1 + + +def test_pairing_rows_without_species_are_kept_but_unlabelled(features): + """No species in a UniProt header means no pairing -- not a failure, and not + a UniProt lookup to recover one.""" + all_seq = features["nospecies"].feature_dict + assert all_seq["msa_all_seq"].shape[0] == 1 + 5 + assert set(all_seq["msa_species_identifiers_all_seq"]) == {b""} + + +def test_a_short_peptide_is_featurised(features): + peptide = features["peptide"] + assert peptide.feature_dict["aatype"].shape[0] == 20 + assert _msa_rows(peptide) >= 1 + + +def test_every_case_carries_the_same_feature_keys(features): + keys = {name: frozenset(m.feature_dict) for name, m in features.items()} + assert len(set(keys.values())) == 1, keys From 61d124c585021dc9911f6c7cb2e7c0d0b2624f47 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 10:49:04 +0200 Subject: [PATCH 07/17] feat: compare AlphaFold 2 feature pickles from two MSA backends compare_msa_backends.py read only AlphaFold 3 JSON. --artifact_format=af2_pickle reads MonomericObject pickles and measures what each gives the model: unpaired depth, coverage and Neff, rows that carry insertions, paired depth, distinct species available to pairing, and real templates (AlphaFold 2's empty-template placeholder is not counted). No homolog overlap for pickles: they store alignments as integer rows without headers, so there is no accession to match on, and residue strings are not a substitute. Compare raw alignments for that. Decodes with the alphabet af2_to_af3_msa already spells out, so it runs without AlphaFold installed; the AlphaFold 3 mode is unchanged apart from an artifactFormat field in the report. Co-Authored-By: Claude Opus 5 (1M context) --- alphapulldown/scripts/compare_msa_backends.py | 137 +++++++++++++++++- test/unit/test_msa_quality.py | 79 ++++++++++ 2 files changed, 212 insertions(+), 4 deletions(-) diff --git a/alphapulldown/scripts/compare_msa_backends.py b/alphapulldown/scripts/compare_msa_backends.py index 0c13f09b..a06f0212 100644 --- a/alphapulldown/scripts/compare_msa_backends.py +++ b/alphapulldown/scripts/compare_msa_backends.py @@ -13,10 +13,17 @@ flags.DEFINE_string( - "reference_dir", None, "Directory of native/jackhmmer AF3 JSON artifacts." + "reference_dir", None, "Directory of native/jackhmmer feature artifacts." ) -flags.DEFINE_string("candidate_dir", None, "Directory of MMseqs2 AF3 JSON artifacts.") +flags.DEFINE_string("candidate_dir", None, "Directory of MMseqs2 feature artifacts.") flags.DEFINE_string("output_path", None, "JSON report path.") +flags.DEFINE_enum( + "artifact_format", + "af3_json", + ["af3_json", "af2_pickle"], + "af3_json: _af3_input.json[.xz]. af2_pickle: .pkl[.xz], the " + "MonomericObject pickles AlphaFold 2 reads.", +) FLAGS = flags.FLAGS @@ -137,16 +144,138 @@ def mean(key: str, backend: str) -> float: } +def _af2_artifacts(directory: Path) -> dict[str, Path]: + result = {} + for path in sorted(directory.glob("*.pkl*")): + filename = path.name + for suffix in (".pkl.xz", ".pkl"): + if filename.endswith(suffix): + result[filename[: -len(suffix)]] = path + break + return result + + +def _af2_side(features: dict) -> dict: + """What one AlphaFold 2 feature set offers the model, measured.""" + import numpy as np + + # The alphabet AlphaFold 2 encodes MSAs in, spelled out without importing it. + from alphapulldown.utils.af2_to_af3_msa import AF2_ID_TO_A3M + + msa = np.asarray(features["msa"]) + length = int(msa.shape[1]) + unpaired = "".join( + f">row{index}\n{''.join(AF2_ID_TO_A3M[int(i)] for i in row)}\n" + for index, row in enumerate(msa) + ) + deletions = np.asarray(features["deletion_matrix_int"]) + species = { + value.decode() if isinstance(value, bytes) else str(value) + for value in features.get("msa_species_identifiers_all_seq", []) + } + species.discard("") + templates = [ + name for name in features.get("template_domain_names", []) + if (name.decode() if isinstance(name, bytes) else str(name)) + ] + return { + "unpaired": measure_a3m(unpaired, query_length=length), + "unpaired_neff": neff(unpaired), + # Rows carrying at least one insertion: all zero for a local MMseqs2 + # alignment built from result2msa mode 2 alone. + "rows_with_insertions": int((deletions.sum(axis=1) > 0).sum()), + "paired_depth": int(np.asarray(features.get("msa_all_seq", msa[:1])).shape[0]), + # Pairing needs a species in common; distinct labels are what it has to use. + "paired_species": len(species), + "template_count": len(templates), + } + + +def compare_af2_directories(reference_dir: Path, candidate_dir: Path) -> list[dict]: + """Paired measurements of two directories of AlphaFold 2 feature pickles. + + No homolog overlap: a pickle stores its alignment as integer rows without the + sequence headers, so there is no accession to match on, and residue strings + are not a substitute -- two backends align the same homolog over different + extents. Compare the raw alignments for overlap; this compares what the + model is given. + """ + from alphapulldown.utils.lightweight_pickles import ( + extract_feature_dict, + load_lightweight_pickle, + ) + + references = _af2_artifacts(reference_dir) + candidates = _af2_artifacts(candidate_dir) + missing = sorted(references.keys() ^ candidates.keys()) + if missing: + raise ValueError("Artifact sets differ: " + ", ".join(missing)) + rows = [] + for name in sorted(references): + reference = load_lightweight_pickle(references[name]) + candidate = load_lightweight_pickle(candidates[name]) + if reference.sequence != candidate.sequence: + raise ValueError(f"Sequence mismatch for {name!r}") + rows.append( + { + "name": name, + "reference_path": str(references[name]), + "candidate_path": str(candidates[name]), + "reference": _af2_side(extract_feature_dict(reference)), + "candidate": _af2_side(extract_feature_dict(candidate)), + } + ) + return rows + + +def summarize_af2(rows: list[dict]) -> dict: + if not rows: + return {"protein_count": 0} + + def mean(side: str, *path: str) -> float: + total = 0.0 + for row in rows: + value = row[side] + for key in path: + value = value[key] + total += value + return total / len(rows) + + summary = {"protein_count": len(rows)} + for side in ("reference", "candidate"): + summary.update( + { + f"mean_{side}_unpaired_depth": mean(side, "unpaired", "depth"), + f"mean_{side}_unpaired_neff": mean(side, "unpaired_neff"), + f"mean_{side}_rows_with_insertions": mean(side, "rows_with_insertions"), + f"mean_{side}_paired_depth": mean(side, "paired_depth"), + f"mean_{side}_paired_species": mean(side, "paired_species"), + f"mean_{side}_template_count": mean(side, "template_count"), + } + ) + return summary + + def main(argv) -> None: del argv - proteins = compare_directories(Path(FLAGS.reference_dir), Path(FLAGS.candidate_dir)) + if FLAGS.artifact_format == "af2_pickle": + proteins = compare_af2_directories( + Path(FLAGS.reference_dir), Path(FLAGS.candidate_dir) + ) + summary = summarize_af2(proteins) + else: + proteins = compare_directories( + Path(FLAGS.reference_dir), Path(FLAGS.candidate_dir) + ) + summary = summarize(proteins) report = { "schemaVersion": 1, "warning": ( "MSA/template metrics are diagnostic only; run matched inference and " "DockQ against experimental references before claiming accuracy equivalence." ), - "summary": summarize(proteins), + "artifactFormat": FLAGS.artifact_format, + "summary": summary, "proteins": proteins, } Path(FLAGS.output_path).write_text( diff --git a/test/unit/test_msa_quality.py b/test/unit/test_msa_quality.py index d69551f3..4de6ef2b 100644 --- a/test/unit/test_msa_quality.py +++ b/test/unit/test_msa_quality.py @@ -66,3 +66,82 @@ def test_compare_directories_rejects_unpaired_artifact_sets(tmp_path): with pytest.raises(ValueError, match="missing from candidate"): compare_directories(reference, candidate) + + +def _af2_pickle(path, sequence, msa_rows, *, deletions=None, species=(), templates=()): + """An AlphaFold 2 feature pickle, as far as the comparison reads one. + + Pickles the lightweight stand-in, so this needs no AlphaFold import. + """ + import pickle + + import numpy as np + + from alphapulldown.utils.af2_to_af3_msa import AF2_ID_TO_A3M + from alphapulldown.utils.lightweight_pickles import LightweightMonomericObject + + msa = np.array([[AF2_ID_TO_A3M.index(r) for r in row] for row in msa_rows], + dtype=np.int32) + feature_dict = { + "msa": msa, + "deletion_matrix_int": ( + np.asarray(deletions) if deletions is not None else np.zeros_like(msa) + ), + "msa_all_seq": msa[: 1 + len(species)], + "msa_species_identifiers_all_seq": np.array( + [b"", *[s.encode() for s in species]], dtype=object + ), + "template_domain_names": np.array( + [t.encode() for t in templates] or [b""], dtype=object + ), + } + monomer = LightweightMonomericObject( + description=path.stem, sequence=sequence, feature_dict=feature_dict + ) + path.write_bytes(pickle.dumps(monomer)) + + +def test_af2_comparison_measures_what_each_pickle_gives_the_model(tmp_path): + from alphapulldown.scripts.compare_msa_backends import ( + compare_af2_directories, + summarize_af2, + ) + + reference, candidate = tmp_path / "native", tmp_path / "local" + reference.mkdir() + candidate.mkdir() + _af2_pickle(reference / "alpha.pkl", "ACDEFG", ["ACDEFG", "ACDEFW", "ACDEWG"], + deletions=[[0] * 6, [0, 2, 0, 0, 0, 0], [0] * 6], + species=("HUMAN", "MOUSE"), templates=("1abc_A",)) + _af2_pickle(candidate / "alpha.pkl", "ACDEFG", ["ACDEFG", "ACDEFW"], + species=("HUMAN",)) + + [row] = compare_af2_directories(reference, candidate) + + assert row["reference"]["unpaired"]["depth"] == 3 + assert row["candidate"]["unpaired"]["depth"] == 2 + assert row["reference"]["rows_with_insertions"] == 1 + assert row["candidate"]["rows_with_insertions"] == 0 + assert row["reference"]["paired_species"] == 2 + assert row["candidate"]["paired_species"] == 1 + assert row["reference"]["template_count"] == 1 + # AlphaFold 2's empty-template placeholder is not a template. + assert row["candidate"]["template_count"] == 0 + assert summarize_af2([row])["mean_candidate_paired_species"] == 1 + + +def test_af2_comparison_refuses_unpaired_or_mismatched_sets(tmp_path): + from alphapulldown.scripts.compare_msa_backends import compare_af2_directories + + reference, candidate = tmp_path / "native", tmp_path / "local" + reference.mkdir() + candidate.mkdir() + _af2_pickle(reference / "alpha.pkl", "ACDEFG", ["ACDEFG"]) + _af2_pickle(candidate / "beta.pkl", "ACDEFG", ["ACDEFG"]) + with pytest.raises(ValueError, match="differ"): + compare_af2_directories(reference, candidate) + + (candidate / "beta.pkl").unlink() + _af2_pickle(candidate / "alpha.pkl", "ACDEFW", ["ACDEFW"]) + with pytest.raises(ValueError, match="Sequence mismatch"): + compare_af2_directories(reference, candidate) From 12abb977c6879c95bb1998d8a63753931fdc59c5 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 14:59:22 +0200 Subject: [PATCH 08/17] fix: keep iterative search out of nucleotide MMseqs2 searches Iterative profile search is protein-only. On the pinned build, --num-iterations 3 on a nucleotide search exits 1, so raising num_iterations failed every shard holding an RNA chain. The option now reaches protein searches only; RNA provenance already never recorded it, so no cached RNA MSA changes identity. Co-Authored-By: Claude Opus 5 (1M context) --- alphapulldown/feature_batch.py | 8 ++++- .../test_mmseqs2_command_contract.py | 10 ++++-- test/unit/test_mmseqs_process_options.py | 33 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/alphapulldown/feature_batch.py b/alphapulldown/feature_batch.py index a0d1bf12..5c95d07f 100644 --- a/alphapulldown/feature_batch.py +++ b/alphapulldown/feature_batch.py @@ -522,8 +522,14 @@ def search( "1" if gpu else "0", ) + ( + # Iterative profile search is protein-only: measured on the pinned + # build, --num-iterations 3 on a nucleotide search exits 1 ("Alignment + # died", or "no diagonal information" on a one-sequence database). + # RNA provenance correctly never records it. ("--num-iterations", str(settings.num_iterations)) - if settings.num_iterations and settings.num_iterations > 1 + if settings.num_iterations + and settings.num_iterations > 1 + and not nucleotide else () ) + (("--search-type", "3") if nucleotide else ()) diff --git a/test/integration/test_mmseqs2_command_contract.py b/test/integration/test_mmseqs2_command_contract.py index 7aecb998..2bf641be 100644 --- a/test/integration/test_mmseqs2_command_contract.py +++ b/test/integration/test_mmseqs2_command_contract.py @@ -118,8 +118,13 @@ def test_real_createdb_padded_search_result2msa_and_unpack_contract(tmp_path): ) -def test_real_nucleotide_createdb_search_and_unpack_contract(tmp_path): - """The same contract for RNA: a nucleotide database, searched on CPU.""" +@pytest.mark.parametrize("num_iterations", (1, 3)) +def test_real_nucleotide_createdb_search_and_unpack_contract(tmp_path, num_iterations): + """The same contract for RNA: a nucleotide database, searched on CPU. + + Also with the protein-only iterative search raised, which must not reach the + nucleotide search: there the pinned build exits 1. + """ configured_binary = os.environ.get("MMSEQS_INTEGRATION_BINARY") if not configured_binary: pytest.skip("set MMSEQS_INTEGRATION_BINARY to run the real command contract") @@ -157,6 +162,7 @@ def test_real_nucleotide_createdb_search_and_unpack_contract(tmp_path): max_residues_per_batch=1_000, threads=2, rna_databases=databases, + num_iterations=num_iterations, ) result = MsaBatch( diff --git a/test/unit/test_mmseqs_process_options.py b/test/unit/test_mmseqs_process_options.py index 45b5864e..1313ba43 100644 --- a/test/unit/test_mmseqs_process_options.py +++ b/test/unit/test_mmseqs_process_options.py @@ -8,6 +8,7 @@ from __future__ import annotations +import dataclasses from pathlib import Path import pytest @@ -139,3 +140,35 @@ def test_db_load_mode_stays_out_of_the_cache_signature(tmp_path: Path): mmseqs_process=SubprocessMmseqsProcess(binary, gpu=False), ) assert plain._cache_signature() != on_cpu._cache_signature() + + +def test_iterations_reach_protein_searches_but_never_nucleotide_ones( + tmp_path: Path, recording_binary +): + """Iterative profile search is protein-only. Measured on the pinned build, + --num-iterations 3 on a nucleotide search exits 1, so raising the setting + used to fail every RNA shard.""" + binary, arguments = recording_binary + settings = dataclasses.replace(_settings(tmp_path), num_iterations=3) + process = SubprocessMmseqsProcess(binary) + + process.search( + tmp_path / "query", + _database(tmp_path), + tmp_path / "result", + tmp_path / "work", + settings, + ) + protein = arguments.read_text(encoding="utf-8").splitlines() + assert protein[protein.index("--num-iterations") + 1] == "3" + + rfam = DatabaseSpec( + name="rfam", path=tmp_path / "rfam", identifier="rfam-fixture", + molecule_type="rna", + ) + process.search( + tmp_path / "query", rfam, tmp_path / "result", tmp_path / "work", settings + ) + nucleotide = arguments.read_text(encoding="utf-8").splitlines() + assert "--num-iterations" not in nucleotide + assert nucleotide[nucleotide.index("--search-type") + 1] == "3" From b1a2f8795e1d2915cec1a26c686a247a7be7cb7f Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 14:59:23 +0200 Subject: [PATCH 09/17] fix: delete an MSA bundle AlphaFold 2 cannot slice, so it is rebuilt AlphaFold 2 slices the unpaired alignment by database, so a bundle whose per-database row spans are missing or do not add up is unusable to it. The finalizer reported that and left the bundle in place, where the workflow's shard completion kept validating it: no repair was ever scheduled and every retry failed the same way. Such a bundle is now treated as damaged and deleted, the way read_msa_bundle already treats every other defect. Co-Authored-By: Claude Opus 5 (1M context) --- alphapulldown/af2_feature_finalizer.py | 4 +++- alphapulldown/feature_batch.py | 19 ++++++++++++++++++- test/unit/test_af2_feature_finalizer.py | 22 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/alphapulldown/af2_feature_finalizer.py b/alphapulldown/af2_feature_finalizer.py index 4d05f34b..3431a18e 100644 --- a/alphapulldown/af2_feature_finalizer.py +++ b/alphapulldown/af2_feature_finalizer.py @@ -267,7 +267,9 @@ def generate(self, requests: Sequence[FeatureRequest]) -> FeatureBatchResult: f"{request.name!r} is {request.molecule_type}: AlphaFold 2 " "has no MSA features for anything but protein chains" ) - payload = read_msa_bundle(self._settings.msa_input_dir, request) + payload = read_msa_bundle( + self._settings.msa_input_dir, request, require_row_spans=True + ) msas = searched_msas_from_payload(payload) provenance = self._provenance(payload) cached = self._read_matching_artifact(request, provenance) diff --git a/alphapulldown/feature_batch.py b/alphapulldown/feature_batch.py index 5c95d07f..f954e0b7 100644 --- a/alphapulldown/feature_batch.py +++ b/alphapulldown/feature_batch.py @@ -1482,10 +1482,19 @@ def _merge_a3ms( return text, tuple(contributed) -def read_msa_bundle(msa_input_dir: Path, request: FeatureRequest) -> dict[str, Any]: +def read_msa_bundle( + msa_input_dir: Path, request: FeatureRequest, *, require_row_spans: bool = False +) -> dict[str, Any]: """Read one request's MSA bundle, deleting it if it is unsafe to use. Shared by every finalizer, so each backend refuses the same damaged bundles. + Deleting is what gets a bundle rebuilt: the workflow's Shard completion then no + longer validates, and a repair shard is scheduled. A bundle that is merely + rejected, and left in place, fails the same finalization on every retry. + + ``require_row_spans`` is for consumers that slice the unpaired alignment by + database -- AlphaFold 2 does. A bundle without usable spans is unusable to them, + so it is treated as damaged, not as a failure to report and keep. """ path = msa_input_dir / f"{request.name}_mmseqs_msa.json" try: @@ -1521,6 +1530,14 @@ def read_msa_bundle(msa_input_dir: Path, request: FeatureRequest) -> dict[str, A raise _InvalidMsaBundle( f"MMseqs2 MSA bundle lacks {key} for {request.name!r}" ) + if require_row_spans: + try: + searched_msas_from_payload(payload) + except (KeyError, TypeError, ValueError) as exc: + raise _InvalidMsaBundle( + f"MMseqs2 MSA bundle {path} has no usable per-database row " + f"spans: {exc}" + ) from exc return payload except _InvalidMsaBundle: path.unlink(missing_ok=True) diff --git a/test/unit/test_af2_feature_finalizer.py b/test/unit/test_af2_feature_finalizer.py index dcf0e60e..4cee0b81 100644 --- a/test/unit/test_af2_feature_finalizer.py +++ b/test/unit/test_af2_feature_finalizer.py @@ -407,3 +407,25 @@ def test_a_chopped_local_chain_pairs_with_a_full_one(tmp_path): region_length = region[1] - region[0] + 1 assert merged["aatype"].shape == (len(QUERY) + region_length,) + + +@pytest.mark.parametrize("damage", ("spans_do_not_add_up", "no_spans")) +def test_a_bundle_unusable_to_alphafold2_is_deleted_so_it_is_rebuilt(tmp_path, damage): + """Rejecting such a bundle and leaving it in place fails the same finalization on + every retry: its Shard completion still validates, so no repair is scheduled. + Deleting it is what gets it rebuilt.""" + _standard_bundle(tmp_path / "msas") + bundle_path = tmp_path / "msas" / "alpha_mmseqs_msa.json" + bundle = json.loads(bundle_path.read_text()) + if damage == "no_spans": + del bundle["unpairedDatabaseRows"] + else: + bundle["unpairedDatabaseRows"][0]["rows"] += 1 + bundle_path.write_text(json.dumps(bundle)) + + finalizer, _ = _finalizer(tmp_path) + result = finalizer.generate([FeatureRequest(name="alpha", sequence=QUERY)]) + + assert [failure.name for failure in result.failures] == ["alpha"] + assert "row spans" in result.failures[0].error + assert not bundle_path.exists() From 71eef1c4d0955c0f18b7f236e50d9aa8b85a4f06 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 14:59:23 +0200 Subject: [PATCH 10/17] docs: the feature glossary covers AlphaFold 2 artifacts too Co-Authored-By: Claude Opus 5 (1M context) --- CONTEXT.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index cd1f8aad..e525de5a 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -13,23 +13,24 @@ - **Fold preparation**: building the object to model for one prediction job and its output directory, including AlphaPulldown-style naming and feature-metadata copying. Shared by the single-fold command and the resident batch so the two cannot diverge. -- **Feature request**: one named sequence, of a stated molecule type, requiring an AlphaFold 3 feature artifact. +- **Feature request**: one named sequence, of a stated molecule type, requiring a feature artifact. - **Molecule type**: whether a feature request is a protein or an RNA chain. It decides which databases are searched, whether a paired MSA exists at all, and which AlphaFold 3 - chain the finalized artifact carries. DNA has no MSA and is not handled by this path. + chain the finalized artifact carries. RNA is AlphaFold 3 only, and DNA has no MSA and + is not handled by this path. - **Feature batch**: an ordered collection of feature requests handled as one operation. - **MSA batch**: the GPU stage that searches MMseqs2 and durably publishes one reusable MSA bundle per feature request. -- **Feature finalization**: the CPU stage that reads an MSA bundle, performs native AF3 template search, and publishes the standard AF3 feature artifact. +- **Feature finalization**: the CPU stage that reads an MSA bundle, performs the backend's native template search (AF3's, or AF2's hmmsearch/hhsearch), and publishes that backend's standard feature artifact. - **MSA bundle**: an atomic intermediate JSON containing one sequence, merged unpaired A3M, paired A3M, how many unpaired rows each database contributed, and complete MMseqs/database provenance. Its A3Ms carry both full database headers and insertions. - **Two-pass format**: formatting one MMseqs2 search result twice and joining the passes row by row, because the format with full headers drops insertions and the format with insertions drops the headers. - **Database identifier**: the caller-supplied immutable identity of one MMseqs2 database build; cache validity depends on it, not only its filesystem path. -- **Feature artifact**: the standard AlphaFold 3 JSON (optionally LZMA-compressed) produced for one feature request. +- **Feature artifact**: the standard features one backend consumes for one feature request: an AlphaFold 3 JSON, or an AlphaFold 2 MonomericObject pickle (either optionally LZMA-compressed). - **MSA cache hit**: an existing MSA bundle whose sequence, MMseqs2 executable version, search settings, and database identifiers match the request. -- **Feature cache hit**: an existing feature artifact whose MSA provenance, maximum template date, PDB seqres identity, and mmCIF identity match the request. +- **Feature cache hit**: an existing feature artifact whose MSA provenance, maximum template date, PDB seqres identity, and mmCIF identity match the request (for AlphaFold 2, also the template searcher). - **Recoverable failure**: a failure isolated to one sequence; remaining requests continue and the batch reports a nonzero summary after writing successful artifacts. - **Database role**: whether a configured MMseqs2 database supplies unpaired hits (uniref90, mgnify, small_bfd, merged into one MSA) or paired hits (uniprot, whose - UniProt taxon headers let AlphaFold 3 pair chains by species). Roles are named, not + UniProt taxon headers let AlphaFold pair chains by species). Roles are named, not inferred from a position in the configured list. - **RNA database set**: the three nucleotide databases AlphaFold 3 merges into one unpaired RNA MSA (rfam, rnacentral, nt_rna). All unpaired - AlphaFold 3 never pairs From ae838f9a30eb961e96edaad54c4a18c506745d14 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 21:21:33 +0200 Subject: [PATCH 11/17] docs: local MMseqs2 AlphaFold 2 features, measured against native Replace "not yet benchmarked" with the benchmark: 32 monomers over native MSA-depth quartiles and 12 heterodimers released after AF2-multimer's cutoff, native reduced_dbs against local GPU and CPU search. Top-ranked DockQ averaged 0.56 against 0.59, 9 of 12 interfaces acceptable either way; the MSAs are shallower, most on the shallowest families, and a CPU search finds far fewer distant hits than the GPU prefilter on deep ones. Finalization cost follows the template hits, not chain length. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 5 ++++- docs/mmseqs2_rna.md | 28 ++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1426ec7c..8929eae9 100644 --- a/README.md +++ b/README.md @@ -713,7 +713,10 @@ spot-check your own targets. UniProt, with no BFD/UniRef30 HHblits arm — built the way native AF2 builds features: its per-database caps and merge order, templates searched from UniRef90 alone, and species pairing from an independent UniProt search. The pickles carry the same feature -keys as native ones. They have not been benchmarked against native AF2 features yet. +keys as native ones. Against native `reduced_dbs` features on 12 heterodimers released +after AF2-multimer's training cutoff, top-ranked DockQ averaged 0.56 against 0.59, with 9 +of 12 interfaces acceptable either way; the MSAs are somewhat shallower (numbers in the +docs below). Alignments now keep their insertions. MSA bundles written before this change carried none, so AlphaFold saw an all-zero deletion matrix; they are searched again rather than diff --git a/docs/mmseqs2_rna.md b/docs/mmseqs2_rna.md index 7378aad0..a6d30ca2 100644 --- a/docs/mmseqs2_rna.md +++ b/docs/mmseqs2_rna.md @@ -175,8 +175,32 @@ What differs, and why: The pickles carry the same feature keys as native ones plus those two accession arrays, and assemble into multimers alongside pickles from other sources. RNA and DNA chains are -refused: AlphaFold 2 has no MSA features for them. These features have not yet been -benchmarked against native AlphaFold 2 features. +refused: AlphaFold 2 has no MSA features for them. + +### Measured against native AlphaFold 2 + +32 monomers spread over the quartiles of their native MSA depth, plus 12 heterodimers +released after AF2-multimer's training cutoff, featurized natively with `reduced_dbs` and +through this path, with the same databases and templates up to 2021-09-30: + +| median, unless stated | native | local, GPU search | local, CPU search | +|---|---|---|---| +| MSA depth, shallowest quartile | 52 | 29 | 28 | +| MSA depth, deepest quartile | 12 247 | 11 756 | 5 181 | +| Neff, all monomers | 778 | 627 | 572 | +| templates per chain | 16 | 16 | 15 | +| AF2-multimer DockQ, top-ranked, mean of 12 | 0.59 | 0.56 | 0.56 | +| acceptable interfaces (DockQ ≥ 0.23) | 9 / 12 | 9 / 12 | 9 / 12 | + +- The MSAs are shallower, most on the shallowest families, as for AlphaFold 3. A GPU + search recovers about three quarters of native's unpaired hits. +- A CPU search, at MMseqs2's default sensitivity, finds far fewer distant hits than the + GPU prefilter on deep families, without changing DockQ here. +- One interface (9HMX) lost about 0.3 DockQ against native; the other eleven moved by + less than 0.1. +- Finalization is dominated by template featurization: median ~1 GB and 2 min per chain, + but up to 19 GB and 90 min, set by which structures the templates come from rather + than by chain length or MSA depth. ## The binary From 48019a4465a82cb86405588e11c9104d4fe67ff8 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 21:59:01 +0200 Subject: [PATCH 12/17] test: compare local MMseqs2 AlphaFold 2 features with the remote ColabFold API An opt-in cluster check that builds AlphaFold 2 features for the same chains both ways -- remotely through --use_mmseqs2, locally through create_batch_msas and finalize_batch_features -- and compares them with compare_af2_directories. The two search different databases, so it asserts agreement, not equality, with bands from the 32-monomer benchmark: for two real families (human lysozyme and O31718 from the benchmark) both sides find at least 100 rows, local is within 0.2-5x of remote on depth and Neff, both carry insertions, and local has species to pair by; lysozyme gets a template; and for a random orphan neither side finds more than 20 rows. The measured report is printed into the job log. Co-Authored-By: Claude Opus 5 (1M context) --- test/cluster/check_alphafold2_predictions.py | 176 +++++++++++++++++++ test/test_data/fastas/O31718.fasta | 2 + 2 files changed, 178 insertions(+) create mode 100644 test/test_data/fastas/O31718.fasta diff --git a/test/cluster/check_alphafold2_predictions.py b/test/cluster/check_alphafold2_predictions.py index 0b7423f9..d672a561 100755 --- a/test/cluster/check_alphafold2_predictions.py +++ b/test/cluster/check_alphafold2_predictions.py @@ -810,5 +810,181 @@ def test_issue_614_precomputed_mmseqs_features_enable_af2_multimer_inference(sel f"Expected AF2 ipTM > 0.6 from precomputed MMseq features, got {result_payload['iptm']}", ) + +MMSEQS_DATABASE_DIR = Path( + os.getenv("MMSEQS_DATABASE_DIR", "/g/alphafold/AlphaFold_DBs/mmseqs") +) +# GPU-padded builds of the AlphaFold 3.0.0 FASTAs (scripts/setup_databases.sh --mmseqs), +# each named _gpu, with the identifiers the AlphaFold 2 benchmark used. +LOCAL_MMSEQS_DATABASE_IDS = { + "uniref90": "uniref90-2022_05-padded", + "mgnify": "mgy_clusters-2022_05-padded", + "small_bfd": "small-bfd-padded", + "uniprot": "uniprot_all-2021_04-padded", +} +# A seeded random 90-mer with no homologs anywhere. In the Snakemake end-to-end run the +# local path returned only the query for it. +ORPHAN_SEQUENCE = ( + "MYNARDGTQMSKFWKTDQPEWVTSYVYMRCQGQFWPAKCVIWGGAYNDV" + "HSGVVSGENWKIGSTWMNISMVDQDMITGQAMWSVRNVLFC" +) + + +class TestLocalMmseqsAgainstRemote(_TestBase): + """Opt-in: AF2 features from the local MMseqs2 path against the remote ColabFold API. + + The two search different databases -- ColabFold's UniRef30 and environmental sets + remotely; UniRef90, MGnify, small BFD and UniProt locally -- so this asserts + agreement, not equality. The bands come from a 32-monomer benchmark: on families + with hundreds of hits or more, local over remote depth ran 0.26-3.7 (one outlier at + 0.03), and Neff alike. Needs network access to the ColabFold API, a GPU-capable + MMseqs2 build, and ~200 GB of host RAM, because the search reads every padded + database in full: + + RUN_MMSEQS_FUNCTIONAL_TESTS=1 MMSEQS_INTEGRATION_BINARY=/path/to/mmseqs \\ + python test/cluster/run_alphafold2_predictions.py \\ + -k TestLocalMmseqsAgainstRemote --constraint "" --mem 200G --time 06:00:00 + """ + + # A deep family with hundreds of structures, and a moderate one from the + # benchmark (1517 rows remotely, 1264 locally). + FAMILY_CHAINS = ("P61626", "O31718") + MAX_TEMPLATE_DATE = "2024-05-02" + RATIO_BAND = (0.2, 5.0) + + def _require_local_mmseqs_environment(self) -> Path: + skip_reason = _mmseqs_functional_test_skip_reason() + if skip_reason: + self.skipTest(skip_reason) + binary = os.getenv("MMSEQS_INTEGRATION_BINARY") + if not binary or not Path(binary).is_file(): + self.skipTest("Set MMSEQS_INTEGRATION_BINARY to a GPU-capable MMseqs2 build.") + missing = [ + name + for name in LOCAL_MMSEQS_DATABASE_IDS + if not (MMSEQS_DATABASE_DIR / f"{name}_gpu.dbtype").is_file() + ] + if missing: + self.skipTest( + f"Padded MMseqs2 databases missing under {MMSEQS_DATABASE_DIR}: " + + ", ".join(missing) + ) + return Path(binary) + + def _run_step(self, label: str, args: list[str]) -> None: + res = self._run_prediction_subprocess([sys.executable, *args]) + self.assertEqual( + res.returncode, + 0, + f"{label} failed.\nSTDOUT:\n{res.stdout}\nSTDERR:\n{res.stderr}", + ) + + def test_local_mmseqs_features_agree_with_remote(self): + binary = self._require_local_mmseqs_environment() + orphan = self.output_dir / "orphan.fasta" + orphan.write_text(f">orphan\n{ORPHAN_SEQUENCE}\n", encoding="utf-8") + fasta_paths = ",".join( + [ + str(self.test_data_dir / "fastas" / f"{name}.fasta") + for name in self.FAMILY_CHAINS + ] + + [str(orphan)] + ) + remote_dir = self.output_dir / "remote" + local_dir = self.output_dir / "local" + msa_dir = self.output_dir / "msas" + scripts = self.script_create_features.parent + shared = [ + f"--fasta_paths={fasta_paths}", + f"--data_dir={DATA_DIR}", + f"--max_template_date={self.MAX_TEMPLATE_DATE}", + "--compress_features=True", + ] + + self._run_step( + "Remote MMseqs2 features", + [ + str(self.script_create_features), + *shared, + f"--output_dir={remote_dir}", + "--use_mmseqs2=True", + "--data_pipeline=alphafold2", + "--skip_existing=False", + ], + ) + self._run_step( + "Local MMseqs2 search", + [ + str(scripts / "create_batch_msas.py"), + f"--fasta_paths={fasta_paths}", + f"--msa_output_dir={msa_dir}", + f"--summary_path={self.output_dir / 'msa_summary.json'}", + f"--mmseqs_binary_path={binary}", + f"--mmseqs_temp_dir={self.output_dir / 'mmseqs_tmp'}", + f"--mmseqs_use_gpu={'true' if _has_nvidia_gpu() else 'false'}", + "--mmseqs_threads=8", + *( + argument + for name, identifier in LOCAL_MMSEQS_DATABASE_IDS.items() + for argument in ( + f"--mmseqs_{name}_database_path={MMSEQS_DATABASE_DIR / f'{name}_gpu'}", + f"--mmseqs_{name}_database_id={identifier}", + ) + ), + ], + ) + self._run_step( + "Local AlphaFold 2 finalization", + [ + str(scripts / "finalize_batch_features.py"), + *shared, + "--data_pipeline=alphafold2", + f"--msa_input_dir={msa_dir}", + f"--output_dir={local_dir}", + "--template_seqres_database_id=pdb-seqres-cluster-check", + "--template_mmcif_database_id=pdb-mmcif-cluster-check", + ], + ) + + from alphapulldown.scripts.compare_msa_backends import ( + compare_af2_directories, + summarize_af2, + ) + + # Raises on a missing artifact or a sequence mismatch between the two sides. + rows = compare_af2_directories(remote_dir, local_dir) + # The measured numbers, for the job log: the assertions below are loose. + print( + json.dumps( + {"summary": summarize_af2(rows), "rows": rows}, indent=1, default=str + ) + ) + by_name = {row["name"]: row for row in rows} + self.assertEqual(set(by_name), {*self.FAMILY_CHAINS, "orphan"}) + + low, high = self.RATIO_BAND + for name in self.FAMILY_CHAINS: + remote = by_name[name]["reference"] + local = by_name[name]["candidate"] + with self.subTest(chain=name): + remote_depth = remote["unpaired"]["depth"] + local_depth = local["unpaired"]["depth"] + self.assertGreaterEqual(min(remote_depth, local_depth), 100) + self.assertBetween(local_depth / remote_depth, low, high) + self.assertBetween( + local["unpaired_neff"] / remote["unpaired_neff"], low, high + ) + # An all-zero deletion matrix is the defect the two-pass format fixed. + self.assertGreater(local["rows_with_insertions"], 0) + self.assertGreater(remote["rows_with_insertions"], 0) + # Local pairing comes from its own UniProt search, which carries species. + self.assertGreaterEqual(local["paired_species"], 5) + self.assertGreaterEqual(by_name["P61626"]["candidate"]["template_count"], 1) + # Neither backend may invent a family for a sequence that has none. + for side in ("reference", "candidate"): + with self.subTest(orphan=side): + self.assertLessEqual(by_name["orphan"][side]["unpaired"]["depth"], 20) + + if __name__ == "__main__": absltest.main() diff --git a/test/test_data/fastas/O31718.fasta b/test/test_data/fastas/O31718.fasta new file mode 100644 index 00000000..435bfcab --- /dev/null +++ b/test/test_data/fastas/O31718.fasta @@ -0,0 +1,2 @@ +>O31718 +MIYKVFYQEKADEVPVREKTDSLYIEGVSERDVRTKLKEKKFNIEFITPVDGAFLEYEQQSENFKVLEL From 94f5144cdc230461ff54742eec2872870ff9dc18 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 22:07:00 +0200 Subject: [PATCH 13/17] test: give the remote-vs-local check the shard limits the search requires The first cluster run failed before searching: create_batch_msas requires --mmseqs_batch_max_sequences and --mmseqs_batch_max_residues and they have no default. Pass limits that put all three chains in one shard, as the workflow would. Both local scripts were checked against flag parsing with these exact arguments before rerunning. Co-Authored-By: Claude Opus 5 (1M context) --- test/cluster/check_alphafold2_predictions.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/cluster/check_alphafold2_predictions.py b/test/cluster/check_alphafold2_predictions.py index d672a561..7f8052dc 100755 --- a/test/cluster/check_alphafold2_predictions.py +++ b/test/cluster/check_alphafold2_predictions.py @@ -923,6 +923,9 @@ def test_local_mmseqs_features_agree_with_remote(self): f"--mmseqs_temp_dir={self.output_dir / 'mmseqs_tmp'}", f"--mmseqs_use_gpu={'true' if _has_nvidia_gpu() else 'false'}", "--mmseqs_threads=8", + # One shard for all three chains, as the workflow would batch them. + "--mmseqs_batch_max_sequences=8", + "--mmseqs_batch_max_residues=100000", *( argument for name, identifier in LOCAL_MMSEQS_DATABASE_IDS.items() From 881642c03afbb1082f5a64a0fb8dfb6731f4de7e Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Fri, 11 Sep 2026 23:31:20 +0200 Subject: [PATCH 14/17] test: run the remote-vs-local steps with this interpreter's tools first on PATH The second cluster run searched fine and then failed every finalization with "expected str, bytes or os.PathLike object, not NoneType". The scripts default kalign, hmmsearch and hmmbuild to whatever is first on PATH, and the job had been launched from a shell whose first environment has no kalign, so template realignment got None. Reproduced on the login node with that PATH, and fixed by putting the AlphaPulldown environment's bin first. Do that in the test itself, so the check works from any shell rather than depending on how it was launched. Co-Authored-By: Claude Opus 5 (1M context) --- test/cluster/check_alphafold2_predictions.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/cluster/check_alphafold2_predictions.py b/test/cluster/check_alphafold2_predictions.py index 7f8052dc..a9a7715f 100755 --- a/test/cluster/check_alphafold2_predictions.py +++ b/test/cluster/check_alphafold2_predictions.py @@ -872,7 +872,18 @@ def _require_local_mmseqs_environment(self) -> Path: return Path(binary) def _run_step(self, label: str, args: list[str]) -> None: - res = self._run_prediction_subprocess([sys.executable, *args]) + env = _af2_subprocess_env() + # The scripts default their template tools (kalign, hmmsearch, hmmbuild) to + # whatever is first on PATH. Put this interpreter's environment first, so a + # job launched from another environment's shell still gets the tools installed + # alongside AlphaPulldown; otherwise kalign resolves to None and every chain + # fails at template realignment. + env["PATH"] = os.pathsep.join( + [str(Path(sys.executable).parent), env.get("PATH", "")] + ) + res = subprocess.run( + [sys.executable, *args], capture_output=True, text=True, env=env + ) self.assertEqual( res.returncode, 0, From 6c53a24aa42cfeb0af929407728d64ab5a145572 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Mon, 14 Sep 2026 09:51:57 +0200 Subject: [PATCH 15/17] fix: validate AF2 template cache identities and restore CI Require and persist the PDB70 build identity for HHsearch while retaining the seqres identity for hmmsearch. Validate complete bundle database roles before reuse so unusable bundles are removed for repair. Update the relocated template-stack test patch targets and cover all new executable functions through unit tests. --- alphapulldown/af2_feature_finalizer.py | 26 ++- alphapulldown/feature_batch.py | 20 ++- alphapulldown/scripts/_mmseqs2_cli.py | 29 ++- .../scripts/finalize_batch_features.py | 6 +- docs/mmseqs2_rna.md | 8 + .../test_create_individual_features.py | 12 +- test/unit/test_af2_feature_finalizer.py | 55 ++++++ test/unit/test_af2_template_stack.py | 170 ++++++++++++++++++ test/unit/test_msa_bundle_validation.py | 121 +++++++++++++ workflows/mmseqs2-gpu.md | 5 + 10 files changed, 431 insertions(+), 21 deletions(-) create mode 100644 test/unit/test_af2_template_stack.py create mode 100644 test/unit/test_msa_bundle_validation.py diff --git a/alphapulldown/af2_feature_finalizer.py b/alphapulldown/af2_feature_finalizer.py index 3431a18e..2319a2df 100644 --- a/alphapulldown/af2_feature_finalizer.py +++ b/alphapulldown/af2_feature_finalizer.py @@ -226,11 +226,12 @@ class Af2FeatureFinalizationSettings: output_dir: Path msa_input_dir: Path max_template_date: str - template_seqres_database_id: str + template_seqres_database_id: str | None template_mmcif_database_id: str # hmmsearch against PDB seqres, or hhsearch against PDB70 (--use_hhsearch). # The two find different templates, so which one ran is part of the identity. template_searcher: str = "hmmsearch" + template_pdb70_database_id: str | None = None compress: bool = False base_metadata: Mapping[str, Any] = dataclasses.field(default_factory=dict) @@ -287,19 +288,21 @@ def generate(self, requests: Sequence[FeatureRequest]) -> FeatureBatchResult: def _validate(self, requests: Sequence[FeatureRequest]) -> None: _validate_feature_requests(requests) - for field_name in ( - "max_template_date", - "template_seqres_database_id", - "template_mmcif_database_id", - ): - if not str(getattr(self._settings, field_name)).strip(): - raise ValueError(f"{field_name} requires a non-empty value") if self._settings.template_searcher not in TEMPLATE_SEARCHERS: raise ValueError( "template_searcher must be one of " f"{', '.join(TEMPLATE_SEARCHERS)}, not " f"{self._settings.template_searcher!r}" ) + for field_name in ( + "max_template_date", + "template_mmcif_database_id", + "template_pdb70_database_id" if self._settings.template_searcher == "hhsearch" + else "template_seqres_database_id", + ): + value = getattr(self._settings, field_name) + if value is None or not str(value).strip(): + raise ValueError(f"{field_name} requires a non-empty value") def _feature_dict( self, request: FeatureRequest, inputs: Af2MsaInputs @@ -363,9 +366,14 @@ def _provenance(self, msa_payload: Mapping[str, Any]) -> dict[str, Any]: def _template_signature(self) -> dict[str, Any]: # Software versions, not base_metadata's wall-clock date, which would miss # on every run -- the same choice the AlphaFold 3 finalizer makes. + database = ( + {"pdb70_database_id": self._settings.template_pdb70_database_id} + if self._settings.template_searcher == "hhsearch" + else {"pdb_seqres_database_id": self._settings.template_seqres_database_id} + ) return { "max_template_date": self._settings.max_template_date, - "pdb_seqres_database_id": self._settings.template_seqres_database_id, + **database, "mmcif_database_id": self._settings.template_mmcif_database_id, "template_searcher": self._settings.template_searcher, "software": dict(self._settings.base_metadata.get("software", {})), diff --git a/alphapulldown/feature_batch.py b/alphapulldown/feature_batch.py index f954e0b7..495c75a6 100644 --- a/alphapulldown/feature_batch.py +++ b/alphapulldown/feature_batch.py @@ -1565,8 +1565,24 @@ def searched_msas_from_payload(payload: Mapping[str, Any]) -> SearchedMsas: ): raise ValueError(f"MSA bundle has a malformed row span: {entry!r}") rows.append((entry["name"], entry["rows"])) - # The query row belongs to no database. - if unpaired and sum(count for _, count in rows) != _msa_depth(unpaired) - 1: + # The producer always searches the complete named recipe. Counts alone do + # not detect a missing database or a duplicate name that would overwrite an + # earlier span in rows_by_database(). Validate before any finalizer uses it. + molecule_type = payload.get("moleculeType", PROTEIN) + required_names = ( + RNA_DATABASE_NAMES if molecule_type == RNA else UNPAIRED_DATABASE_NAMES + ) + names = tuple(name for name, _ in rows) + if len(names) != len(required_names) or set(names) != set(required_names): + raise ValueError( + "MSA bundle database row spans must name each of " + f"{', '.join(required_names)} exactly once" + ) + if molecule_type == PROTEIN and _msa_depth(payload["pairedMsa"]) == 0: + raise ValueError("Protein MSA bundle has no paired UniProt alignment") + # The query row belongs to no database. An empty alignment is invalid too: + # its depth is zero, so no nonnegative span total can account for its query. + if sum(count for _, count in rows) != _msa_depth(unpaired) - 1: raise ValueError( "MSA bundle row spans account for " f"{sum(count for _, count in rows)} rows but the alignment has " diff --git a/alphapulldown/scripts/_mmseqs2_cli.py b/alphapulldown/scripts/_mmseqs2_cli.py index 0377a9b5..409b3b22 100644 --- a/alphapulldown/scripts/_mmseqs2_cli.py +++ b/alphapulldown/scripts/_mmseqs2_cli.py @@ -170,6 +170,13 @@ def define_msa_search_flags( def define_template_provenance_flags() -> None: + _define_once( + "template_pdb70_database_id", + flags.DEFINE_string, + None, + "Immutable identity of the PDB70 build used with AF2 --use_hhsearch. " + "Change this identity whenever PDB70 is rebuilt, even at the same path.", + ) _define_once( "template_seqres_database_id", flags.DEFINE_string, @@ -310,5 +317,23 @@ def always_required_msa_flag_names() -> tuple[str, ...]: return required_msa_flag_names(molecule_types=()) -def required_template_flag_names() -> tuple[str, ...]: - return ("template_seqres_database_id", "template_mmcif_database_id") +def required_template_flag_names( + *, data_pipeline: str = "alphafold3", use_hhsearch: bool = False +) -> tuple[str, ...]: + database = ( + "template_pdb70_database_id" + if data_pipeline == "alphafold2" and use_hhsearch + else "template_seqres_database_id" + ) + return (database, "template_mmcif_database_id") + + +def require_template_flags(flag_values: flags.FlagValues) -> None: + """Validate identities for the databases the selected template search reads.""" + required = required_template_flag_names( + data_pipeline=_flag_value(flag_values, "data_pipeline"), + use_hhsearch=bool(_flag_value(flag_values, "use_hhsearch")), + ) + missing = [name for name in required if not str(_flag_value(flag_values, name) or "").strip()] + if missing: + raise ValueError("Template finalization requires " + ", ".join(f"--{name}" for name in missing)) diff --git a/alphapulldown/scripts/finalize_batch_features.py b/alphapulldown/scripts/finalize_batch_features.py index 51937d2e..27f29dfc 100644 --- a/alphapulldown/scripts/finalize_batch_features.py +++ b/alphapulldown/scripts/finalize_batch_features.py @@ -32,7 +32,7 @@ from alphapulldown.scripts import create_individual_features as legacy_features from alphapulldown.scripts._mmseqs2_cli import ( define_template_provenance_flags, - required_template_flag_names, + require_template_flags, ) from alphapulldown.utils import save_meta_data @@ -50,6 +50,7 @@ def main(argv) -> None: "MMseqs2 MSA finalization cannot be combined with --keep_msas, " "--skip_msa, --path_to_mmt, or --use_mmseqs2" ) + require_template_flags(FLAGS) if FLAGS.data_pipeline == "alphafold2": result = _finalize_alphafold2() backend = "AF2" @@ -116,6 +117,7 @@ def _finalize_alphafold2(): template_seqres_database_id=FLAGS.template_seqres_database_id, template_mmcif_database_id=FLAGS.template_mmcif_database_id, template_searcher=stack.searcher_name, + template_pdb70_database_id=FLAGS.template_pdb70_database_id, compress=FLAGS.compress_features, base_metadata=af2_template_metadata(stack), ), @@ -164,7 +166,7 @@ def _finalize_alphafold3(): "output_dir", "data_dir", "max_template_date", - *required_template_flag_names(), + "template_mmcif_database_id", ] ) app.run(main) diff --git a/docs/mmseqs2_rna.md b/docs/mmseqs2_rna.md index a6d30ca2..8da2aee1 100644 --- a/docs/mmseqs2_rna.md +++ b/docs/mmseqs2_rna.md @@ -150,6 +150,14 @@ Templates come from the AlphaFold 2 database tree under `--data_dir` (`pdb_seqre `pdb_mmcif`), searched with hmmsearch, or with hhsearch against PDB70 under `--use_hhsearch`. The MSA databases are the MMseqs2 ones the search stage used. +For HHsearch, replace `--template_seqres_database_id` in the example with +`--template_pdb70_database_id pdb70-2026-08`. The selected database identity and +the mmCIF identity are required. Change the relevant identity whenever that +database is rebuilt, even if its path stays the same. This regenerates features +while reusing the existing MSA bundle; changing an unused database does not +invalidate features. Existing HHsearch pickles without a PDB70 identity are +regenerated once. The hmmsearch and AF3 cache identities are unchanged. + The features are built the way native AlphaFold 2 builds them from jackhmmer: - uniref90 capped at 10 000 rows and MGnify at 501, counting the query as AlphaFold 2 diff --git a/test/integration/test_create_individual_features.py b/test/integration/test_create_individual_features.py index e8d979b1..caba7971 100644 --- a/test/integration/test_create_individual_features.py +++ b/test/integration/test_create_individual_features.py @@ -1369,8 +1369,8 @@ def test_create_pipeline_af2_uses_hhsearch_template_stack(tmp_flags): create_features.FLAGS.kalign_binary_path = "/bin/kalign" create_features.FLAGS.obsolete_pdbs_path = "/db/obsolete.dat" - with patch.object(create_features.hhsearch, "HHSearch", return_value="searcher") as mock_searcher, \ - patch.object(create_features.templates, "HhsearchHitFeaturizer", return_value="featurizer") as mock_featurizer, \ + with patch("alphafold.data.tools.hhsearch.HHSearch", return_value="searcher") as mock_searcher, \ + patch("alphafold.data.templates.HhsearchHitFeaturizer", return_value="featurizer") as mock_featurizer, \ patch.object(create_features, "AF2DataPipeline", return_value="pipeline") as mock_pipeline: pipeline = create_features.create_pipeline_af2() @@ -1402,8 +1402,8 @@ def test_create_pipeline_af2_uses_hmmsearch_template_stack(tmp_flags): create_features.FLAGS.kalign_binary_path = "/bin/kalign" create_features.FLAGS.obsolete_pdbs_path = "/db/obsolete.dat" - with patch.object(create_features.hmmsearch, "Hmmsearch", return_value="searcher") as mock_searcher, \ - patch.object(create_features.templates, "HmmsearchHitFeaturizer", return_value="featurizer") as mock_featurizer, \ + with patch("alphafold.data.tools.hmmsearch.Hmmsearch", return_value="searcher") as mock_searcher, \ + patch("alphafold.data.templates.HmmsearchHitFeaturizer", return_value="featurizer") as mock_featurizer, \ patch.object(create_features, "AF2DataPipeline", return_value="pipeline") as mock_pipeline: pipeline = create_features.create_pipeline_af2() @@ -1437,8 +1437,8 @@ def test_create_pipeline_af2_skip_msa_returns_template_only_pipeline(tmp_flags): create_features.FLAGS.kalign_binary_path = "/bin/kalign" create_features.FLAGS.obsolete_pdbs_path = "/db/obsolete.dat" - with patch.object(create_features.hmmsearch, "Hmmsearch", return_value="searcher") as mock_searcher, \ - patch.object(create_features.templates, "HmmsearchHitFeaturizer", return_value="featurizer") as mock_featurizer, \ + with patch("alphafold.data.tools.hmmsearch.Hmmsearch", return_value="searcher") as mock_searcher, \ + patch("alphafold.data.templates.HmmsearchHitFeaturizer", return_value="featurizer") as mock_featurizer, \ patch.object(create_features, "AF2DataPipeline") as mock_pipeline: pipeline = create_features.create_pipeline_af2() diff --git a/test/unit/test_af2_feature_finalizer.py b/test/unit/test_af2_feature_finalizer.py index 4cee0b81..c45dd02c 100644 --- a/test/unit/test_af2_feature_finalizer.py +++ b/test/unit/test_af2_feature_finalizer.py @@ -281,6 +281,61 @@ def test_changed_template_settings_are_not_served_from_cache(tmp_path): assert [artifact.name for artifact in moved.written] == ["alpha"] +def test_hhsearch_cache_tracks_pdb70_without_rebuilding_the_msa(tmp_path): + _standard_bundle(tmp_path / "msas") + bundle = tmp_path / "msas" / "alpha_mmseqs_msa.json" + original_bundle = bundle.read_bytes() + options = dict(template_searcher="hhsearch", template_pdb70_database_id="pdb70-v1") + first, _ = _generate(tmp_path, **options) + assert [artifact.name for artifact in first.written] == ["alpha"] + again, searcher = _generate(tmp_path, **options) + assert [artifact.name for artifact in again.reused] == ["alpha"] + assert searcher.queries == [] + + changed, searcher = _generate( + tmp_path, **{**options, "template_pdb70_database_id": "pdb70-v2"} + ) + assert [artifact.name for artifact in changed.written] == ["alpha"] + assert len(searcher.queries) == 1 + assert bundle.read_bytes() == original_bundle + with open(tmp_path / "features" / "alpha.pkl", "rb") as handle: + provenance = pickle.load(handle).local_msa_provenance["af2_templates"] + assert provenance["pdb70_database_id"] == "pdb70-v2" + assert "pdb_seqres_database_id" not in provenance + + +@pytest.mark.parametrize("searcher,unused_id", [ + ("hmmsearch", "template_pdb70_database_id"), + ("hhsearch", "template_seqres_database_id"), +]) +def test_unused_template_database_does_not_invalidate_features(tmp_path, searcher, unused_id): + _standard_bundle(tmp_path / "msas") + options = dict(template_searcher=searcher, template_pdb70_database_id="pdb70-v1") + _generate(tmp_path, **options) + options[unused_id] = "unused-database-v2" + result, recording = _generate(tmp_path, **options) + assert [artifact.name for artifact in result.reused] == ["alpha"] + assert recording.queries == [] + + +@pytest.mark.parametrize("missing", [None, "", " "]) +def test_hhsearch_requires_a_pdb70_identity(tmp_path, missing): + finalizer, _ = _finalizer( + tmp_path, template_searcher="hhsearch", template_pdb70_database_id=missing + ) + with pytest.raises(ValueError, match="template_pdb70_database_id"): + finalizer.generate([]) + + +def test_hhsearch_does_not_require_an_unused_seqres_identity(tmp_path): + _standard_bundle(tmp_path / "msas") + result, _ = _generate( + tmp_path, template_searcher="hhsearch", template_seqres_database_id=None, + template_pdb70_database_id="pdb70-v1", + ) + assert [artifact.name for artifact in result.written] == ["alpha"] + + def test_compressed_output_round_trips(tmp_path): import lzma diff --git a/test/unit/test_af2_template_stack.py b/test/unit/test_af2_template_stack.py new file mode 100644 index 00000000..ca241fff --- /dev/null +++ b/test/unit/test_af2_template_stack.py @@ -0,0 +1,170 @@ +"""Exercise template construction and finalization through their caller interfaces.""" +from unittest.mock import Mock, patch + +import pytest + +from alphapulldown.af2_feature_finalizer import build_af2_template_stack +from alphapulldown.scripts import create_individual_features as legacy +from alphapulldown.scripts import finalize_batch_features as cli +from alphapulldown.scripts._mmseqs2_cli import ( + require_template_flags, + required_template_flag_names, +) +from absl.testing import flagsaver +from types import SimpleNamespace + + +@pytest.fixture +def finalization_flags(tmp_flags, tmp_path): + with flagsaver.flagsaver(): + tmp_flags.msa_input_dir = str(tmp_path / "msas") + tmp_flags.template_seqres_database_id = "seqres-v1" + tmp_flags.template_pdb70_database_id = "pdb70-v1" + tmp_flags.template_mmcif_database_id = "mmcif-v1" + tmp_flags.keep_msas = False + (tmp_path / "a.fasta").write_text(">query\nACDE\n") + yield tmp_flags + + +@pytest.mark.parametrize("hhsearch", [False, True]) +def test_template_stack_resolves_defaults_without_mutating_flags(finalization_flags, hhsearch): + finalization_flags.use_hhsearch = hhsearch + before = finalization_flags.flag_values_dict() + settings = legacy.af2_template_stack_settings() + assert settings.searcher_name == ("hhsearch" if hhsearch else "hmmsearch") + assert settings.pdb70_database_path == "/db/pdb70/pdb70" + assert settings.pdb_seqres_database_path == "/db/pdb_seqres/pdb_seqres.txt" + assert settings.template_mmcif_dir == "/db/pdb_mmcif/mmcif_files" + assert finalization_flags.flag_values_dict() == before + + +def test_template_stack_honors_overrides_without_a_data_root(finalization_flags): + finalization_flags.data_dir = None + finalization_flags.pdb70_database_path = "/custom/pdb70" + settings = legacy.af2_template_stack_settings() + assert settings.pdb70_database_path == "/custom/pdb70" + assert settings.pdb_seqres_database_path is None + + +@pytest.mark.parametrize("hhsearch", [False, True]) +def test_template_factory_builds_the_selected_search_and_featurizer(finalization_flags, hhsearch): + finalization_flags.use_hhsearch = hhsearch + settings = legacy.af2_template_stack_settings() + with patch("alphafold.data.tools.hhsearch.HHSearch") as hh, \ + patch("alphafold.data.tools.hmmsearch.Hmmsearch") as hmm, \ + patch("alphafold.data.templates.HhsearchHitFeaturizer") as hh_features, \ + patch("alphafold.data.templates.HmmsearchHitFeaturizer") as hmm_features: + searcher, featurizer = build_af2_template_stack(settings) + selected_search, selected_features = (hh, hh_features) if hhsearch else (hmm, hmm_features) + assert searcher is selected_search.return_value + assert featurizer is selected_features.return_value + if hhsearch: + hh.assert_called_once_with(binary_path="hhsearch", databases=[settings.pdb70_database_path]) + hmm.assert_not_called() + else: + hmm.assert_called_once_with(binary_path="hmmsearch", hmmbuild_binary_path="hmmbuild", + database_path=settings.pdb_seqres_database_path) + hh.assert_not_called() + assert selected_features.call_args.kwargs == dict( + mmcif_dir=settings.template_mmcif_dir, max_template_date=settings.max_template_date, + max_hits=20, kalign_binary_path="kalign", release_dates_path=None, + obsolete_pdbs_path=settings.obsolete_pdbs_path, + ) + + +@pytest.mark.parametrize("hhsearch", [False, True]) +def test_metadata_contains_only_the_template_resources_used(finalization_flags, hhsearch): + finalization_flags.use_hhsearch = hhsearch + stack = legacy.af2_template_stack_settings() + with patch.object(cli.save_meta_data, "get_meta_dict", return_value={"sentinel": 1}) as metadata: + assert cli.af2_template_metadata(stack) == {"sentinel": 1} + supplied = metadata.call_args.args[0] + assert supplied["kalign_binary_path"] == "kalign" + assert supplied["template_mmcif_dir"] == stack.template_mmcif_dir + if hhsearch: + assert supplied["pdb70_database_path"] == stack.pdb70_database_path + assert "pdb_seqres_database_path" not in supplied + assert "hmmsearch_binary_path" not in supplied + else: + assert supplied["pdb_seqres_database_path"] == stack.pdb_seqres_database_path + assert "pdb70_database_path" not in supplied + assert "hhsearch_binary_path" not in supplied + assert "jackhmmer_binary_path" not in supplied + assert "hhblits_binary_path" not in supplied + + +@pytest.mark.parametrize("backend,hhsearch,required", [ + ("alphafold2", True, "template_pdb70_database_id"), + ("alphafold2", False, "template_seqres_database_id"), + ("alphafold3", True, "template_seqres_database_id"), +]) +def test_template_identity_validation_selects_the_database(finalization_flags, backend, hhsearch, required): + finalization_flags.data_pipeline = backend + finalization_flags.use_hhsearch = hhsearch + assert required_template_flag_names(data_pipeline=backend, use_hhsearch=hhsearch) == ( + required, "template_mmcif_database_id" + ) + require_template_flags(finalization_flags) + setattr(finalization_flags, required, " ") + with pytest.raises(ValueError, match=required): + require_template_flags(finalization_flags) + + +@pytest.mark.parametrize("hhsearch", [False, True]) +def test_af2_finalization_cli_passes_selected_identity_and_requests(finalization_flags, hhsearch): + finalization_flags.use_hhsearch = hhsearch + if hhsearch: + finalization_flags.template_seqres_database_id = None + result = SimpleNamespace(written=(), reused=(), failures=()) + with patch.object(cli, "build_af2_template_stack", return_value=("searcher", "featurizer")), \ + patch.object(cli, "af2_template_metadata", return_value={"software": {}}), \ + patch.object(cli, "Af2FeatureFinalizer") as factory: + factory.return_value.generate.return_value = result + cli.main([]) + settings = factory.call_args.kwargs["settings"] + assert settings.template_searcher == ("hhsearch" if hhsearch else "hmmsearch") + assert settings.template_pdb70_database_id == "pdb70-v1" + assert settings.template_mmcif_database_id == "mmcif-v1" + assert factory.call_args.kwargs["template_searcher"] == "searcher" + [request] = factory.return_value.generate.call_args.args[0] + assert (request.name, request.sequence) == ("query", "ACDE") + + +def test_af3_finalization_cli_keeps_its_seqres_identity(finalization_flags): + finalization_flags.data_pipeline = "alphafold3" + result = SimpleNamespace(written=(), reused=(), failures=()) + with patch.object(legacy, "create_pipeline_af3", return_value="af3-pipeline"), \ + patch.object(legacy, "get_af3_feature_metadata", return_value={}) as metadata, \ + patch.object(cli, "FeatureFinalizer") as factory: + factory.return_value.generate.return_value = result + cli.main([]) + settings = factory.call_args.kwargs["settings"] + assert settings.template_seqres_database_id == "seqres-v1" + assert settings.template_mmcif_database_id == "mmcif-v1" + assert factory.call_args.kwargs["af3_pipeline"] == "af3-pipeline" + assert metadata.call_args.kwargs["skip_msa"] is True + [request] = factory.return_value.generate.call_args.args[0] + assert request.sequence == "ACDE" + + +def test_cli_rejects_missing_pdb70_identity_before_loading_tools(finalization_flags): + finalization_flags.use_hhsearch = True + finalization_flags.template_pdb70_database_id = None + with patch.object(cli, "build_af2_template_stack") as factory: + with pytest.raises(ValueError, match="template_pdb70_database_id"): + cli.main([]) + factory.assert_not_called() + + +def test_cli_reports_per_sequence_failures(finalization_flags): + result = SimpleNamespace(written=(), reused=(), failures=(SimpleNamespace(name="query", error="damaged bundle"),)) + with patch.object(cli, "_finalize_alphafold2", return_value=result): + with pytest.raises(RuntimeError, match=r"query \(damaged bundle\)"): + cli.main([]) + + +@pytest.mark.parametrize("flag", ["skip_msa", "keep_msas", "use_mmseqs2", "path_to_mmt"]) +def test_cli_rejects_incompatible_feature_modes(finalization_flags, flag): + setattr(finalization_flags, flag, "/tmp/mmt" if flag == "path_to_mmt" else True) + with pytest.raises(ValueError, match="cannot be combined"): + cli.main([]) diff --git a/test/unit/test_msa_bundle_validation.py b/test/unit/test_msa_bundle_validation.py new file mode 100644 index 00000000..f5799e2a --- /dev/null +++ b/test/unit/test_msa_bundle_validation.py @@ -0,0 +1,121 @@ +"""Validate persisted alignment data before finalization can trust it.""" + +import json + +import pytest + +from alphapulldown.feature_batch import ( + FeatureRequest, + RNA, + RNA_DATABASE_NAMES, + read_msa_bundle, +) + + +@pytest.fixture +def bundle(tmp_path): + payload = { + "sequence": "ACDE", + "provenance": {"fixture": "bundle-validation"}, + "unpairedMsa": ">query\nACDE\n>hit\nACDF\n", + "pairedMsa": ">query\nACDE\n", + "unpairedDatabaseRows": [ + {"name": "uniref90", "rows": 1}, + {"name": "mgnify", "rows": 0}, + {"name": "small_bfd", "rows": 0}, + ], + } + return tmp_path / "alpha_mmseqs_msa.json", payload + + +@pytest.mark.parametrize( + "damage", ("missing_role", "duplicate_role", "unknown_role", "empty_paired", "empty_unpaired") +) +def test_unusable_alignment_data_is_deleted_before_finalization(bundle, damage): + path, payload = bundle + if damage == "missing_role": + payload["unpairedDatabaseRows"].pop() + elif damage == "duplicate_role": + # Keep every required role and the correct total, but duplicate UniRef90. + # A decoder keyed only by name would silently replace its nonempty span. + payload["unpairedDatabaseRows"].append({"name": "uniref90", "rows": 0}) + elif damage == "unknown_role": + payload["unpairedDatabaseRows"][-1]["name"] = "unknown" + elif damage == "empty_paired": + payload["pairedMsa"] = "" + else: + payload["unpairedMsa"] = "" + payload["unpairedDatabaseRows"][0]["rows"] = 0 + path.write_text(json.dumps(payload)) + + with pytest.raises(ValueError): + read_msa_bundle( + path.parent, FeatureRequest("alpha", "ACDE"), require_row_spans=True + ) + + assert not path.exists(), "An unusable bundle must be removed so the shard repairs it" + + +def test_valid_protein_bundle_keeps_its_query_only_pairing_alignment(bundle): + path, payload = bundle + path.write_text(json.dumps(payload)) + + result = read_msa_bundle( + path.parent, FeatureRequest("alpha", "ACDE"), require_row_spans=True + ) + + assert result == payload + assert path.exists() + + +def test_rna_bundle_has_no_paired_alignment_and_uses_its_own_database_roles(bundle): + path, payload = bundle + payload.update( + sequence="ACGU", moleculeType=RNA, + unpairedMsa=">query\nACGU\n", pairedMsa="", + unpairedDatabaseRows=[{"name": name, "rows": 0} for name in RNA_DATABASE_NAMES], + ) + path.write_text(json.dumps(payload)) + + result = read_msa_bundle( + path.parent, FeatureRequest("alpha", "ACGU", RNA), require_row_spans=True + ) + + assert result == payload + assert path.exists() + + +def test_template_search_failure_preserves_a_valid_af2_msa_bundle(bundle): + pytest.importorskip("alphafold.data.pipeline", reason="needs AlphaFold 2") + from alphapulldown.af2_feature_finalizer import ( + Af2FeatureFinalizationSettings, + Af2FeatureFinalizer, + ) + + class FailingTemplateSearcher: + input_format = "sto" + output_format = "sto" + + def query(self, text): + raise RuntimeError("template database is temporarily unavailable") + + path, payload = bundle + encoded = json.dumps(payload) + path.write_text(encoded) + finalizer = Af2FeatureFinalizer( + settings=Af2FeatureFinalizationSettings( + output_dir=path.parent / "features", msa_input_dir=path.parent, + max_template_date="2050-01-01", template_seqres_database_id="seqres-v1", + template_mmcif_database_id="mmcif-v1", + ), + template_searcher=FailingTemplateSearcher(), + template_featurizer=None, + ) + + result = finalizer.generate([FeatureRequest("alpha", "ACDE")]) + + assert not result.written + assert [(failure.name, failure.error) for failure in result.failures] == [ + ("alpha", "template database is temporarily unavailable") + ] + assert path.read_text() == encoded diff --git a/workflows/mmseqs2-gpu.md b/workflows/mmseqs2-gpu.md index 5dedb163..7395bf0a 100644 --- a/workflows/mmseqs2-gpu.md +++ b/workflows/mmseqs2-gpu.md @@ -52,6 +52,11 @@ RNA databases from `--data_dir`. Final artifact provenance therefore also includes `--max_template_date`, `--template_seqres_database_id`, and `--template_mmcif_database_id`. +AF2 finalization with `--use_hhsearch` requires `--template_pdb70_database_id` +instead of the unused seqres identity. Update the selected immutable identity +when its database is rebuilt, including rebuilds at the same path. Only features +are invalidated; the search-stage MSA bundles remain reusable. + GPU database memory can be substantial. Prefer fast node-local storage and an Ampere-or-newer GPU. A database larger than VRAM can stream from host RAM, but requires enough host memory and runs below peak throughput. From bedcaf6674ee1921ed94688873134c6461a04701 Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Mon, 14 Sep 2026 10:12:32 +0200 Subject: [PATCH 16/17] release: prepare 2.9.0 and sync the workflow guide --- README.md | 243 +++++++++++++++++++++----------------- alphapulldown/__init__.py | 2 +- 2 files changed, 134 insertions(+), 111 deletions(-) diff --git a/README.md b/README.md index 8929eae9..6b5f0b52 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ### Quick install (recommended) ```bash -curl -O https://raw.githubusercontent.com/KosinskiLab/AlphaPulldownSnakemake/2.8.0/install.sh +curl -O https://raw.githubusercontent.com/KosinskiLab/AlphaPulldownSnakemake/2.9.0/install.sh bash install.sh conda activate snake cd AlphaPulldownSnakemake @@ -25,7 +25,7 @@ Useful options: | Option | Meaning | | --- | --- | | `-d, --dest DIR` | working directory to deploy into (default `AlphaPulldownSnakemake`) | -| `-v, --version TAG` | workflow version to deploy (default `2.8.0`) | +| `-v, --version TAG` | workflow version to deploy (default `2.9.0`) | | `-i, --image-dir DIR` | shared container image directory | | `-n, --env-name NAME` | conda environment name (default `snake`) | | `--no-pull` | skip container pre-fetch (Snakemake will fetch on first run) | @@ -43,7 +43,7 @@ Create and activate the conda environment: ```bash conda env create \ -n snake \ - -f https://raw.githubusercontent.com/KosinskiLab/AlphaPulldownSnakemake/2.8.0/workflow/envs/alphapulldown.yaml + -f https://raw.githubusercontent.com/KosinskiLab/AlphaPulldownSnakemake/2.9.0/workflow/envs/alphapulldown.yaml conda activate snake ``` @@ -55,7 +55,7 @@ Then deploy the workflow into a new processing directory for your project: snakedeploy deploy-workflow \ https://github.com/KosinskiLab/AlphaPulldownSnakemake \ AlphaPulldownSnakemake \ - --tag 2.8.0 + --tag 2.9.0 cd AlphaPulldownSnakemake ``` @@ -104,24 +104,25 @@ You can also specify: - **Combinations**: `Q8I2G6:2:1-100+Q8I5K4` (dimer of residues 1-100 plus another protein) - **Copies plus discontinuous regions**: `Q8I2G6:2:1-100:150-200+Q8I5K4` -The same copy/range syntax also works with AlphaFold 3 JSON features -(`--data_pipeline: alphafold3`). Examples: +The same copy/range syntax also works when the workflow generates AlphaFold 3 +JSON features (`--data_pipeline: alphafold3`). Examples: - `Q8I2G6_af3_input.json:1-100` - `Q8I2G6_af3_input.json:1-100:150-200` - `Q8I2G6_af3_input.json:2:1-100:150-200+Q8I5K4_af3_input.json` -When a workflow or wrapper maps a logical token such as `Q8I2G6:1-100:150-200` -to `Q8I2G6_af3_input.json:1-100:150-200`, AlphaPulldown preserves the region -selection and keeps the AF3 JSON feature input as one discontinuous polymer -chain with preserved residue-number gaps, so chopped regions stay intra-chain -and template contacts between retained fragments are not masked as inter-chain -interactions. The original residue IDs are written to the mmCIF author-numbering -fields (`auth_seq_id` and `pdbx_PDB_ins_code`); overlapping IDs are disambiguated -with insertion codes such as `2A`, `2B`, and so on. -This syntax is parsed by the shared `alphapulldown-input-parser` package used by -both AlphaPulldown and AlphaPulldownSnakemake; make sure the execution -environment carries `alphapulldown-input-parser>=0.5.1`. +In that mode the Snakefile rewrites logical inputs such as +`Q8I2G6:1-100:150-200` to the corresponding +`Q8I2G6_af3_input.json:1-100:150-200` feature reference automatically. +AlphaPulldown preserves those discontinuous regions as one gapped polymer +chain with preserved residue-number gaps. +This keeps retained fragments intra-chain, so template contacts between those +fragments are not masked as inter-chain interactions. +The original residue IDs are written to the mmCIF author-numbering fields +(`auth_seq_id` and `pdbx_PDB_ins_code`); overlapping IDs are disambiguated with +insertion codes such as `2A`, `2B`, and so on. +Make sure the prediction container or runtime environment includes a matching +AlphaPulldown build together with `alphapulldown-input-parser>=0.5.1`. @@ -136,7 +137,7 @@ input_files: ### Setting up databases -If you do not already have the AlphaFold databases, `scripts/setup_databases.sh` +If you do not already have the AlphaFold databases, `scripts/setup_databases.sh` from AlphaPulldown fetches them and builds the MMseqs2 versions: ```bash @@ -335,18 +336,18 @@ prediction_container: "/path/to/images/alphafold3-2.5.0.sif" ### GPU compatibility The containers carry their own CUDA runtime (pip `nvidia-*` wheels), so GPU support depends on the -image tag, not on the driver installed on the node. Releases 2.5.0 and newer run on every GPU in the -EMBL cluster, with both AlphaFold 2 and AlphaFold 3: - -- RTX 3090, 24 GB, sm_86 (`gpu21-22`, `gpu29-37`) -- A100, 40 GB, sm_80 (`gpu25-28`) -- A40, 48 GB, sm_86 (`sb03-05` to `sb03-20`) -- L40S, 48 GB, sm_89 (`gpu40-48`) -- H100, 80 GB, sm_90 (`gpu38-39`, and `hgx2-3` in `gpu-training`) -- H200, 141 GB, sm_90 (`hgx4-5` in `gpu-training`) -- B200, 180 GB, sm_100 (`bgx1` in `gpu-training`) -- RTX PRO 4500 Blackwell, 16 GB MIG slices, sm_120 (`gpu60-68`) -- RTX PRO 6000 Blackwell, 96 GB, sm_120 (`gpu51-53`) +image tag, not on the driver installed on the node. Releases 2.5.0 and newer have been tested on +the following GPUs, with both AlphaFold 2 and AlphaFold 3: + +- RTX 3090, 24 GB, sm_86 +- A100, 40 GB, sm_80 +- A40, 48 GB, sm_86 +- L40S, 48 GB, sm_89 +- H100, 80 GB, sm_90 +- H200, 141 GB, sm_90 +- B200, 180 GB, sm_100 +- RTX PRO 4500 Blackwell, 16 GB MIG slices, sm_120 +- RTX PRO 6000 Blackwell, 96 GB, sm_120 On other clusters the same rule applies by compute capability: sm_80 (Ampere) through sm_120 (Blackwell) all work with a 2.5.0 or newer image. @@ -375,7 +376,7 @@ While you are still on an older image, keep inference off those nodes with `slur
-MIG slices (gpu60-68) +MIG slices Those nodes are RTX PRO 4500 cards split into 16 GB `1g.16gb` MIG instances. They need no special `slurm_gres`: a plain `gpu:1` request lands on one slice and SLURM sets @@ -450,15 +451,15 @@ you hit these. uses the biggest tier and spills to host RAM via unified memory. ```yaml - # Example for the EMBL GPU pool; replace nodes with your cluster's (nothing is hard-coded): + # Example GPU tiers; replace these node names with your cluster's: structure_inference_gpu_vram_headroom: 1.0 # <1.0 tolerates that fraction of host spill structure_inference_gpu_tiers: - - {min_vram_gb: 16, nodes: "gpu60,gpu61,gpu62,gpu63,gpu64,gpu65,gpu66,gpu67,gpu68"} # RTX PRO 4500, 16GB MIG - - {min_vram_gb: 24, nodes: "gpu21,gpu22,gpu29,gpu30,gpu31,gpu32,gpu33,gpu34,gpu35,gpu36,gpu37"} - - {min_vram_gb: 40, nodes: "gpu25,gpu26,gpu27,gpu28"} - - {min_vram_gb: 48, nodes: "gpu40,gpu41,gpu42,gpu43,gpu44,gpu45,gpu46,gpu47,gpu48"} - - {min_vram_gb: 80, nodes: "gpu38,gpu39"} - - {min_vram_gb: 96, nodes: "gpu51,gpu52,gpu53"} # RTX PRO 6000 Blackwell + - {min_vram_gb: 16, nodes: "gpu-16gb-01,gpu-16gb-02"} # RTX PRO 4500, 16GB MIG + - {min_vram_gb: 24, nodes: "gpu-24gb-01,gpu-24gb-02"} + - {min_vram_gb: 40, nodes: "gpu-40gb-01,gpu-40gb-02"} + - {min_vram_gb: 48, nodes: "gpu-48gb-01,gpu-48gb-02"} + - {min_vram_gb: 80, nodes: "gpu-80gb-01,gpu-80gb-02"} + - {min_vram_gb: 96, nodes: "gpu-96gb-01,gpu-96gb-02"} # RTX PRO 6000 Blackwell ``` When set this drives `--exclude` per job and **overrides** `structure_inference_gpu_model` (the two @@ -468,7 +469,7 @@ you hit these. partition(s); it excludes nodes by name, so if you span **multiple partitions** (see above) make sure the tier node lists cover every partition you submit to. - **Exclude specific nodes** with `slurm_exclude_nodes`, passed verbatim to `sbatch --exclude` - (e.g. `"gpu51,gpu52"`). `--exclude` is allowed in `slurm_extra` whereas + (e.g. `"gpu-96gb-01,gpu-96gb-02"`). `--exclude` is allowed in `slurm_extra` whereas `--constraint`/`--gres`/`--gpus` are not, so it is the supported way to drop a few nodes while keeping the rest of the partition. The usual reason to need it is a GPU the container image is too old for; see [GPU compatibility](#gpu-compatibility). @@ -512,8 +513,7 @@ read with `nvidia-smi` once the job lands on a node, and the host RAM is the job ceiling within the SLURM allocation so XLA cannot oversubscribe host RAM beyond what the job requested — which would otherwise get the job OOM-killed. The chosen fraction is logged as a `[unified-memory]` line at the top of the job log. Pin a number instead if -you want a fixed multiplier regardless of GPU/RAM (mirrors the EMBL `run_AF_multimer.sh` -convention). +you want a fixed multiplier regardless of GPU/RAM. > The fraction is computed in the job shell rather than via the SLURM executor: the > executor passes the submit environment through with `--export=ALL` but offers no @@ -542,7 +542,8 @@ structure_inference mem = safety * (structure_inference_ram_bytes + per_token_s ``` - `seq_len` is the query length; `N` is the **total residues of the complex** (the - AlphaFold token count, summed over chains and copy numbers). AlphaFold's pair + AlphaFold token count, summed over chains and copy numbers). For AlphaFold 3, `N` is + rounded up to the `--buckets` size the model pads to. AlphaFold's pair representation is `O(N^2)`, hence the quadratic inference term. - **The coefficients default by backend** (selected from `--data_pipeline` / `--fold_backend`). AlphaFold-Multimer (AF2) is heavier than AlphaFold 3 — measured AF2 inference host RSS was @@ -677,53 +678,117 @@ batch_max_tokens: 0 # optional cap on summed residues per batch (0 = no cap)
+### Using precomputed features + +If you have precomputed protein features, specify the directory: + +```yaml +feature_directory: + - "/path/to/directory/with/features/" +``` + +> **Note**: If your features are compressed, set `compress-features: True` in the config. + +### Feature generation flags (`create_individual_features.py`) + +Tweak the feature-generation step by editing `create_feature_arguments` (or by running the script +manually). + +
+Commonly used flags + +- `--data_pipeline {alphafold2,alphafold3}` – choose the feature format to emit. +- `--db_preset {full_dbs,reduced_dbs}` – switch between the full BFD stack or the reduced databases. +- `--use_mmseqs2` – rely on the remote MMseqs2 API; skips local jackhmmer/HHsearch database lookups. + To reuse a3m files generated locally with `colabfold_search`, also set `--use_precomputed_msas=True` + (see the [mmseqs2 manual](https://github.com/KosinskiLab/AlphaPulldown/blob/main/manuals/mmseqs2_manual.md)); + otherwise the remote API is contacted again and your a3m files are overwritten. +- `--skip_msa` – generate query-only single-sequence features instead of running bulk MSA searches. + Use those feature pickles with `run_structure_prediction.py --pair_msa=False`. +- `--use_precomputed_msas` / `--save_msa_files` – reuse stored MSAs (`/.a3m`) or + keep new ones for later runs. Required to reuse precomputed MMseqs2/ColabFold a3m files rather + than regenerating them. +- `--compress_features` – compress the generated features to save space: `*.pkl.xz` for the AlphaFold2 pipeline, `*_af3_input.json.xz` for AlphaFold3. Both are read back transparently, so compressed feature sets can be used directly (this is how the [features database](https://alphapulldown.s3.embl.de) ships them). +- `--skip_existing` – leave existing feature files untouched (safe for reruns). +- `--keep_msas` – refresh **templates only** in features that already exist in `--output_dir`, keeping their MSAs. Use it when the template database or `--max_template_date` has moved but the alignments are still valid: it costs a template search (minutes) instead of a full MSA run (hours). Works for both pipelines — AlphaFold2 features get their `template_*` block replaced, AlphaFold3 features are re-processed through AF3's "search for templates only" path. Proteins with no stored features are generated normally, and it takes precedence over `--skip_existing`. Cannot be combined with `--use_mmseqs2` (which fetches MSAs and templates together) or `--skip_msa` (no MSAs to keep). +- `--seq_index N` – only process the N‑th sequence from the FASTA list. +- `--use_hhsearch`, `--re_search_templates_mmseqs2` – toggle template search implementations. +- `--path_to_mmt`, `--description_file`, `--multiple_mmts` – enable TrueMultimer CSV-driven feature sets. +- `--max_template_date YYYY-MM-DD` – required cutoff for template structures; keeps runs reproducible. + +
+ ### Batched local MMseqs2 features (AlphaFold 2 and 3)
Faster MSAs using local MMseqs2 instead of jackhmmer/HHblits -Off by default. Proteins are split into bounded shards searched with MMseqs2, on GPU or -CPU, and a separate CPU stage turns each chain's alignment into standard features: an -AF3 JSON, or an AF2 `MonomericObject` pickle with `--data_pipeline alphafold2`. The -search is shared, so template work can use CPU and big-memory partitions in parallel. -The remote `--use_mmseqs2` path is unchanged. RNA chains are supported for AlphaFold 3 -once the RNA databases are configured. +Off by default. Missing proteins are split into bounded shards searched with MMseqs2 — +as GPU jobs, or CPU jobs with `use_gpu: false` — and a separate CPU stage turns each +chain's alignment into standard features, so template work can use CPU and big-memory +partitions in parallel. Which features follows `--data_pipeline` in +`create_feature_arguments`: an AF3 JSON per chain, or an AF2 pickle. The remote +`--use_mmseqs2` path is unchanged. RNA chains are supported for AlphaFold 3 once the RNA +databases are configured. ```yaml mmseqs2_features: enabled: true + use_gpu: true temp_dir: /local-fast-scratch/mmseqs + template_database_ids: + pdb_seqres: pdb-seqres-2026-08 + mmcif: pdb-mmcif-2026-08 + # pdb70: pdb70-2026-08 # required for AF2 --use_hhsearch databases: - uniref90: {path: /db/mmseqs/uniref90, identifier: uniref90-2026-08, max_sequences: 10000} - mgnify: {path: /db/mmseqs/mgnify, identifier: mgnify-2026-08, max_sequences: 5000} - small_bfd: {path: /db/mmseqs/small_bfd, identifier: small-bfd-2026-08, max_sequences: 5000} - uniprot: {path: /db/mmseqs/uniprot, identifier: uniprot-2026-08, max_sequences: 50000} + uniref90: {path: /db/mmseqs/uniref90_gpu, identifier: uniref90-2026-08, max_sequences: 10000} + mgnify: {path: /db/mmseqs/mgnify_gpu, identifier: mgnify-2026-08, max_sequences: 5000} + small_bfd: {path: /db/mmseqs/small_bfd_gpu, identifier: small-bfd-2026-08, max_sequences: 5000} + uniprot: {path: /db/mmseqs/uniprot_gpu, identifier: uniprot-2026-08, max_sequences: 50000} ``` The protein databases must be padded (`makepaddedseqdb`); the RNA ones must not be. `scripts/setup_databases.sh --mmseqs` builds them. The native AlphaFold 3 database tree -is still required — these are additive, not a replacement. +is still required — these are additive, not a replacement. Memory and walltime for both +stages are derived from the configured databases; the remaining knobs live in the +ADVANCED section of `config/config.yaml`. + +**The GPU search reads every padded database in full**, about 375 GB for the four +protein ones. On network storage a cold first attempt is bound by that read, not by the +GPU: measured ~150 MB/s from NFS with the GPU idle, about an hour per shard, against +minutes once the node's page cache holds the databases. If first attempts time out, +raise `search_runtime_base_minutes` or stage the databases on local disk; the retry, +with twice the walltime, recovers either way. **Depth is not identical to the native pipeline.** Measured on eight *B. subtilis* proteins it was ~90% of jackhmmer's unpaired depth overall, but only 54–68% on the shallowest families. Whether that costs accuracy is untested, so treat it as opt-in and spot-check your own targets. -**For AlphaFold 2 this is the `reduced_dbs` recipe** — UniRef90, MGnify, small BFD and -UniProt, with no BFD/UniRef30 HHblits arm — built the way native AF2 builds features: -its per-database caps and merge order, templates searched from UniRef90 alone, and -species pairing from an independent UniProt search. The pickles carry the same feature -keys as native ones. Against native `reduced_dbs` features on 12 heterodimers released -after AF2-multimer's training cutoff, top-ranked DockQ averaged 0.56 against 0.59, with 9 -of 12 interfaces acceptable either way; the MSAs are somewhat shallower (numbers in the -docs below). - -Alignments now keep their insertions. MSA bundles written before this change carried -none, so AlphaFold saw an all-zero deletion matrix; they are searched again rather than -reused. +**For AlphaFold 2** set `--data_pipeline: alphafold2` and enable the block above. The +MSA recipe is AlphaFold 2's `reduced_dbs` set (no BFD/UniRef30 HHblits arm); templates +come from the AlphaFold 2 database tree, and `--use_hhsearch` and any explicit template +paths in `create_feature_arguments` reach the finalization stage. The MSA cache +remains reusable when only the template database changes. With +`--use_hhsearch: true`, set `mmseqs2_features.template_database_ids.pdb70` to the +immutable PDB70 build identity; `pdb_seqres` is then unused. Other template searches +require `pdb_seqres`, and every search requires `mmcif`. Update the relevant ID when +rebuilding a database, even at the same path; this invalidates finalized features. +The native MSA arguments do not reach finalization because this stage replaces +that search. Use a matching prediction image, such as +`docker://kosinskilab/alphafold2:2.9.0`, for AlphaFold 2. AlphaFold 2 finalization is +heavier than AlphaFold 3's because template featurization dominates it — median ~1 GB and 2 min, but up to +19 GB and 90 min, set by which structures the templates come from rather than by length +— so its defaults request 16 GB (times the safety factor) and 60 min. Against native +`reduced_dbs` features on 12 heterodimers released after AF2-multimer's training cutoff, +top-ranked DockQ averaged 0.56 against 0.59, with 9 of 12 interfaces acceptable either +way. + +Alignments preserve insertions for both backends. Older MSA bundles that lost +insertions are regenerated automatically. Databases, RNA, AlphaFold 2, tuning, caching and caveats: -[docs/mmseqs2_rna.md](docs/mmseqs2_rna.md). +[AlphaPulldown docs/mmseqs2_rna.md](https://github.com/KosinskiLab/AlphaPulldown/blob/main/docs/mmseqs2_rna.md).
@@ -837,51 +902,9 @@ structure_inference_arguments: --- -### Using precomputed features - -If you have precomputed protein features, specify the directory: - -```yaml -feature_directory: - - "/path/to/directory/with/features/" -``` - -> **Note**: If your features are compressed, set `compress-features: True` in the config. - -### Feature generation flags (`create_individual_features.py`) - -Tweak the feature-generation step by editing `create_feature_arguments` (or by running the script -manually). - -
-Commonly used flags - -- `--data_pipeline {alphafold2,alphafold3}` – choose the feature format to emit. -- `--db_preset {full_dbs,reduced_dbs}` – switch between the full BFD stack or the reduced databases. -- `--use_mmseqs2` – rely on the remote MMseqs2 API; skips local jackhmmer/HHsearch database lookups. - To reuse a3m files generated locally with `colabfold_search`, also set `--use_precomputed_msas=True` - (see the [mmseqs2 manual](https://github.com/KosinskiLab/AlphaPulldown/blob/main/manuals/mmseqs2_manual.md)); - otherwise the remote API is contacted again and your a3m files are overwritten. -- `--skip_msa` – generate query-only single-sequence features instead of running bulk MSA searches. - Use those feature pickles with `run_structure_prediction.py --pair_msa=False`. -- `--use_precomputed_msas` / `--save_msa_files` – reuse stored MSAs (`/.a3m`) or - keep new ones for later runs. Required to reuse precomputed MMseqs2/ColabFold a3m files rather - than regenerating them. -- `--compress_features` – compress the generated features to save space: `*.pkl.xz` for the AlphaFold2 pipeline, `*_af3_input.json.xz` for AlphaFold3. Both are read back transparently, so compressed feature sets can be used directly (this is how the [features database](https://alphapulldown.s3.embl.de) ships them). -- `--skip_existing` – leave existing feature files untouched (safe for reruns). -- `--keep_msas` – refresh **templates only** in features that already exist in `--output_dir`, keeping their MSAs. Use it when the template database or `--max_template_date` has moved but the alignments are still valid: it costs a template search (minutes) instead of a full MSA run (hours). Works for both pipelines — AlphaFold2 features get their `template_*` block replaced, AlphaFold3 features are re-processed through AF3's "search for templates only" path. Proteins with no stored features are generated normally, and it takes precedence over `--skip_existing`. Cannot be combined with `--use_mmseqs2` (which fetches MSAs and templates together) or `--skip_msa` (no MSAs to keep). -- `--seq_index N` – only process the N‑th sequence from the FASTA list. -- `--use_hhsearch`, `--re_search_templates_mmseqs2` – toggle template search implementations. -- `--path_to_mmt`, `--description_file`, `--multiple_mmts` – enable TrueMultimer CSV-driven feature sets. -- `--max_template_date YYYY-MM-DD` – required cutoff for template structures; keeps runs reproducible. - -
- ---- - -## How to Cite +## How to cite -If AlphaPulldown contributed significantly to your research, please cite [the corresponding publication](https://doi.org/10.1093/bioinformatics/btaf115) in *Bioinformatics*: +If AlphaPulldown (or this workflow) contributed to your research, please cite [Molodenskiy et al., 2025](https://doi.org/10.1093/bioinformatics/btaf115): ```bibtex @article{Molodenskiy2025AlphaPulldown2, diff --git a/alphapulldown/__init__.py b/alphapulldown/__init__.py index 892994aa..43ce13db 100755 --- a/alphapulldown/__init__.py +++ b/alphapulldown/__init__.py @@ -1 +1 @@ -__version__ = "2.8.0" +__version__ = "2.9.0" From dd8793e39ab5460a32e9a3bb2c80cd10caf6455d Mon Sep 17 00:00:00 2001 From: Dima Molodenskiy Date: Mon, 14 Sep 2026 10:19:03 +0200 Subject: [PATCH 17/17] docs: sync the configuration guide with the first-run layout --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6b5f0b52..f6b0835d 100644 --- a/README.md +++ b/README.md @@ -71,12 +71,13 @@ images are still shared across projects. See | section | what it holds | | --- | --- | -| **REQUIRED** | inputs, output directory, databases, weights, prediction container | -| **COMMON** | features, backend flags, analysis, batching, SLURM partition | -| **ADVANCED** | memory sizing, length filtering, GPU routing, spilling, CPU partitions | +| **REQUIRED** | inputs, output directory, databases, weights, matching backend settings, SLURM partitions | +| **COMMON** | precomputed features, feature-only runs, analysis, duplicate complexes | +| **ADVANCED** | batching, resource limits, GPU selection, local MMseqs2, detailed report options | -Each key carries a one-line comment naming the section below that documents it in full. -A first run normally only needs the REQUIRED section. +The comments explain each group and point to the relevant section below. A first run +normally only needs REQUIRED. Desktop runs ignore the SLURM settings. Local MMseqs2 +is off by default; its complete configuration is kept together under ADVANCED. ### Setup protein folding jobs