Coot Figure-Making Best Practices
Coot Figure-Making Best Practices
This skill provides guidance for creating publication-quality molecular graphics figures in Coot, with emphasis on custom coloring schemes and ribbon representations.
Critical Rule: Use Function Wrappers
ALWAYS wrap complex multi-line code in functions when using the MCP interface.
Why?
Multi-line code executed directly (without a function wrapper) can corrupt the Python interpreter if any error occurs. Function wrappers provide proper error handling and prevent interpreter crashes.
Pattern
# Step 1: Define the function with run_python_multiline()
def my_figure_function():
# ... complex code here ...
return result
# Step 2: Call the function with run_python()
my_figure_function()
Example
# ❌ BAD - Direct multi-line execution (can crash interpreter)
ss_info = coot.get_header_secondary_structure_info(0)
strands = ss_info['strands']
# ... more code ...
# ✅ GOOD - Function wrapper (safe error handling)
def setup_figure():
ss_info = coot.get_header_secondary_structure_info(0)
strands = ss_info['strands']
# ... more code ...
return "Done"
setup_figure()
User-Defined Color Workflow
Overview
Coot’s user-defined color system allows custom coloring of specific selections. The workflow has strict ordering requirements:
- Define color palette with
set_user_defined_colours_py() - Assign colors to selections with
set_user_defined_atom_colour_by_selection_py() - Create representation that uses those colors
- Critical: Recreating a representation requires reassigning ALL colors
Color Indices
- Indices 0-59: Reserved for Coot’s internal colors
- Indices 60+: Available for user-defined colors
- Convention: Start at 60 and increment (60, 61, 62, etc.)
Basic Pattern
def setup_colors():
# Step 1: Define colors (RGB values 0.0-1.0)
blue = [0.3, 0.6, 1.0]
orange = [1.0, 0.5, 0.0]
# Step 2: Set color palette
coot.set_user_defined_colours_py([
(60, blue),
(61, orange)
])
# Step 3: Assign colors to selections (MMDB format)
color_assignments = [
("//A/10-50", 60), # Blue for residues 10-50
("//A/100-150", 61) # Orange for residues 100-150
]
coot.set_user_defined_atom_colour_by_selection_py(imol, color_assignments)
# Step 4: Create representation
coot.add_ribbon_representation_with_user_defined_colours(imol, "My Figure")
return "Colors applied"
Secondary Structure Coloring
Using PDB Header Information
The most reliable way to color by secondary structure is to use the annotations in the PDB header.
def color_by_secondary_structure(imol):
# Get secondary structure from PDB header
ss_info = coot.get_header_secondary_structure_info(imol)
strands = ss_info['strands']
helices = ss_info['helices']
# Build MMDB selection strings for strands
strand_selections = []
for strand in strands:
chain = strand['initChainID']
start = strand['initSeqNum']
end = strand['endSeqNum']
selection = f"//{chain}/{start}-{end}"
strand_selections.append(selection)
# Build MMDB selection strings for helices
helix_selections = []
for helix in helices:
chain = helix['initChainID']
start = helix['initSeqNum']
end = helix['endSeqNum']
selection = f"//{chain}/{start}-{end}"
helix_selections.append(selection)
# Define colors
blue = [0.3, 0.6, 1.0] # Beta strands
purple = [0.5, 0.3, 0.5] # Helices
coot.set_user_defined_colours_py([
(60, blue),
(61, purple)
])
# Assign colors
strand_assignments = [(sel, 60) for sel in strand_selections]
helix_assignments = [(sel, 61) for sel in helix_selections]
all_assignments = strand_assignments + helix_assignments
coot.set_user_defined_atom_colour_by_selection_py(imol, all_assignments)
# Create ribbon
coot.add_ribbon_representation_with_user_defined_colours(imol, "Secondary Structure")
return f"{len(strand_selections)} strands, {len(helix_selections)} helices"
Adding Manual Secondary Structure Annotations
Sometimes secondary structure elements aren’t annotated in the PDB header. You can add them manually:
def add_missing_helix(imol):
# Get existing colors
ss_info = coot.get_header_secondary_structure_info(imol)
strands = ss_info['strands']
helices = ss_info['helices']
# Build all selections (as before)
strand_selections = [...]
helix_selections = [...]
# Add manually identified helix
helix_selections.append("//A/135-139")
# Reassign ALL colors and recreate ribbon
# (must include ALL selections every time)
coot.set_user_defined_colours_py([...])
all_assignments = strand_assignments + helix_assignments
coot.set_user_defined_atom_colour_by_selection_py(imol, all_assignments)
coot.add_ribbon_representation_with_user_defined_colours(imol, "Updated")
return "Helix added"
Critical Rule: Reassign All Colors When Recreating
When you recreate a ribbon representation, you MUST reassign ALL color selections, not just the new ones.
# ❌ BAD - Only assigns new helix, strands lose their color
coot.set_user_defined_atom_colour_by_selection_py(imol, [("//A/135-139", 61)])
coot.add_ribbon_representation_with_user_defined_colours(imol, "New")
# ✅ GOOD - Reassigns everything
all_assignments = strand_assignments + helix_assignments + new_helix
coot.set_user_defined_atom_colour_by_selection_py(imol, all_assignments)
coot.add_ribbon_representation_with_user_defined_colours(imol, "New")
Highlighting Specific Features
Extracting Residues to Separate Molecules
To highlight specific residues (like active site residues, ligands, chromophores), extract them to a new molecule:
def highlight_feature(imol, selection, color_rgb, bond_thickness=10.0):
# Extract to new molecule
feature_imol = coot.new_molecule_by_atom_selection(imol, selection)
if not coot.is_valid_model_molecule(feature_imol):
return -1
# Define color
color_index = 62 # Use a different index than strands/helices
coot.set_user_defined_colours_py([(color_index, color_rgb)])
# Assign color
coot.set_user_defined_atom_colour_by_selection_py(feature_imol, [(selection, color_index)])
# Add representation with thick bonds
coot.add_molecular_representation_py(
feature_imol,
selection,
"userDefined", # Use user-defined colors
"Bonds"
)
# Make bonds thicker for emphasis
coot.set_bond_thickness(feature_imol, bond_thickness)
return feature_imol
# Example: Highlight chromophore in orange
highlight_feature(0, "//A/66", [1.0, 0.5, 0.0], 10.0)
View Setup
Centering and Zooming
def setup_view(chain_id, resno, zoom_level=200):
# Center on specific residue
coot.set_go_to_atom_chain_residue_atom_name(chain_id, resno, "CA")
# Set zoom level
# 150-300: Whole molecule overview
# 50-100: Domain level
# 20-50: Residue detail
coot.set_zoom(zoom_level)
Hiding Bond Representation
For ribbon-only figures, hide the bond representation:
# Hide bonds for molecule 0
coot.set_mol_displayed(0, 0)
# Show bonds again if needed
coot.set_mol_displayed(0, 1)
Complete Example: GFP Beta Barrel Figure
This example creates a publication-quality figure showing GFP’s beta barrel structure with colored secondary structure and highlighted chromophore.
def make_gfp_figure():
"""
Create a figure showing GFP with:
- Blue beta barrel strands
- Dark pastel helices
- Orange chromophore with thick bonds
"""
imol = 0 # GFP molecule
# Get secondary structure
ss_info = coot.get_header_secondary_structure_info(imol)
strands = ss_info['strands']
helices = ss_info['helices']
# Build strand selections
strand_selections = []
for strand in strands:
sel = f"//{strand['initChainID']}/{strand['initSeqNum']}-{strand['endSeqNum']}"
strand_selections.append(sel)
# Build helix selections
helix_selections = []
for helix in helices:
sel = f"//{helix['initChainID']}/{helix['initSeqNum']}-{helix['endSeqNum']}"
helix_selections.append(sel)
# Add manually identified helix (not in PDB header)
helix_selections.append("//A/135-139")
# Define colors
blue = [0.3, 0.6, 1.0] # Beta strands
dark_pastel = [0.5, 0.3, 0.5] # Helices
orange = [1.0, 0.5, 0.0] # Chromophore
coot.set_user_defined_colours_py([
(60, blue),
(61, dark_pastel),
(62, orange)
])
# Assign colors to secondary structure
strand_assignments = [(sel, 60) for sel in strand_selections]
helix_assignments = [(sel, 61) for sel in helix_selections]
all_assignments = strand_assignments + helix_assignments
coot.set_user_defined_atom_colour_by_selection_py(imol, all_assignments)
# Create ribbon
coot.add_ribbon_representation_with_user_defined_colours(imol, "GFP Barrel")
# Hide bonds
coot.set_mol_displayed(imol, 0)
# Extract and highlight chromophore
chrom_imol = coot.new_molecule_by_atom_selection(imol, "//A/66")
coot.set_user_defined_atom_colour_by_selection_py(chrom_imol, [("//A/66", 62)])
coot.add_molecular_representation_py(chrom_imol, "//A/66", "userDefined", "Bonds")
coot.set_bond_thickness(chrom_imol, 10.0)
# Center view
coot.set_go_to_atom_chain_residue_atom_name("A", 100, "CA")
coot.set_zoom(200)
return f"Figure created: {len(strand_selections)} strands, {len(helix_selections)} helices, chromophore"
# To use (must be called with run_python after defining with run_python_multiline):
make_gfp_figure()
Color Scheme Suggestions
Standard Secondary Structure
- Beta strands: Blue
[0.3, 0.6, 1.0] - Alpha helices: Red/Purple
[0.8, 0.2, 0.4]or[0.5, 0.3, 0.5] - Loops: Gray (or leave uncolored)
Highlight Schemes
- Active site: Bright orange
[1.0, 0.5, 0.0] - Substrate binding: Yellow
[1.0, 0.9, 0.0] - Metal coordination: Cyan
[0.0, 0.8, 0.8] - Mutation sites: Magenta
[1.0, 0.0, 1.0]
Domain Coloring
- Domain 1: Blue
[0.2, 0.4, 0.8] - Domain 2: Green
[0.2, 0.8, 0.4] - Domain 3: Orange
[0.9, 0.5, 0.2] - Linker: Gray
[0.6, 0.6, 0.6]
Troubleshooting
Colors Don’t Appear
Problem: Ribbon is gray after setting colors.
Solution: Make sure you call add_ribbon_representation_with_user_defined_colours() AFTER setting colors.
Colors Disappear After Update
Problem: Added new colored region, but existing colors turned red/brown.
Solution: When recreating ribbon, reassign ALL color selections, not just new ones.
Python Interpreter Crashes
Problem: Multi-line code causes “Failed to get main module” error.
Solution: Always use function wrappers with run_python_multiline() then call with run_python().
Feature Not Visible
Problem: Extracted feature (ligand, chromophore) doesn’t show up.
Solution:
- Check molecule is valid:
coot.is_valid_model_molecule(feature_imol) - Ensure
add_molecular_representation_py()succeeded - Verify feature molecule is displayed:
coot.set_mol_displayed(feature_imol, 1)
Graphics Quality Settings for Publication Figures
For publication-quality figures, especially for journal covers or high-impact visualizations, use these graphics settings:
Background Color
Set an appropriate background color for your publication medium:
# Light grey (80%) - excellent for print publications
coot.set_background_colour(0.8, 0.8, 0.8)
# Near-white (98%) - for very light backgrounds
coot.set_background_colour(0.98, 0.98, 0.98)
# Medium grey (50%) - good general purpose
coot.set_background_colour(0.5, 0.5, 0.5)
# White - for manuscripts requiring white backgrounds
coot.set_background_colour(1.0, 1.0, 1.0)
# Black - for dark backgrounds (presentations)
coot.set_background_colour(0.0, 0.0, 0.0)
Outline Mode
Enable outline mode (also called “cel shading” or “toon shading”) for a polished, professional look with dark edges around ribbons and bonds:
# Enable outline mode
coot.set_use_outline(1)
# Disable outline mode
coot.set_use_outline(0)
# Query outline state
state = coot.use_outline_state()
Fancy Graphics Mode
Enable advanced rendering effects for high-quality figures:
def enable_fancy_graphics():
"""Enable all fancy graphics effects for publication figures"""
# Ambient Occlusion (SSAO) - adds subtle shadows in crevices
# Makes surfaces appear more 3D with depth perception
coot.set_use_ambient_occlusion(1)
# Fancy Lighting - enhanced lighting model
# Provides better shading and highlights
coot.set_use_fancy_lighting(1)
# Depth Blur - depth of field effect
# Blurs distant objects for focus effect
coot.set_use_depth_blur(1)
return "Fancy graphics enabled"
def disable_fancy_graphics():
"""Disable fancy graphics for faster rendering"""
coot.set_use_ambient_occlusion(0)
coot.set_use_fancy_lighting(0)
coot.set_use_depth_blur(0)
return "Fancy graphics disabled"
SSAO Fine-Tuning
Ambient occlusion can be fine-tuned for different effects:
# Adjust SSAO strength (default: typically around 1.0)
coot.set_ssao_strength(1.5) # Stronger shadows
# Adjust SSAO radius (default: typically around 0.5)
coot.set_ssao_radius(0.7) # Larger shadow radius
# Adjust SSAO bias (default: typically around 0.025)
coot.set_ssao_bias(0.03) # Reduces shadow artifacts
# Set number of samples for SSAO (more = better quality, slower)
coot.set_ssao_kernel_n_samples(32) # Default is often 16
# Set blur size (0, 1, or 2)
coot.set_ssao_blur_size(1) # Smooths out SSAO shadows
Other Quality Settings
# Anti-aliasing - smooths jagged edges
# Note: May need to restart Coot for this to take effect
coot.set_anti_aliasing(1)
# Enable fog for atmospheric depth
coot.set_use_fog(1)
# Perspective projection (more realistic depth)
coot.set_use_perspective_projection(1)
Complete Publication Setup Example
def setup_publication_graphics():
"""
Configure Coot for creating publication-quality figures
Optimized for journal covers and high-impact visualizations
"""
# Background: 80% grey (excellent for print)
coot.set_background_colour(0.8, 0.8, 0.8)
# Enable outline mode for polished look
coot.set_use_outline(1)
# Enable all fancy graphics effects
coot.set_use_ambient_occlusion(1)
coot.set_use_fancy_lighting(1)
coot.set_use_depth_blur(1)
# Fine-tune SSAO for publication quality
coot.set_ssao_strength(1.2)
coot.set_ssao_radius(0.6)
coot.set_ssao_kernel_n_samples(32)
coot.set_ssao_blur_size(1)
return "Publication graphics settings applied"
def setup_presentation_graphics():
"""
Configure Coot for presentation slides (dark background)
"""
# Black background for presentations
coot.set_background_colour(0.0, 0.0, 0.0)
# Enable outline mode
coot.set_use_outline(1)
# Enable fancy graphics
coot.set_use_ambient_occlusion(1)
coot.set_use_fancy_lighting(1)
coot.set_use_depth_blur(1)
return "Presentation graphics settings applied"
Summary
- Always use function wrappers for complex code
- Set colors BEFORE creating representations
- Reassign ALL colors when recreating ribbons
- Use PDB header secondary structure as the authoritative source
- Extract features to separate molecules for emphasis
- Use consistent color schemes for clarity
- Enable fancy graphics for publication-quality figures
- Choose appropriate background for your publication medium
Following these practices ensures reliable, publication-quality molecular graphics figures in Coot.