Preparation of the \(\mu\) opioid receptor with ligand

This is a complex build system as it has several components, the protein, a sodium ion, the ligand and of course the membrane.

from htmd.ui import *
from htmd.home import home
#get the files
shutil.copytree(home()+'/data/mor','/tmp/testmor/pdb')
os.chdir('/tmp/testmor')
path='./01_prepare/'
%ls /tmp/testmor/pdb

Build

#Protein 4dkl is taken from opm

topos  = charmm.defaultTopo() + ['pdb/ff.rtf']
params = charmm.defaultParam() + ['pdb/ff.prm']
prot = Molecule('pdb/4dkl.pdb')
prot.filter('protein and noh and chain B or water within 5 of (chain B and protein)')
pcenter = np.mean(prot.get('coords','protein'), axis=0)
prot = autoSegment(prot, sel='protein')

prot = charmm.build(prot, topo=topos, param=params, outdir= path+'prot',ionize=False)
prot.view()
#Add sodium in the receptor
sod = Molecule('pdb/sod.pdb')
sod.set('segid','S1')
prot.append(sod)

#Use a POPC membrane created with vmd and C36
memb = Molecule('pdb/membrane80by80C36.pdb')
mcenter = np.mean(memb.get('coords'),axis=0)
memb.moveBy(pcenter-mcenter)
mol = prot.copy()
mol.append(memb, collisions=True)  # Append membrane and remove colliding atoms

#Add ligand, previously parametrized using gaamp
lig = Molecule('pdb/QM-min.pdb')
lig.set('segid','L')
lcenter = np.mean(lig.get('coords'),axis=0)
newlcenter = [np.random.uniform(-10, 10), np.random.uniform(-10, 10),  43]
lig.rotateBy(uniformRandomRotation(), lcenter)
lig.moveBy(newlcenter - lcenter)
mol.append(lig)

#Add water
coo = mol.get('coords','lipids or protein')
m = np.min(coo,axis=0) + [0,0,-5]
M = np.max(coo,axis=0) + [0,0,20]
mol = solvate(mol, minmax=np.vstack((m,M)))

#Build
mol = charmm.build(mol, topo=topos, param=params, outdir=os.path.join(path,'build'), saltconc=0.15)

Equilibrate

from htmd.protocols.equilibration_v3 import Equilibration
from htmd.mdengine.acemd.acemd import GroupRestraint

# Use a 10A flat bottom potential to prevent the ligand from diffusing from original position during equilibration
width = np.array([10, 10, 10])
flatbot = GroupRestraint('segname L and noh', width, [(5, '0ns')])

md = Equilibration()
md.runtime = 40
md.timeunits = 'ns'
md.temperature = 300
md.restraints = [flatbot] + md.defaultEquilRestraints('20ns')
md.useconstantratio = True
md.write(os.path.join(path,'build'), os.path.join(path,'equil'))
# Visualize the flat bottom potential box
mol.view('not water')
fbcentre = mol.get('coords', sel='segid L').mean(axis=0).squeeze()
b = VMDBox(np.vstack((fbcentre - width/2, fbcentre + width/2)).T.flatten())
mdx = LocalGPUQueue()
mdx.submit(os.path.join(path, 'equil'))
mdx.wait()

Production

# Read in the last frame of the equilibration
mol = Molecule(os.path.join(path,'equil','structure.psf'))
mol.read(os.path.join(path,'equil','output.xtc'))
mol.dropFrames(keep=mol.numFrames-1)
from htmd.protocols.production_v6 import Production
from htmd.mdengine.acemd.acemd import GroupRestraint

# Apply a flat bottom potential to prevent the ligand from entering from periodic image of the protein
width = np.array([70, 70, 60])

# Center the box at residue 218 which is on the upper side of the protein
fbcentre = mol.get('coords', sel='protein and resid 218').mean(axis=0).squeeze()
flatbot = GroupRestraint('segname L and noh', width, [(5, '0ns')], fbcentre=fbcentre)

md = Production()
md.runtime = 50
md.timeunits = 'ns'
md.temperature = 300
md.restraints = flatbot
md.write(os.path.join(path,'equil'), os.path.join(path,'prod'))
mol.view('not water')
b = VMDBox(np.vstack((fbcentre - width/2, fbcentre + width/2)).T.flatten())