pemsley/coot/figure-making

Claude Code and agent skill by pemsley/coot

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Best practices for creating publication-quality molecular graphics figures in Coot using user-defined colors, ribbons, and molecular representations

Install

npx vskill@latest install pemsley/coot/figure-making

SKILL.md

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
python
# 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
python
# ❌ 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:

  1. Define color palette with set_user_defined_colours_py()
  2. Assign colors to selections with set_user_defined_atom_colour_by_selection_py()
  3. Create representation that uses those colors
  4. 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
python
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
# //! @param secondary_structure_usage_flag 0 (USE_HEADER) i.e. use the secondary structure defined in the header (if any),
# // 1 (DONT_USE) or
# // 2 (CALC_SECONDARY_STRUCTURE)
# // the DONT_USE case will give a worm-like backbone representation
# as a rule of thumb, use 2 when there is no HELIX/SHEET records in the input file.
# if the user wants "worm-like" then they will (should) make it clear that that is the case.
coot.add_ribbon_representation_with_user_defined_colours(imol, "My Figure", secondary_structure_usage_flag)
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.

python
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", secondary_structure_usage_flag)
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:

python
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", secondary_structure_usage_flag)
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.

python
# ❌ 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", secondary_structure_usage_flag)
# ✅ 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", secondary_structure_usage_flag)

Highlighting Specific Features

Extracting Residues to Separate Molecules

To highlight specific residues (like active site residues, ligands, chromophores), extract them to a new molecule:

python
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
#
# //! @param secondary_structure_usage_flag 0 (USE_HEADER) i.e. use the secondary structure defined in the header (if any),
# // 1 (DONT_USE) or
# // 2 (CALC_SECONDARY_STRUCTURE)
# // the DONT_USE case will give a worm-like backbone representation
# as a rule of thumb, use 2 when there is no HELIX/SHEET records in the input file.
# if the user wants "worm-like" then they will (should) make it clear that that is the case.
coot.add_molecular_representation_py(
feature_imol,
selection,
"userDefined", # Use user-defined colors
"Bonds"
secondary_structure_usage_flag
)
# 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
python
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:

python
# 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.

python
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", secondary_structure_usage_flag)
# 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", secondary_structure_usage_flag)
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]

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
157
Repository forks
58
7-day trend score
25

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 30 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/pemsley/coot/figure-making/badge)](https://verified-skill.com/skills/pemsley/coot/figure-making)

Something wrong with this skill or its page? Tell us.