Repository navigation
Conversation
fetch_target_msa_colabfold.py's seq_from_pdb() derives the target protein's sequence for MSA/ColabFold submission by scanning only lines starting with "ATOM". Selenomethionine (MSE), a very common Se-SAD/MAD crystallographic phasing substitution for methionine, is always recorded as HETATM in PDB format even though it is a genuine part of the polymer chain. Any MSE residue in a fetched RCSB target structure was therefore not just mapped to the wrong letter, it was skipped entirely, silently shortening and frameshifting the derived sequence relative to the true target. The sibling script in the same package, pdb_to_boltz_template_cif.py, reads structures via biotite (which includes HETATM-recorded residues as part of the chain) and already maps MSE -> M in its own dict, so the same pipeline produces two different target sequences for the same target.pdb depending only on which conditioning mode (msa vs template) is selected -- an operational choice, not a biological one. Fix: also accept HETATM lines, but only when the residue name is one we recognize (now including MSE), not a blanket "any HETATM". A naive blanket-HETATM fix would have introduced a new bug: a Ca2+ ion's PDB record has residue name "CA" and atom name "CA" -- the identical four characters as a protein alpha-carbon atom -- and would be picked up as a spurious residue. Verified with two synthetic PDB snippets (not part of the existing test suite, which has no file for this script): 1. ALA-MSE-GLY chain: previous code returned "AG" (MSE silently dropped); fixed code returns "AMG". 2. ALA-GLY chain plus a Ca2+ ion and a water HETATM: both before and after the fix return "AG" -- confirming the fix does not introduce the Ca2+ false-positive a blanket HETATM match would have. Scope note: this repo vendors most skill directories nightly from upstream sources (sync-skills.yml, overwritten via rsync --delete); only directories listed in catalog-exceptions.yml are native and safe to edit here. `workflows/` is explicitly listed as native, so this file is fixable in-repo. The duplicate copy of this same script under `skills/bionemo-agent-toolkit/skills/complexa-binder-design/scripts/` is NOT in that native list and was left untouched, since any edit there would be overwritten on the next sync. Signed-off-by: Siddhardha Nanda <99672439+SID-6921@users.noreply.github.com>
[Medium impact] The change affects PDB-derived target sequences in the Complexa binder-design workflow. The MSE fix is ready, but the shipped skill must be regenerated before merging so the sync check passes. SummaryBoth copies of
Reviews (2) · Last reviewed commit: "Sync generated aggregate and add regress..." · Reviewed by Greptile |
Running scripts/plugin_sync.py --write to propagate the MSE/selenomethionine fix from the source script (workflows/.../complexa-binder-design/scripts/fetch_target_msa_colabfold.py) into the generated aggregate copy at skills/bionemo-agent-toolkit/skills/complexa-binder-design/scripts/fetch_target_msa_colabfold.py, which plugin_sync.py --check confirmed had drifted (the plugin-sync CI gate would have failed on this PR). Also added tests/test_fetch_target_msa_colabfold.py, covering the two synthetic cases verified manually in the original fix: an ALA-MSE-GLY chain must return "AMG", and an ALA-GLY chain with a Ca2+ ion and a water HETATM record must still return "AG" (guards against the fix treating any HETATM as a residue). Both pass against the real script. Signed-off-by: Siddhardha Nanda <99672439+SID-6921@users.noreply.github.com>
Author
|
Checking in — this has been open about a week with no review yet. Happy to address any feedback. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
fetch_target_msa_colabfold.py'sseq_from_pdb()only matches linesstartswith("ATOM"). Selenomethionine (MSE) — a standard Se-SAD/MAD phasing substitution for methionine — is always recorded asHETATMin PDB files, neverATOM, even though it is genuinely part of the polymer chain. The effect isn't just a wrong residue letter: MSE residues are silently dropped from the derived sequence entirely, which is a frameshift/deletion, not a substitution.Verified empirically with a synthetic ALA-MSE-GLY chain: the current code returns
"AG"(2 residues) instead of"AMG"(3 residues).The sibling script
pdb_to_boltz_template_cif.pyin the same package doesn't have this bug, because it parses viabiotite.structure.io.pdb.PDBFile.read(...).get_structure(), which includes HETATM-recorded residues as part of the chain, combined with its own_AA3to1dict that already has"MSE": "M".Fix
"MSE": "M"to theAA3dict.HETATMlines too, but only when the residue name is one we recognize (i.e.,res_name in AA3) — not a blanketstartswith(("ATOM", "HETATM")), which would also pick up non-polymer HETATM records such as aCa2+ion (resNameand atom name both"CA", matching the alpha-carbon atom-name check).Verification
Two synthetic PDB files (no existing test file covers this script):
"AMG".Ca2+ionHETATMand a waterHETATM→ still correctly returns"AG"(confirms the fix doesn't introduce a false positive from the ion).