bio-pdb-structure-modification
Modify protein structures using Biopython Bio.PDB. Use when transforming coordinates, removing atoms or residues, adding new entities, modifying B-factors and occupancies, or building structures programmatically.
What this skill does
## Version Compatibility
Reference examples tested with: BioPython 1.83+, numpy 1.26+
Before using code patterns, verify installed versions match. If versions differ:
- Python: `pip show <package>` then `help(module.function)` to check signatures
If code throws ImportError, AttributeError, or TypeError, introspect the installed
package and adapt the example to match the actual API rather than retrying.
# Structure Modification
**"Extract a chain from a PDB file"** -> Remove/add atoms, residues, or chains; transform coordinates; modify B-factors and occupancies; build structures programmatically.
- Python: `Bio.PDB.PDBIO()` with `Select` subclass for filtering, `Bio.PDB.Superimposer()` for transforms
Transform coordinates, remove/add entities, modify properties, and build structures programmatically.
## Required Imports
```python
from Bio.PDB import PDBParser, PDBIO, StructureBuilder
from Bio.PDB.Structure import Structure
from Bio.PDB.Model import Model
from Bio.PDB.Chain import Chain
from Bio.PDB.Residue import Residue
from Bio.PDB.Atom import Atom
import numpy as np
```
## Transforming Coordinates
```python
from Bio.PDB import PDBParser, PDBIO
import numpy as np
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Translate all atoms
translation = np.array([10.0, 0.0, 0.0])
for atom in structure.get_atoms():
atom.coord = atom.coord + translation
# Save transformed structure
io = PDBIO()
io.set_structure(structure)
io.save('translated.pdb')
```
## Rotation Around Axis
```python
from Bio.PDB import PDBParser
from Bio.PDB.vectors import rotaxis
import numpy as np
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Rotate around Z axis by 90 degrees
angle = np.radians(90)
axis = np.array([0, 0, 1])
# Get center of mass for rotation origin
coords = np.array([a.coord for a in structure.get_atoms()])
center = coords.mean(axis=0)
# Rotation matrix
cos_a = np.cos(angle)
sin_a = np.sin(angle)
rot_matrix = np.array([
[cos_a, -sin_a, 0],
[sin_a, cos_a, 0],
[0, 0, 1]
])
# Apply rotation around center
for atom in structure.get_atoms():
atom.coord = np.dot(rot_matrix, atom.coord - center) + center
```
## Applying Transformation Matrix
```python
from Bio.PDB import PDBParser
import numpy as np
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# 4x4 transformation matrix (rotation + translation)
# From superimposition or external source
transform = np.array([
[1.0, 0.0, 0.0, 10.0],
[0.0, 1.0, 0.0, 5.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
])
rotation = transform[:3, :3]
translation = transform[:3, 3]
for atom in structure.get_atoms():
atom.coord = np.dot(rotation, atom.coord) + translation
```
## Center Structure at Origin
```python
from Bio.PDB import PDBParser
import numpy as np
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Calculate center
coords = np.array([a.coord for a in structure.get_atoms()])
center = coords.mean(axis=0)
# Translate to origin
for atom in structure.get_atoms():
atom.coord = atom.coord - center
```
## Removing Atoms
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Remove hydrogens
for residue in structure.get_residues():
atoms_to_remove = [a.id for a in residue if a.element == 'H']
for atom_id in atoms_to_remove:
residue.detach_child(atom_id)
io = PDBIO()
io.set_structure(structure)
io.save('no_hydrogens.pdb')
```
## Removing Residues
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Remove water molecules
for model in structure:
for chain in model:
residues_to_remove = [r.id for r in chain if r.id[0] == 'W']
for res_id in residues_to_remove:
chain.detach_child(res_id)
io = PDBIO()
io.set_structure(structure)
io.save('no_water.pdb')
```
## Removing a Chain
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Remove chain B
model = structure[0]
if model.has_id('B'):
model.detach_child('B')
io = PDBIO()
io.set_structure(structure)
io.save('without_chain_B.pdb')
```
## Modifying B-factors
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Set all B-factors to same value
for atom in structure.get_atoms():
atom.bfactor = 20.0
# Or set based on residue property (e.g., conservation score)
conservation_scores = {100: 9.0, 101: 5.0, 102: 3.0} # resnum -> score
for residue in structure.get_residues():
resnum = residue.id[1]
score = conservation_scores.get(resnum, 5.0)
for atom in residue:
atom.bfactor = score * 10 # Scale to B-factor range
io = PDBIO()
io.set_structure(structure)
io.save('modified_bfactor.pdb')
```
## Modifying Occupancy
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Set occupancy for specific chain
for atom in structure[0]['A'].get_atoms():
atom.occupancy = 0.5
io = PDBIO()
io.set_structure(structure)
io.save('modified_occupancy.pdb')
```
## Renumbering Residues
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
chain = structure[0]['A']
# Renumber sequentially starting from 1
new_residues = []
for i, residue in enumerate(chain, start=1):
hetfield, _, icode = residue.id
new_id = (hetfield, i, icode)
residue.id = new_id
new_residues.append(residue)
io = PDBIO()
io.set_structure(structure)
io.save('renumbered.pdb')
```
## Changing Chain ID
```python
from Bio.PDB import PDBParser, PDBIO
parser = PDBParser(QUIET=True)
structure = parser.get_structure('protein', 'protein.pdb')
# Rename chain A to X
model = structure[0]
chain = model['A']
chain.id = 'X'
io = PDBIO()
io.set_structure(structure)
io.save('renamed_chain.pdb')
```
## Building Structure from Scratch
```python
from Bio.PDB.Structure import Structure
from Bio.PDB.Model import Model
from Bio.PDB.Chain import Chain
from Bio.PDB.Residue import Residue
from Bio.PDB.Atom import Atom
from Bio.PDB import PDBIO
import numpy as np
# Create hierarchy
structure = Structure('new_struct')
model = Model(0)
chain = Chain('A')
residue = Residue((' ', 1, ' '), 'ALA', '')
# Add atoms
ca = Atom('CA', np.array([0.0, 0.0, 0.0]), 20.0, 1.0, ' ', 'CA', 1, 'C')
cb = Atom('CB', np.array([1.5, 0.0, 0.0]), 20.0, 1.0, ' ', 'CB', 2, 'C')
residue.add(ca)
residue.add(cb)
chain.add(residue)
model.add(chain)
structure.add(model)
io = PDBIO()
io.set_structure(structure)
io.save('new_structure.pdb')
```
## Using StructureBuilder
```python
from Bio.PDB import StructureBuilder, PDBIO
import numpy as np
sb = StructureBuilder.StructureBuilder()
sb.init_structure('built')
sb.init_model(0)
sb.init_chain('A')
sb.init_seg(' ')
# Add residue with atoms
sb.init_residue('ALA', ' ', 1, ' ')
sb.init_atom('N', np.array([-1.0, 0.0, 0.0]), 20.0, 1.0, ' ', 'N', 1, 'N')
sb.init_atom('CA', np.array([0.0, 0.0, 0.0]), 20.0, 1.0, ' ', 'CA', 2, 'C')
sb.init_atom('C', np.array([1.0, 0.0, 0.0]), 20.0, 1.0, ' ', 'C', 3, 'C')
sb.init_atom('O', np.array([1.5, 1.0, 0.0]), 20.0, 1.0, ' ', 'O', 4, 'O')
sb.init_residue('GLY', ' ', 2, ' ')
sb.init_atom('N', np.array([1.5, -1.0, 0.0]), 20.0, 1.0, ' ', 'N', 5, 'N')
sb.init_atom('CA', np.array([2.5, -1.0, 0.0]), 20.0, 1.0, ' ', 'CA', 6, 'C')
sb.init_atom('C', np.array([3.5, -1.0, 0.0]), 20.0, 1.0, ' ', 'C', 7, 'C')
sb.init_atom('O', np.array([4.0, 0.0, 0.0]), 20.0, 1.0, ' ', 'O', 8, 'O')
structure = sb.get_structure()
io = PDBIO()
io.set_structure(structure)
io.save('built_structure.pdb')
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.