Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
468c0dd2
"platforms/vscode:/vscode.git/clone" did not exist on "2feabb15773638b2b55a1966ba10f56db63baa53"
Commit
468c0dd2
authored
Apr 10, 2017
by
peastman
Browse files
Beginning of support for adding membranes
parent
111844a2
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
205 additions
and
2 deletions
+205
-2
wrappers/python/simtk/openmm/app/modeller.py
wrappers/python/simtk/openmm/app/modeller.py
+198
-2
wrappers/python/simtk/openmm/app/topology.py
wrappers/python/simtk/openmm/app/topology.py
+7
-0
No files found.
wrappers/python/simtk/openmm/app/modeller.py
View file @
468c0dd2
...
@@ -35,10 +35,10 @@ __author__ = "Peter Eastman"
...
@@ -35,10 +35,10 @@ __author__ = "Peter Eastman"
__version__
=
"1.0"
__version__
=
"1.0"
from
simtk.openmm.app
import
Topology
,
PDBFile
,
ForceField
from
simtk.openmm.app
import
Topology
,
PDBFile
,
ForceField
from
simtk.openmm.app.forcefield
import
HAngles
,
AllBonds
,
CutoffNonPeriodic
,
_createResidueSignature
,
_matchResidue
,
DrudeGenerator
from
simtk.openmm.app.forcefield
import
HAngles
,
AllBonds
,
CutoffNonPeriodic
,
CutoffPeriodic
,
_createResidueSignature
,
_matchResidue
,
DrudeGenerator
from
simtk.openmm.app.topology
import
Residue
from
simtk.openmm.app.topology
import
Residue
from
simtk.openmm.vec3
import
Vec3
from
simtk.openmm.vec3
import
Vec3
from
simtk.openmm
import
System
,
Context
,
NonbondedForce
,
CustomNonbondedForce
,
HarmonicBondForce
,
HarmonicAngleForce
,
VerletIntegrator
,
LocalEnergyMinimizer
from
simtk.openmm
import
System
,
Context
,
NonbondedForce
,
CustomNonbondedForce
,
HarmonicBondForce
,
HarmonicAngleForce
,
VerletIntegrator
,
LangevinIntegrator
,
LocalEnergyMinimizer
from
simtk.unit
import
nanometer
,
molar
,
elementary_charge
,
amu
,
gram
,
liter
,
degree
,
sqrt
,
acos
,
is_quantity
,
dot
,
norm
from
simtk.unit
import
nanometer
,
molar
,
elementary_charge
,
amu
,
gram
,
liter
,
degree
,
sqrt
,
acos
,
is_quantity
,
dot
,
norm
import
simtk.unit
as
unit
import
simtk.unit
as
unit
from
.
import
element
as
elem
from
.
import
element
as
elem
...
@@ -47,6 +47,7 @@ import random
...
@@ -47,6 +47,7 @@ import random
import
xml.etree.ElementTree
as
etree
import
xml.etree.ElementTree
as
etree
from
copy
import
deepcopy
from
copy
import
deepcopy
from
math
import
ceil
,
floor
from
math
import
ceil
,
floor
from
collections
import
defaultdict
class
Modeller
(
object
):
class
Modeller
(
object
):
"""Modeller provides tools for editing molecular models, such as adding water or missing hydrogens.
"""Modeller provides tools for editing molecular models, such as adding water or missing hydrogens.
...
@@ -1148,3 +1149,198 @@ class Modeller(object):
...
@@ -1148,3 +1149,198 @@ class Modeller(object):
self
.
topology
=
newTopology
self
.
topology
=
newTopology
self
.
positions
=
newPositions
self
.
positions
=
newPositions
def
addMembrane
(
self
,
forcefield
,
minimumPadding
=
1
*
nanometer
):
patchPdb
=
PDBFile
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'data'
,
'POPC.pdb'
))
# Figure out how many copies of the membrane patch we need in each direction.
proteinPos
=
self
.
positions
.
value_in_unit
(
nanometer
)
proteinMinPos
=
min
(
proteinPos
)
proteinMaxPos
=
max
(
proteinPos
)
proteinSize
=
proteinMaxPos
-
proteinMinPos
proteinCenterPos
=
(
proteinMinPos
+
proteinMaxPos
)
/
2
patchPos
=
patchPdb
.
positions
.
value_in_unit
(
nanometer
)
patchSize
=
patchPdb
.
topology
.
getUnitCellDimensions
().
value_in_unit
(
nanometer
)
patchCenterPos
=
(
min
(
patchPos
)
+
max
(
patchPos
))
/
2
padding
=
minimumPadding
.
value_in_unit
(
nanometer
)
nx
=
ceil
((
proteinSize
[
0
]
+
2
*
padding
)
/
patchSize
[
0
])
ny
=
ceil
((
proteinSize
[
1
]
+
2
*
padding
)
/
patchSize
[
1
])
# Record the bonds for each residue.
resBonds
=
defaultdict
(
list
)
for
bond
in
patchPdb
.
topology
.
bonds
():
resBonds
[
bond
[
0
].
residue
].
append
(
bond
)
# Identify which leaf of the membrane each lipid is in.
numLipidAtoms
=
0
resMeanZ
=
{}
membraneMeanZ
=
0.0
for
res
in
patchPdb
.
topology
.
residues
():
if
res
.
name
!=
'HOH'
:
numResAtoms
=
0
sumZ
=
0.0
for
atom
in
res
.
atoms
():
numResAtoms
+=
1
sumZ
+=
patchPos
[
atom
.
index
][
2
]
numLipidAtoms
+=
numResAtoms
membraneMeanZ
+=
sumZ
resMeanZ
[
res
]
=
sumZ
/
numResAtoms
membraneMeanZ
/=
numLipidAtoms
lipidLeaf
=
dict
((
res
,
0
if
resMeanZ
[
res
]
<
membraneMeanZ
else
1
)
for
res
in
resMeanZ
)
# Compute scaled positions for the protein.
scaledProteinPos
=
[
None
]
*
len
(
proteinPos
)
for
i
,
p
in
enumerate
(
proteinPos
):
p
=
p
-
proteinCenterPos
p
=
Vec3
(
0.5
*
p
[
0
],
0.5
*
p
[
1
],
p
[
2
])
scaledProteinPos
[
i
]
=
p
+
proteinCenterPos
# Create a new Topology for the membrane.
membraneTopology
=
Topology
()
membranePos
=
[]
boxSizeZ
=
patchSize
[
2
]
if
self
.
topology
.
getUnitCellDimensions
()
is
not
None
:
boxSizeZ
=
max
(
boxSizeZ
,
self
.
topology
.
getUnitCellDimensions
()[
2
].
value_in_unit
(
nanometer
))
membraneTopology
.
setUnitCellDimensions
((
nx
*
patchSize
[
0
],
ny
*
patchSize
[
1
],
boxSizeZ
))
# Add membrane patches. DESCRIBE HOW.
overlapCutoff
=
0.22
chain
=
membraneTopology
.
addChain
()
addedWater
=
[]
addedLipids
=
[]
removedFromLeaf
=
[
0
,
0
]
vectors
=
membraneTopology
.
getPeriodicBoxVectors
().
value_in_unit
(
nanometer
)
proteinCells
=
_CellList
(
proteinPos
,
overlapCutoff
,
vectors
,
False
)
scaledProteinCells
=
_CellList
(
scaledProteinPos
,
overlapCutoff
,
vectors
,
False
)
for
x
in
range
(
nx
):
for
y
in
range
(
ny
):
offset
=
proteinCenterPos
-
patchCenterPos
+
Vec3
((
x
-
0.5
*
(
nx
-
1
))
*
patchSize
[
0
],
(
y
-
0.5
*
(
ny
-
1
))
*
patchSize
[
1
],
0
)
for
res
in
patchPdb
.
topology
.
residues
():
resPos
=
[
patchPos
[
atom
.
index
]
+
offset
for
atom
in
res
.
atoms
()]
if
res
.
name
==
'HOH'
:
referencePos
=
proteinPos
cells
=
proteinCells
else
:
referencePos
=
scaledProteinPos
cells
=
scaledProteinCells
overlap
=
False
nearest
=
nx
*
patchSize
[
0
]
for
index
,
atom
in
enumerate
(
res
.
atoms
()):
pos
=
resPos
[
index
]
for
atom
in
cells
.
neighbors
(
pos
):
distance
=
norm
(
pos
-
referencePos
[
atom
])
if
distance
<
overlapCutoff
:
overlap
=
True
break
nearest
=
min
(
nearest
,
distance
)
if
overlap
:
break
if
res
.
name
==
'HOH'
:
if
not
overlap
:
addedWater
.
append
((
res
,
resPos
))
else
:
if
overlap
:
removedFromLeaf
[
lipidLeaf
[
res
]]
+=
1
else
:
addedLipids
.
append
((
nearest
,
res
,
resPos
))
# Add the solvent.
newAtoms
=
{}
solventChain
=
membraneTopology
.
addChain
()
for
(
residue
,
pos
)
in
addedWater
:
newResidue
=
membraneTopology
.
addResidue
(
residue
.
name
,
solventChain
,
residue
.
id
)
for
atom
in
residue
.
atoms
():
newAtom
=
membraneTopology
.
addAtom
(
atom
.
name
,
atom
.
element
,
newResidue
,
atom
.
id
)
newAtoms
[
atom
]
=
newAtom
membranePos
+=
pos
for
bond
in
resBonds
[
residue
]:
membraneTopology
.
addBond
(
newAtoms
[
bond
[
0
]],
newAtoms
[
bond
[
1
]],
bond
.
type
,
bond
.
order
)
# Add the lipids.
lipidChain
=
membraneTopology
.
addChain
()
for
(
nearest
,
residue
,
pos
)
in
addedLipids
:
newResidue
=
membraneTopology
.
addResidue
(
residue
.
name
,
lipidChain
,
residue
.
id
)
for
atom
in
residue
.
atoms
():
newAtom
=
membraneTopology
.
addAtom
(
atom
.
name
,
atom
.
element
,
newResidue
,
atom
.
id
)
newAtoms
[
atom
]
=
newAtom
membranePos
+=
pos
for
bond
in
resBonds
[
residue
]:
membraneTopology
.
addBond
(
newAtoms
[
bond
[
0
]],
newAtoms
[
bond
[
1
]],
bond
.
type
,
bond
.
order
)
# Create a System for the lipids, then add in the protein as stationary particles.
system
=
forcefield
.
createSystem
(
membraneTopology
,
nonbondedMethod
=
CutoffPeriodic
)
proteinSystem
=
forcefield
.
createSystem
(
self
.
topology
,
nonbondedMethod
=
CutoffPeriodic
)
numMembraneParticles
=
system
.
getNumParticles
()
numProteinParticles
=
proteinSystem
.
getNumParticles
()
for
i
in
range
(
numProteinParticles
):
system
.
addParticle
(
0.0
)
for
f1
,
f2
in
zip
(
system
.
getForces
(),
proteinSystem
.
getForces
()):
if
isinstance
(
f1
,
NonbondedForce
):
for
i
in
range
(
numProteinParticles
):
f1
.
addParticle
(
*
f2
.
getParticleParameters
(
i
))
for
j
in
range
(
i
):
f1
.
addException
(
i
+
numMembraneParticles
,
j
+
numMembraneParticles
,
0.0
,
1.0
,
0.0
)
mergedPositions
=
membranePos
+
scaledProteinPos
# Run a simulation while slowly scaling up the protein so membrane can relax.
integrator
=
LangevinIntegrator
(
10.0
,
50.0
,
0.001
)
context
=
Context
(
system
,
integrator
)
context
.
setPositions
(
mergedPositions
)
LocalEnergyMinimizer
.
minimize
(
context
,
10.0
,
30
)
for
i
in
range
(
50
):
print
(
i
,
context
.
getState
(
getEnergy
=
True
).
getPotentialEnergy
(),
context
.
getState
().
getTime
())
weight1
=
i
/
49.0
weight2
=
1.0
-
weight1
mergedPositions
=
context
.
getState
(
getPositions
=
True
).
getPositions
().
value_in_unit
(
nanometer
)
for
j
in
range
(
len
(
proteinPos
)):
mergedPositions
[
j
+
numMembraneParticles
]
=
(
weight1
*
proteinPos
[
j
]
+
weight2
*
scaledProteinPos
[
j
])
context
.
setPositions
(
mergedPositions
)
integrator
.
step
(
20
)
# Add the membrane to the protein.
self
.
add
(
membraneTopology
,
context
.
getState
(
getPositions
=
True
).
getPositions
()[:
numMembraneParticles
])
class
_CellList
(
object
):
"""This class organizes atom positions into cells, so the neighbors of a point can be quickly retrieved"""
def
__init__
(
self
,
positions
,
maxCutoff
,
vectors
,
periodic
):
self
.
positions
=
positions
[:]
self
.
cells
=
{}
self
.
numCells
=
tuple
((
max
(
1
,
int
(
floor
(
vectors
[
i
][
i
]
/
maxCutoff
)))
for
i
in
range
(
3
)))
self
.
cellSize
=
tuple
((
vectors
[
i
][
i
]
/
self
.
numCells
[
i
]
for
i
in
range
(
3
)))
invBox
=
Vec3
(
1.0
/
vectors
[
0
][
0
],
1.0
/
vectors
[
1
][
1
],
1.0
/
vectors
[
2
][
2
])
for
i
in
range
(
len
(
self
.
positions
)):
pos
=
self
.
positions
[
i
]
if
periodic
:
pos
=
pos
-
floor
(
pos
[
2
]
*
invBox
[
2
])
*
vectors
[
2
]
pos
-=
floor
(
pos
[
1
]
*
invBox
[
1
])
*
vectors
[
1
]
pos
-=
floor
(
pos
[
0
]
*
invBox
[
0
])
*
vectors
[
0
]
self
.
positions
[
i
]
=
pos
cell
=
tuple
((
int
(
floor
(
pos
[
j
]
/
self
.
cellSize
[
j
]))
%
self
.
numCells
[
j
]
for
j
in
range
(
3
)))
if
cell
in
self
.
cells
:
self
.
cells
[
cell
].
append
(
i
)
else
:
self
.
cells
[
cell
]
=
[
i
]
def
neighbors
(
self
,
pos
):
centralCell
=
tuple
((
int
(
floor
(
pos
[
i
]
/
self
.
cellSize
[
i
]))
for
i
in
range
(
3
)))
offsets
=
(
-
1
,
0
,
1
)
for
i
in
offsets
:
for
j
in
offsets
:
for
k
in
offsets
:
cell
=
((
centralCell
[
0
]
+
i
+
self
.
numCells
[
0
])
%
self
.
numCells
[
0
],
(
centralCell
[
1
]
+
j
+
self
.
numCells
[
1
])
%
self
.
numCells
[
1
],
(
centralCell
[
2
]
+
k
+
self
.
numCells
[
2
])
%
self
.
numCells
[
2
])
if
cell
in
self
.
cells
:
for
atom
in
self
.
cells
[
cell
]:
yield
atom
wrappers/python/simtk/openmm/app/topology.py
View file @
468c0dd2
...
@@ -112,6 +112,11 @@ class Topology(object):
...
@@ -112,6 +112,11 @@ class Topology(object):
"""
"""
return
len
(
self
.
_chains
)
return
len
(
self
.
_chains
)
def
getNumBonds
(
self
):
"""Return the number of bonds in the Topology.
"""
return
len
(
self
.
_bonds
)
def
addChain
(
self
,
id
=
None
):
def
addChain
(
self
,
id
=
None
):
"""Create a new Chain and add it to the Topology.
"""Create a new Chain and add it to the Topology.
...
@@ -329,6 +334,8 @@ class Topology(object):
...
@@ -329,6 +334,8 @@ class Topology(object):
toAtom
=
bond
[
1
]
toAtom
=
bond
[
1
]
if
fromAtom
in
atomMaps
[
fromResidue
]
and
toAtom
in
atomMaps
[
toResidue
]:
if
fromAtom
in
atomMaps
[
fromResidue
]
and
toAtom
in
atomMaps
[
toResidue
]:
self
.
addBond
(
atomMaps
[
fromResidue
][
fromAtom
],
atomMaps
[
toResidue
][
toAtom
])
self
.
addBond
(
atomMaps
[
fromResidue
][
fromAtom
],
atomMaps
[
toResidue
][
toAtom
])
elif
name
==
'POP'
:
print
(
fromAtom
,
toAtom
)
def
createDisulfideBonds
(
self
,
positions
):
def
createDisulfideBonds
(
self
,
positions
):
"""Identify disulfide bonds based on proximity and add them to the
"""Identify disulfide bonds based on proximity and add them to the
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment