How to embed a protein in a pre-equilibrated membrane#
Goal#
Drop a protein into a membrane bilayer that has already been built and equilibrated separately (e.g. from CHARMM-GUI, a previous buildMembrane() run, or a downloaded membrane file). This is the alternative to buildMembrane(solute=...), which builds the membrane around the protein from scratch.
Minimal example#
from moleculekit.molecule import Molecule
from htmd.builder.builder import embed
prot = Molecule("./protein-opm-aligned.pdb") # protein, bilayer centre at z=0
memb = Molecule("./equilibrated-membrane.pdb") # pre-built bilayer + waters
system = embed(prot, memb, gap=1.3) # protein into membrane
system.write("./protein-in-membrane.pdb")
embed() removes any residues of the second molecule whose atoms come within gap Å of any atom of the first, then appends the first molecule onto the trimmed second. For protein-in-membrane: pass the protein as mol1 and the membrane as mol2 so the lipids clashing with the protein get removed (carving the hole the protein sits in).
Parameters that matter#
Parameter |
What it does |
|---|---|
|
The two molecules to merge. The function removes residues of |
|
Minimum allowed atom-atom distance in Å. Default 1.3 Å - increase to ~2.0 Å for tighter packing if your equilibrated membrane is already dense. |
Common variations#
Lipid-only removal (keep waters)#
If your pre-equilibrated membrane file has waters and you only want to remove clashing lipids (not waters that happen to sit near the protein):
from htmd.builder.builder import removeLipidsInProtein
# Drop lipids that overlap the protein footprint, leave waters in place.
# Returns a (trimmed_mol2, n_removed_fragments) tuple.
trimmed_memb, n_removed = removeLipidsInProtein(prot, memb, lipidsel="lipids")
system = Molecule()
system.append(trimmed_memb)
system.append(prot)
removeLipidsInProtein() is more surgical than embed - it only touches atoms matching lipidsel, leaving waters and ions alone.
Re-centering the membrane on the protein#
import numpy as np
pcenter = np.mean(prot.coords[:, :2, 0], axis=0) # XY centroid of the protein
mcenter = np.mean(memb.coords[:, :2, 0], axis=0) # XY centroid of the membrane
memb.moveBy([pcenter[0] - mcenter[0],
pcenter[1] - mcenter[1], 0])
system = embed(prot, memb)
buildMembrane(solute=...) does this re-centering automatically. With a pre-built membrane you usually need to do it by hand before embed.
Then run the standard build#
After embed produces a clash-free protein + membrane + (existing) waters, solvate any uncovered extramembrane regions and build under AMBER as usual:
from htmd.builder.solvate import solvate
from htmd.builder import amber
# Drop the membrane's water layer first - we re-solvate to cover the protein's
# extramembrane domains too
system.remove("water", _logger=False)
lipid_mask = system.atomselect("lipid")
xy_min = system.coords[lipid_mask, :2, 0].min(axis=0)
xy_max = system.coords[lipid_mask, :2, 0].max(axis=0)
z_min = system.coords[:, 2, 0].min() - 15
z_max = system.coords[:, 2, 0].max() + 15
system = solvate(system, minmax=[[xy_min[0], xy_min[1], z_min],
[xy_max[0], xy_max[1], z_max]])
amber.build(system, outdir="./build", ionize=True, saltconc=0.15)
Gotchas#
The protein and the membrane must be in the same coordinate frame before
embed. If the membrane sits atz ∈ [50, 90]but the protein is OPM-aligned (z=0is the bilayer centre),embedwill see no overlap and the protein ends up floating in the water layer.embedremoves entire residues ofmol2whose any-atom comes withingapofmol1. For a membrane this means whole lipids get dropped, not partial ones — so the carved hole is the union of every clashing lipid residue (no convex-hull expansion; that’s a separate function,removeLipidsInProtein()).After
embed, the membrane’s water layer probably doesn’t cover the protein’s intracellular / extracellular domains. Always re-solvate with a membrane-aware box (XY from the lipid extent, Z padded above and below the tallest atom) before the build.When in doubt, prefer
buildMembrane(solute=...)- it handles re-centering, carve-out, and waters in one call. Reach forembedonly when you have a pre-equilibrated membrane you want to preserve.
See also#
Build a membrane-embedded protein - the canonical
buildMembrane(solute=...)path.htmd.builder.builder.embed()andhtmd.builder.builder.removeLipidsInProtein()- API references.