Skip to content

new commands: isolde validate#32

Open
arohou wants to merge 2 commits into
tristanic:masterfrom
arohou:alr-new-validate-commands
Open

new commands: isolde validate#32
arohou wants to merge 2 commits into
tristanic:masterfrom
arohou:alr-new-validate-commands

Conversation

@arohou
Copy link
Copy Markdown

@arohou arohou commented May 15, 2026

isolde validate: a read-only validation command suite (agent-friendly)

What this PR delivers

Four new ChimeraX commands that expose the same scoring as the subpanels of
ISOLDE's GUI Validate tab as structured, programmatically-consumable
tool calls:

  • isolde validate peptidebonds [model]
  • isolde validate rama [model] [include outliers|allowed|all]
  • isolde validate rotamers [model] [include outliers|nonfavored|all]
  • isolde validate clashes [model]

Plus no-op isolde validate and isolde preflight parent commands that
return a useful "expected one of: ..." error instead of ChimeraX's generic
Unknown command: isolde validate #1.2.

The primary intended consumer is an LLM agent driving ChimeraX through the
MCP server, but the commands are equally useful from scripts:
they're read-only, never start a simulation, and return a Python dict of
summary counts plus an itemised list.

Design decisions

Shared output keywords across all four subcommands, matching the pattern
of ChimeraX's existing clashes / hbonds commands:

  • log true — dump the full per-item table to the ChimeraX HTML log
    (capped at 500 rows so a 5000-clash structure doesn't trash the Reply Log).
  • saveFile <path> — write the full unclipped table to disk.
    .json → structured JSON; anything else → plain UTF-8 text via
    chimerax.io.open_output.
  • limit <n> — cap the inline items list so a giant structure doesn't blow
    up the caller's context window. The returned dict carries truncated,
    returned_count, total_count whenever clipping happens. clashes
    defaults to limit=200; the others have no default cap.

Summary lines tell the caller how to see the full list. Every summary
gets a one-line hint pointing at log true / saveFile <path> whenever
there's something to list. This was added after observing an agent see "499 unique clashes" with no clue how to drill
in.

Friendly parent commands. isolde validate <model> and
isolde preflight <model> (with no subcommand) now raise a UserError
listing the available subcommands instead of ChimeraX's generic
Unknown command. Implemented by registering the parents with a no-op
handler that always raises. Fixing this in ChimeraX's cli.py parser was
considered — it would benefit every hierarchical command in ChimeraX — but
rejected as out of scope here: cli.py is too central to change without
dedicated test coverage.

Overlap with existing rama and rota

There is a deliberate, contained overlap with the older rama and rota
commands. They are not removed and not deprecated:

  • rama / rota (existing) add live 3D annotators to the model and,
    with report=True, dump non-favored residues as a free-text log message.
    They're an interactive convenience for human ISOLDE users — toggle the
    coloured 3D markup, with an optional text dump.
  • isolde validate rama / rotamers (new) are pure read-only data
    accessors — no annotators, no model side effects, structured output,
    paginated, optionally saveable. Intended for agents and scripts.

The two are kept side by side because they serve genuinely different
consumers. The new commands' docstrings point users at the existing
rama / rota for the live-annotator use case.

Minimising the duplication

To avoid two divergent implementations of the same scoring, the actual
compute is factored into pure helpers that both surfaces consume:

Helper Used by
_compute_rama_report(...) isolde validate rama and rama report=true (refactored)
_compute_rotamer_report(...) isolde validate rotamers and rota report=true (refactored)
classify_peptide_bonds(pdm, residues) isolde validate peptidebonds, rama report=true cis/twisted dump, and the GUI PeptideBondDialog (refactored)
clash_atom_label(atom) isolde validate clashes and the GUI ClashesDialog (refactored)

RamaMgr.cis() / twisted() were also tweaked to read their cutoffs from
defaults.CIS_PEPTIDE_BOND_CUTOFF / defaults.TWISTED_PEPTIDE_BOND_DELTA
rather than hardcoded radians(30) / radians(150), so the value lives in
one place.

Net effect: the new isolde validate commands, the GUI Validate panels,
and the legacy rama / rota report=true text dumps all classify
residues / bonds / clashes through the same code paths and give the same
answer.

Files touched

  • isolde/src/validation/cmd.py — new validators, parent commands, shared
    compute helpers, file/log output helpers.
  • isolde/src/validation/clashes.py — extracted clash_atom_label.
  • isolde/src/molobject.pyRamaMgr.cis() / twisted() use
    defaults.* constants.
  • isolde/src/cmd/cmd.py — register the new command group.
  • isolde/src/ui/validation_tab/{clashes.py,peptide_bond.py} — GUI panels
    switched to the shared helpers.
  • isolde/docs/source/commands/isolde.rst — full command reference for
    the new validators.

Out of scope

  • Fixing ChimeraX's cli.py to emit Incomplete command: instead of
    Unknown command: for hierarchical commands missing a sub-action.
    Would benefit every ChimeraX bundle, but cli.py needs more deliberate
    testing than this PR can provide.
  • Tightening the misleading Command 'isolde' is not recognized hint in
    the chimerax MCP bridge. The new parent commands neutralise it for
    isolde validate / isolde preflight, but the bridge heuristic itself
    could still be improved separately.

Alexis Rohou added 2 commits May 14, 2026 16:29
…r agentic control, because otherwise popup windows requiring the human to click were getting in the way.
Adds `isolde validate {peptidebonds,rama,rotamers,clashes}` for
agent / scripted access to the same scoring as the GUI Validate
tab, plus a no-op `isolde validate` parent that lists the
subcommands when called bare (same for `isolde preflight`). Each
subcommand returns a structured dict (summary + items) and accepts
shared `log` / `saveFile` / `limit` keywords; summary lines include
a hint pointing the caller at how to see the full list.

Refactors the GUI peptide-bond and clashes panels and the
`rama` / `rota` `report=True` text dumps to share the new compute
helpers (`_compute_rama_report`, `_compute_rotamer_report`,
`classify_peptide_bonds`, `clash_atom_label`) so the new commands
and the legacy GUI/CLI surfaces stay in lock-step. `RamaMgr.cis()`
and `twisted()` now also read their cutoffs from
`defaults.CIS_PEPTIDE_BOND_CUTOFF` / `defaults.TWISTED_PEPTIDE_BOND_DELTA`
instead of hardcoded `radians(30)` / `radians(150)`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant