Claude Code Plugins

Community-maintained marketplace

Feedback

coot-model-building

@pemsley/coot
151
0

Best Practices for Model-Building Tools and Refinement

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name coot-model-building
description Best Practices for Model-Building Tools and Refinement

Key Lessons from Chain A Refinement Session

Refinement Best Practices

1. Always Accept Regularizement After Refining

Critical: Call coot.accept_regularizement() after every refine_residues_py() call.

  • Without this, subsequent refinements may fail silently
  • The refinement creates intermediate atoms that must be accepted to update the model
coot.refine_residues_py(0, [["A", 41, ""]])
coot.accept_regularizement()  # Essential!

2. Extend Selection Around Problem Residues

Don't refine problem residues in isolation - include neighboring residues for context.

  • Bad: refine_residues_py(0, [["A", 41, ""]]) - Often fails to correct the model
  • Good: refine_residues_py(0, [["A", 40, ""], ["A", 41, ""], ["A", 42, ""], ["A", 43, ""]])

Recommended approach:

  • For single problem residue: include ±1 or ±2 neighbors
  • For consecutive problem residues: include ±1 neighbor on each end
  • Larger regions (±3-4 residues) can sometimes help severe issues

Example from session:

  • Residues 41-42 had severe Ramachandran outliers
  • Refining just 41-42 failed
  • Refining 40-43 succeeded: Residue 41 improved from p=0.00004 to p=0.308

3. Iterative Refinement Strategy

Sometimes multiple rounds of refinement with different selections help:

  1. First pass: Refine larger region to establish general geometry
  2. Second pass: Refine smaller region to fine-tune specific problem
  3. Check validation after each step
  4. Undo if results get worse

Example workflow:

# First: larger region
coot.refine_residues_py(0, [["A", i, ""] for i in range(40, 44)])
coot.accept_regularizement()
check_validation()  # Did it help?

# Second: targeted refinement
coot.refine_residues_py(0, [["A", 41, ""], ["A", 42, ""], ["A", 43, ""]])
coot.accept_regularizement()
check_validation()  # Better or worse?

# If worse:
coot.apply_undo()

4. Measure Before and After

Always validate changes objectively using:

  • Ramachandran probabilities
  • Density correlation (all-atom and side-chain)
  • Geometry statistics
def check_residue_validation(imol, chain_id, resno):
    """Check both Ramachandran and density correlation"""
    # Get Ramachandran
    rama_data = coot.all_molecule_ramachandran_score_py(imol)
    residue_data = rama_data[5]
    rama_score = None
    for r in residue_data:
        if r[1][0] == chain_id and r[1][1] == resno:
            rama_score = r[2]
            break
    
    # Get density correlation
    corr_data = coot.map_to_model_correlation_stats_per_residue_range_py(
        imol, chain_id, 1, 1, 1
    )
    all_atom_corr = None
    sidechain_corr = None
    
    for r in corr_data[0]:
        if r[0][1] == resno:
            all_atom_corr = r[1][1]
            break
    
    for r in corr_data[1]:
        if r[0][1] == resno:
            sidechain_corr = r[1][1]
            break
    
    return {
        'residue': resno,
        'rama_prob': rama_score,
        'all_atom_corr': all_atom_corr,
        'sidechain_corr': sidechain_corr
    }

# Usage
before = check_residue_validation(0, "A", 41)
coot.refine_residues_py(0, [["A", 40, ""], ["A", 41, ""], ["A", 42, ""], ["A", 43, ""]])
coot.accept_regularizement()
after = check_residue_validation(0, "A", 41)

# Compare and decide
if after['all_atom_corr'] > before['all_atom_corr']:
    # Keep it!
    pass
else:
    # Revert
    coot.apply_undo()

5. Use Undo Liberally

Don't be afraid to revert changes - apply_undo() is your friend.

  • If validation metrics get worse, undo immediately
  • If refinement creates new problems, undo
  • You can try multiple approaches and keep the best result

6. Auto-fit Rotamer for Side-chain Issues

For poor side-chain density correlation, try auto_fit_best_rotamer() first:

# Check if it's a side-chain problem
validation = check_residue_validation(0, "A", 89)
if validation['sidechain_corr'] < 0.5:
    # Try auto-fit rotamer
    score = coot.auto_fit_best_rotamer(0, "A", 89, "", "", 1, 1, 0.01)
    
    if score > 0:  # Positive score is good
        # Check improvement
        after = check_residue_validation(0, "A", 89)
        if after['sidechain_corr'] > validation['sidechain_corr']:
            # Success! (e.g., 0.034 → 0.900)
            pass
        else:
            coot.apply_undo()
    else:
        # Negative score means failure
        coot.apply_undo()

7. Set Refinement to Synchronous Mode

Always call this at the start to make refinement complete immediately:

coot.set_refinement_immediate_replacement(1)

Without this, refinement may be asynchronous and difficult to control programmatically.

8. Navigate to Residue Before Working

Bring residue to screen center so you can watch the refinement:

coot.set_go_to_atom_molecule(0)
coot.set_go_to_atom_chain_residue_atom_name("A", 41, "CA")

This helps with:

  • Visual inspection of the problem
  • Seeing the refinement in real-time
  • Verifying the result makes geometric sense

9. Flipping peptides

If the Ramachandran Plot is poor, try using coot.pepflip(imol, chain_id, res_no, ins_code, alt_conf) followed by a refinement of the residues in the extended region.

10. Flipping side-chains terminal Chi-angle

If the Rotamer score is poor, try using coot.do_180_degree_side_chain_flip() to improve the Rotamer score. It is occassionally useful.

Key Takeaway

Context matters in refinement. Including neighboring residues provides the geometric and density context needed for refinement algorithms to find better solutions, especially for severe outliers.