| 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:
- First pass: Refine larger region to establish general geometry
- Second pass: Refine smaller region to fine-tune specific problem
- Check validation after each step
- 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.