This document contains the core Coot API functions needed for typical validation and model-building workflows. Reading these function signatures at session start eliminates the need for searching.
When experimenting with the various model building tools available to address a particular model-building problem it is useful to create backup checkpoints. This allows you to return to a particular state, so that you can try alternative model-building parameters or functions, or combinations of functions.
python
coot.make_backup_checkpoint(imol, description_string) -> int
# Creates a named checkpoint of the molecule's current state
# Returns: checkpoint index for later restoration
#
# Parameters:
# imol: Model molecule index
# description_string: Human-readable description (e.g., "before rotamer fix")
#
# CRITICAL: Always checkpoint before experimental or risky operations
#
# Example:
checkpoint_idx = coot.make_backup_checkpoint(0, "before rotamer fix")
coot.auto_fit_best_rotamer(0, "A", 42, "", "", 1, 1, 0.01)
# ... check if improvement worked ...
if not improved:
coot.restore_to_backup_checkpoint(0, checkpoint_idx)
coot.restore_to_backup_checkpoint(imol, checkpoint_index)
# Restores molecule to a previously saved checkpoint state
# Parameters:
# imol: Model molecule index
# checkpoint_index: Index returned by make_backup_checkpoint()
coot.compare_current_model_to_backup(imol, checkpoint_index) -> dict
# Compares current model state to a checkpoint to see what changed
# Parameters:
# imol: Model molecule index
# checkpoint_index: Index of checkpoint to compare against
python
coot.set_go_to_atom_chain_residue_atom_name(chain_id, resno, atom_name) -> int
# Centers view on specified atom. Returns 1 on success.
# Example: coot.set_go_to_atom_chain_residue_atom_name("A", 42, "CA")
coot.closest_atom_simple_py() -> list
# Returns: [imol, chain_id, resno, ins_code, atom_name, alt_conf]
# Gets the atom closest to screen center across all displayed molecules
coot.closest_atom_py(imol) -> list
# Same as above but for specific molecule
coot.active_atom_spec_py() -> list
# Returns the currently "active" atom specification (or False if none found)
# (found, (imol, atom_spec))
# found: Boolean indicating if an atom exists close to the center
# molecule_number: Integer molecule ID
# atom_spec: List [chain_id, resno, ins_code, atom_name, alt_conf]
python
coot.residue_info_py(imol, chain_id, resno, ins_code) -> list
# Returns detailed atom information for a residue
#
# Parameters:
# imol: Model molecule index
# chain_id: Chain identifier (e.g., "A")
# resno: Residue number
# ins_code: Insertion code (use "" if none)
#
# Returns: List of atom entries, each containing:
# [[atom_name, alt_conf], [occupancy, b_factor, element, ?], [x, y, z], atom_index]
#
# Example output for a complete CYS:
# [[' N ', ''], [1.0, 12.5, ' N', ''], [x, y, z], 100],
# [[' CA ', ''], [1.0, 11.2, ' C', ''], [x, y, z], 101],
# [[' CB ', ''], [1.0, 14.3, ' C', ''], [x, y, z], 102],
# [[' SG ', ''], [1.0, 18.1, ' S', ''], [x, y, z], 103], # Sulfur!
# [[' C ', ''], [1.0, 10.8, ' C', ''], [x, y, z], 104],
# [[' O ', ''], [1.0, 11.0, ' O', ''], [x, y, z], 105]
#
# NOTE: b_factor may be a list [b_iso, B11, B22, B33, B12, B13, B23] for anisotropic
# Always handle safely:
# def get_b(atom): b = atom[1][1]; return b[0] if isinstance(b, list) else b
# Check for missing atoms in a residue
atoms = coot.residue_info_py(0, "A", 72, "")
atom_names = [a[0][0].strip() for a in atoms]
print(f"Atoms present: {atom_names}")
# Expected atoms for common residues
expected_atoms = {
'CYS': ['N', 'CA', 'CB', 'SG', 'C', 'O'],
'ILE': ['N', 'CA', 'CB', 'CG1', 'CG2', 'CD1', 'C', 'O'],
'GLY': ['N', 'CA', 'C', 'O'],
'PHE': ['N', 'CA', 'CB', 'CG', 'CD1', 'CD2', 'CE1', 'CE2', 'CZ', 'C', 'O'],
}
# Find missing atoms
res_type = coot.residue_name_py(0, "A", 72, "")
if res_type in expected_atoms:
missing = [a for a in expected_atoms[res_type] if a not in atom_names]
if missing:
print(f"WARNING: Missing atoms in {res_type}: {missing}")
python
coot.map_to_model_correlation_stats_per_residue_range_py(
imol, # Model molecule number
chain_id, # Chain identifier (e.g., "A")
imol_map, # Map molecule number
n_per_range, # Residues per window (use 1 for per-residue)
exclude_NOC # 0=include all atoms, 1=exclude backbone N,O,C
) -> list
# Returns: [[all_atom_stats], [sidechain_stats]]
# Each stats list: [[residue_spec, [n_points, correlation]], ...]
# residue_spec = [chain_id, resno, ins_code]
# Example - find worst fitting residues:
stats = coot.map_to_model_correlation_stats_per_residue_range_py(0, "A", 1, 1, 0)
all_atom = stats[0]
worst = sorted(all_atom, key=lambda x: x[1][1])[:5] # 5 worst by correlatio
# Mainchain vs sidechain correlation for a single residue:
coot.map_to_model_correlation_py(imol, residue_specs, neighb_specs, atom_mask_mode, imol_map)
# atom_mask_mode: 0=all atoms, 1=mainchain only, 2=sidechain only
# Use to distinguish backbone problems from sidechain problems before choosing a fix
# Per-atom density probing — the most powerful backbone diagnostic:
sigma = coot.map_sigma_py(imol_map)
d = coot.density_at_point(imol_map, x, y, z) / sigma # value in sigma units
# Backbone atom < 0.5σ = problem; carbonyl O near 0σ with good CA = pepflip needed
python
coot.all_molecule_ramachandran_score_py(imol) -> list
# Returns a list of exactly 6 elements (confirmed from C++ source):
# [0]: overall score (float)
# [1]: n_residues (int)
# [2]: score_non_sec_str (float)
# [3]: n_residues_non_sec_str (int)
# [4]: n_zeros (int)
# [5]: per-residue list (list of per-residue entries)
#
# Each per-residue entry: [[phi, psi], [chain_id, resno, ins_code], probability, [prev_resname, this_resname, next_resname]]
# NOTE: rama_data[5] and rama_data[-1] are equivalent and both correct.
# LOW probability = BAD (outlier). Outlier threshold: prob < 0.02
#
# Example:
# per_res = coot.all_molecule_ramachandran_score_py(imol)[5]
# outliers = [r for r in per_res if r[2] < 0.02]
# worst = min(per_res, key=lambda x: x[2])
coot.rotamer_graphs_py(imol) -> list
# Returns: [[chain_id, resno, ins_code, score_percentage, resname], ...]
# LOW score = BAD rotamer
coot.molecule_atom_overlaps_py(imol, n_pairs) -> list
# Returns worst n_pairs atom overlaps (use -1 for all)
# Each overlap: {
# 'atom-1-spec': [imol, chain, resno, ins, atom_name, alt],
# 'atom-2-spec': [imol, chain, resno, ins, atom_name, alt],
# 'overlap-volume': float # in ų, >5.0 is severe
# }
python
coot.get_hydrogen_bonds_py(imol, selection_1, selection_2, mcdonald_and_thornton) -> list
# Find hydrogen bonds between two atom selections.
# selection_1, selection_2: MMDB selection strings (e.g. "//A/35", "//A")
# Note: selection_1 and selection_2 can be the same, e.g. "//A" for intra-chain H-bonds
# mcdonald_and_thornton: 0 if model has no H atoms, 1 if it does
# Returns list of H-bond candidates, each a list of 12 elements:
# [0] hydrogen atom (dict or None)
# [1] donor atom (dict)
# [2] acceptor atom (dict)
# [3] donor neighbour atom (dict or None)
# [4] acceptor neighbour atom (dict or None)
# [5] angle_1 (float, degrees)
# [6] angle_2 (float, degrees)
# [7] angle_3 (float, degrees)
# [8] distance (float, Å)
# [9] ligand_atom_is_donor (bool)
# [10] hydrogen_is_ligand_atom (bool)
# [11] bond_has_hydrogen_flag (bool)
# Atom dicts have keys: x, y, z, name, element, chain, residue_name, occ, b_iso, altLoc
#
# Example:
hbonds = coot.get_hydrogen_bonds_py(0, "//A/35", "//A", 0)
for hb in hbonds:
donor = hb[1]
acceptor = hb[2]
dist = hb[8]
d_str = donor['chain'] + " " + donor['residue_name'] + " " + donor['name'].strip()
a_str = acceptor['chain'] + " " + acceptor['residue_name'] + " " + acceptor['name'].strip()
print("H-bond: " + d_str + " -> " + a_str + " dist=" + str(dist))
python
coot.refine_residues_py(imol, residue_specs) -> list
# Real-space refinement of specified residues
# residue_specs = [["A", 42, ""], ["A", 43, ""], ...] # [chain, resno, ins_code]
# Returns: ['', status, lights] where:
# status: 0=converged, -2=GSL_CONTINUE (call again), 27=no progress
# lights: list of [name, label, value] refinement statistics, or False
# CRITICAL: if status == -2, call refine_residues_py() again (up to 3 times total)
# Example robust call:
# for _ in range(3):
# result = coot.refine_residues_py(imol, specs)
# if result and result[1] != -2: break
# accepted = coot.accept_moving_atoms_py() # get traffic lights