Thanks a lot Tristan!
In case anyone else needs this, here is a ChatGPT-polished version of that that can be saved locally and executed in the command line with
runscript path/to/select_incomplete_residues.py
atom-spec.
Best wishes,
Matthias
#!/usr/bin/env python
"""
Incomplete-residue finder
========================
Select **all amino‑acid residues missing one or more heavy template atoms**.
Optionally limit the search to a user‑specified atom selection.
Selection priority (highest → lowest)
-------------------------------------
1. **Command‑line spec** following the script name (quoted if it has spaces).
Example inside ChimeraX:
```
runscript /path/to/select_incomplete_residues.py #1/A
```
2. **Current GUI selection** if no command‑line spec is given.
3. **Whole model** – ISOLDE‑selected model → first atomic model in the session.
import sys
from chimerax.atomic import (
Residue,
concise_residue_spec,
selected_atoms, # ← ChimeraX convenience to get currently selected atoms
)
from chimerax.core.commands import run
from chimerax.core.errors import UserError
# -----------------------------------------------------------------------------
# Helper functions
# -----------------------------------------------------------------------------
def _pick_model(sess):
"""Return an atomic model
if none
is implied by user selection."""
isolde = getattr(sess, "isolde", None)
if isolde and isolde.selected_model is not None:
return isolde.selected_model
for m in sess.models.list():
if hasattr(m, "residues"):
return m
raise UserError("No atomic model with residues found in the session.")
def _atoms_from_spec(sess, spec: str):
"""Return atoms matching
*spec*
(empty collection if spec
is invalid/empty)."""
if not spec:
return None
try:
# Use ChimeraX commands to create the selection, then read it back.
run(sess, "select clear")
run(sess, f"select
{spec}")
return selected_atoms(sess)
except Exception as err:
sess.logger.warning(f"Failed to apply selection '{spec}':
{err}")
run(sess, "select clear")
return None
def _candidate_residues(sess, sel_spec):
"""Determine which residues to analyse based on the priority
rules."""
# 1 – explicit selection string
atoms = _atoms_from_spec(sess, sel_spec)
if atoms and len(atoms):
return atoms.unique_residues
# 2 – current GUI selection
atoms = selected_atoms(sess)
if atoms and len(atoms):
return atoms.unique_residues
# 3 – fall back to whole model
mdl = _pick_model(sess)
return mdl.residues
# -----------------------------------------------------------------------------
# Main logic
# -----------------------------------------------------------------------------
def main(sess):
# Merge all argv tokens into a single selection spec (may contain spaces)
sel_spec = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else None
residues = _candidate_residues(sess, sel_spec)
protein_res = residues[residues.polymer_types == Residue.PT_AMINO]
incomplete = [r for r in protein_res if r.is_missing_heavy_template_atoms()]
if not incomplete:
sess.logger.info("✅
No incomplete residues found in the chosen target set.")
run(sess, "select clear")
return
spec = concise_residue_spec(sess, incomplete)
run(sess, f"select
{spec}")
sess.logger.info(f"⚠️ Selected {len(incomplete)}
incomplete protein residues.")
# -----------------------------------------------------------------------------
# Script entry point (ChimeraX injects 'session')
# -----------------------------------------------------------------------------
try:
session # noqa: F401 – provided by ChimeraX
except NameError as exc:
raise RuntimeError("This script must be run inside UCSF ChimeraX.") from exc
else:
main(session)
From: Tristan Croll <tcroll@altoslabs.com>
Date: Thursday, June 5, 2025 at 13:57
To: Vorländer,Matthias Kopano <matthias.vorlaender@imp.ac.at>
Cc: Alexis Rohou via ChimeraX-users <chimerax-users@cgl.ucsf.edu>
Subject: Re: [chimerax-users] Select all truncated amino acids in model (though ISOLDE?)