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
ba907d8a
Unverified
Commit
ba907d8a
authored
Sep 04, 2023
by
Peter Eastman
Committed by
GitHub
Sep 04, 2023
Browse files
Added residueTemplates argument to more methods (#4211)
parent
0a3a914f
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
64 additions
and
23 deletions
+64
-23
wrappers/python/openmm/app/forcefield.py
wrappers/python/openmm/app/forcefield.py
+19
-8
wrappers/python/openmm/app/modeller.py
wrappers/python/openmm/app/modeller.py
+45
-15
No files found.
wrappers/python/openmm/app/forcefield.py
View file @
ba907d8a
...
@@ -1042,7 +1042,7 @@ class ForceField(object):
...
@@ -1042,7 +1042,7 @@ class ForceField(object):
bondedToAtom
=
[
sorted
(
b
)
for
b
in
bondedToAtom
]
bondedToAtom
=
[
sorted
(
b
)
for
b
in
bondedToAtom
]
return
bondedToAtom
return
bondedToAtom
def
getUnmatchedResidues
(
self
,
topology
):
def
getUnmatchedResidues
(
self
,
topology
,
residueTemplates
=
dict
()
):
"""Return a list of Residue objects from specified topology for which no forcefield templates are available.
"""Return a list of Residue objects from specified topology for which no forcefield templates are available.
.. CAUTION:: This method is experimental, and its API is subject to change.
.. CAUTION:: This method is experimental, and its API is subject to change.
...
@@ -1051,6 +1051,12 @@ class ForceField(object):
...
@@ -1051,6 +1051,12 @@ class ForceField(object):
----------
----------
topology : Topology
topology : Topology
The Topology whose residues are to be checked against the forcefield residue templates.
The Topology whose residues are to be checked against the forcefield residue templates.
residueTemplates : dict=dict()
Specifies which template to use for particular residues. The keys should be Residue
objects from the Topology, and the values should be the names of the templates to
use for them. This is useful when a ForceField contains multiple templates that
can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
monoatomic iron ion in the Topology).
Returns
Returns
-------
-------
...
@@ -1064,8 +1070,13 @@ class ForceField(object):
...
@@ -1064,8 +1070,13 @@ class ForceField(object):
bondedToAtom
=
self
.
_buildBondedToAtomList
(
topology
)
bondedToAtom
=
self
.
_buildBondedToAtomList
(
topology
)
unmatched_residues
=
list
()
# list of unmatched residues
unmatched_residues
=
list
()
# list of unmatched residues
for
res
in
topology
.
residues
():
for
res
in
topology
.
residues
():
# Attempt to match one of the existing templates.
if
res
in
residueTemplates
:
[
template
,
matches
]
=
self
.
_getResidueTemplateMatches
(
res
,
bondedToAtom
)
# Make sure the specified template matches.
template
=
self
.
_templates
[
residueTemplates
[
res
]]
matches
=
compiled
.
matchResidueToTemplate
(
res
,
template
,
bondedToAtom
,
False
,
False
)
else
:
# Attempt to match one of the existing templates.
[
template
,
matches
]
=
self
.
_getResidueTemplateMatches
(
res
,
bondedToAtom
)
if
matches
is
None
:
if
matches
is
None
:
# No existing templates match.
# No existing templates match.
unmatched_residues
.
append
(
res
)
unmatched_residues
.
append
(
res
)
...
@@ -1179,11 +1190,11 @@ class ForceField(object):
...
@@ -1179,11 +1190,11 @@ class ForceField(object):
their total mass the same. If rigidWater is used to make water molecules
their total mass the same. If rigidWater is used to make water molecules
rigid, then water hydrogens are not altered.
rigid, then water hydrogens are not altered.
residueTemplates : dict=dict()
residueTemplates : dict=dict()
Key: Topology Residue object
Specifies which template to use for particular residues. The keys should be Residue
Value: string, name of _TemplateData residue template object to use for (Key) residue.
objects from the Topology, and the values should be the names of the templates to
This allows user to specify which
template t
o apply to particular Residues
use for them. This is useful when a ForceField contains multiple
template
s
t
hat
in the event that multiple matching templates are available (e.g Fe2+ and Fe3+
can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
templates in the ForceField for a
monoatomic iron ion in the
t
opology).
monoatomic iron ion in the
T
opology).
ignoreExternalBonds : boolean=False
ignoreExternalBonds : boolean=False
If true, ignore external bonds when matching residues to templates. This is
If true, ignore external bonds when matching residues to templates. This is
useful when the Topology represents one piece of a larger molecule, so chains are
useful when the Topology represents one piece of a larger molecule, so chains are
...
...
wrappers/python/openmm/app/modeller.py
View file @
ba907d8a
...
@@ -257,7 +257,7 @@ class Modeller(object):
...
@@ -257,7 +257,7 @@ class Modeller(object):
self
.
topology
=
newTopology
self
.
topology
=
newTopology
self
.
positions
=
newPositions
self
.
positions
=
newPositions
def
_addIons
(
self
,
forcefield
,
numWaters
,
replaceableMols
,
ionCutoff
=
0.05
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
def
_addIons
(
self
,
forcefield
,
numWaters
,
replaceableMols
,
ionCutoff
=
0.05
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
,
residueTemplates
=
dict
()
):
"""Adds ions to the system by replacing certain molecules.
"""Adds ions to the system by replacing certain molecules.
Parameters
Parameters
...
@@ -281,6 +281,12 @@ class Modeller(object):
...
@@ -281,6 +281,12 @@ class Modeller(object):
Note that only monovalent ions are currently supported.
Note that only monovalent ions are currently supported.
neutralize : bool=True
neutralize : bool=True
whether to add ions to neutralize the system
whether to add ions to neutralize the system
residueTemplates : dict=dict()
specifies which template the ForceField should use for particular residues. The keys
should be Residue objects from the Topology, and the values should be the names of the
templates to use for them. This is useful when a ForceField contains multiple templates
that can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
monoatomic iron ion in the Topology).
"""
"""
posIonElements
=
{
'Cs+'
:
elem
.
cesium
,
'K+'
:
elem
.
potassium
,
posIonElements
=
{
'Cs+'
:
elem
.
cesium
,
'K+'
:
elem
.
potassium
,
...
@@ -302,7 +308,7 @@ class Modeller(object):
...
@@ -302,7 +308,7 @@ class Modeller(object):
negativeElement
=
negIonElements
[
negativeIon
]
negativeElement
=
negIonElements
[
negativeIon
]
# Determine the total charge of the system
# Determine the total charge of the system
system
=
forcefield
.
createSystem
(
self
.
topology
)
system
=
forcefield
.
createSystem
(
self
.
topology
,
residueTemplates
=
residueTemplates
)
for
i
in
range
(
system
.
getNumForces
()):
for
i
in
range
(
system
.
getNumForces
()):
if
isinstance
(
system
.
getForce
(
i
),
NonbondedForce
):
if
isinstance
(
system
.
getForce
(
i
),
NonbondedForce
):
nonbonded
=
system
.
getForce
(
i
)
nonbonded
=
system
.
getForce
(
i
)
...
@@ -375,7 +381,7 @@ class Modeller(object):
...
@@ -375,7 +381,7 @@ class Modeller(object):
self
.
topology
=
modeller
.
topology
self
.
topology
=
modeller
.
topology
self
.
positions
=
modeller
.
positions
self
.
positions
=
modeller
.
positions
def
addSolvent
(
self
,
forcefield
,
model
=
'tip3p'
,
boxSize
=
None
,
boxVectors
=
None
,
padding
=
None
,
numAdded
=
None
,
boxShape
=
'cube'
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
def
addSolvent
(
self
,
forcefield
,
model
=
'tip3p'
,
boxSize
=
None
,
boxVectors
=
None
,
padding
=
None
,
numAdded
=
None
,
boxShape
=
'cube'
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
,
residueTemplates
=
dict
()
):
"""Add solvent (both water and ions) to the model to fill a periodic box.
"""Add solvent (both water and ions) to the model to fill a periodic box.
The algorithm works as follows:
The algorithm works as follows:
...
@@ -439,6 +445,12 @@ class Modeller(object):
...
@@ -439,6 +445,12 @@ class Modeller(object):
Note that only monovalent ions are currently supported.
Note that only monovalent ions are currently supported.
neutralize : bool=True
neutralize : bool=True
whether to add ions to neutralize the system
whether to add ions to neutralize the system
residueTemplates : dict=dict()
specifies which template the ForceField should use for particular residues. The keys
should be Residue objects from the Topology, and the values should be the names of the
templates to use for them. This is useful when a ForceField contains multiple templates
that can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
monoatomic iron ion in the Topology).
"""
"""
if
len
([
x
for
x
in
(
boxSize
,
boxVectors
,
padding
,
numAdded
)
if
x
is
not
None
])
>
1
:
if
len
([
x
for
x
in
(
boxSize
,
boxVectors
,
padding
,
numAdded
)
if
x
is
not
None
])
>
1
:
raise
ValueError
(
'At most one of the following arguments may be specified: boxSize, boxVectors, padding, numAdded'
)
raise
ValueError
(
'At most one of the following arguments may be specified: boxSize, boxVectors, padding, numAdded'
)
...
@@ -504,7 +516,7 @@ class Modeller(object):
...
@@ -504,7 +516,7 @@ class Modeller(object):
# Have the ForceField build a System for the solute from which we can determine van der Waals radii.
# Have the ForceField build a System for the solute from which we can determine van der Waals radii.
system
=
forcefield
.
createSystem
(
self
.
topology
)
system
=
forcefield
.
createSystem
(
self
.
topology
,
residueTemplates
=
residueTemplates
)
nonbonded
=
None
nonbonded
=
None
for
i
in
range
(
system
.
getNumForces
()):
for
i
in
range
(
system
.
getNumForces
()):
if
isinstance
(
system
.
getForce
(
i
),
NonbondedForce
):
if
isinstance
(
system
.
getForce
(
i
),
NonbondedForce
):
...
@@ -644,7 +656,7 @@ class Modeller(object):
...
@@ -644,7 +656,7 @@ class Modeller(object):
numTotalWaters
=
len
(
waterPos
)
numTotalWaters
=
len
(
waterPos
)
# Add ions to neutralize the system.
# Add ions to neutralize the system.
self
.
_addIons
(
forcefield
,
numTotalWaters
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
)
self
.
_addIons
(
forcefield
,
numTotalWaters
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
,
residueTemplates
=
residueTemplates
)
def
_computeBoxVectors
(
self
,
width
,
boxShape
):
def
_computeBoxVectors
(
self
,
width
,
boxShape
):
"""Compute the periodic box vectors given a box width and shape."""
"""Compute the periodic box vectors given a box width and shape."""
...
@@ -721,7 +733,7 @@ class Modeller(object):
...
@@ -721,7 +733,7 @@ class Modeller(object):
terminal
=
hydrogen
.
attrib
[
'terminal'
]
terminal
=
hydrogen
.
attrib
[
'terminal'
]
data
.
hydrogens
.
append
(
Modeller
.
_Hydrogen
(
hydrogen
.
attrib
[
'name'
],
hydrogen
.
attrib
[
'parent'
],
maxph
,
atomVariants
,
terminal
))
data
.
hydrogens
.
append
(
Modeller
.
_Hydrogen
(
hydrogen
.
attrib
[
'name'
],
hydrogen
.
attrib
[
'parent'
],
maxph
,
atomVariants
,
terminal
))
def
addHydrogens
(
self
,
forcefield
=
None
,
pH
=
7.0
,
variants
=
None
,
platform
=
None
):
def
addHydrogens
(
self
,
forcefield
=
None
,
pH
=
7.0
,
variants
=
None
,
platform
=
None
,
residueTemplates
=
dict
()
):
"""Add missing hydrogens to the model.
"""Add missing hydrogens to the model.
Some residues can exist in multiple forms depending on the pH and properties of the local environment. These
Some residues can exist in multiple forms depending on the pH and properties of the local environment. These
...
@@ -787,6 +799,12 @@ class Modeller(object):
...
@@ -787,6 +799,12 @@ class Modeller(object):
platform : Platform=None
platform : Platform=None
the Platform to use when computing the hydrogen atom positions. If
the Platform to use when computing the hydrogen atom positions. If
this is None, the default Platform will be used.
this is None, the default Platform will be used.
residueTemplates : dict=dict()
specifies which template the ForceField should use for particular residues. The keys
should be Residue objects from the Topology, and the values should be the names of the
templates to use for them. This is useful when a ForceField contains multiple templates
that can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
monoatomic iron ion in the Topology).
Returns
Returns
-------
-------
...
@@ -991,7 +1009,7 @@ class Modeller(object):
...
@@ -991,7 +1009,7 @@ class Modeller(object):
if
forcefield
is
not
None
:
if
forcefield
is
not
None
:
# Use the ForceField the user specified.
# Use the ForceField the user specified.
system
=
forcefield
.
createSystem
(
newTopology
,
rigidWater
=
False
,
nonbondedMethod
=
CutoffNonPeriodic
)
system
=
forcefield
.
createSystem
(
newTopology
,
rigidWater
=
False
,
nonbondedMethod
=
CutoffNonPeriodic
,
residueTemplates
=
residueTemplates
)
atoms
=
list
(
newTopology
.
atoms
())
atoms
=
list
(
newTopology
.
atoms
())
for
i
in
range
(
system
.
getNumParticles
()):
for
i
in
range
(
system
.
getNumParticles
()):
if
i
not
in
addedH
:
if
i
not
in
addedH
:
...
@@ -1051,7 +1069,7 @@ class Modeller(object):
...
@@ -1051,7 +1069,7 @@ class Modeller(object):
del
context
del
context
return
actualVariants
return
actualVariants
def
addExtraParticles
(
self
,
forcefield
,
ignoreExternalBonds
=
False
):
def
addExtraParticles
(
self
,
forcefield
,
ignoreExternalBonds
=
False
,
residueTemplates
=
dict
()
):
"""Add missing extra particles to the model that are required by a force
"""Add missing extra particles to the model that are required by a force
field.
field.
...
@@ -1074,6 +1092,12 @@ class Modeller(object):
...
@@ -1074,6 +1092,12 @@ class Modeller(object):
If true, ignore external bonds when matching residues to templates.
If true, ignore external bonds when matching residues to templates.
This is useful when the Topology represents one piece of a larger
This is useful when the Topology represents one piece of a larger
molecule, so chains are not terminated properly.
molecule, so chains are not terminated properly.
residueTemplates : dict=dict()
specifies which template the ForceField should use for particular residues. The keys
should be Residue objects from the Topology, and the values should be the names of the
templates to use for them. This is useful when a ForceField contains multiple templates
that can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
monoatomic iron ion in the Topology).
"""
"""
# Record which atoms are bonded to each other atom.
# Record which atoms are bonded to each other atom.
...
@@ -1093,7 +1117,7 @@ class Modeller(object):
...
@@ -1093,7 +1117,7 @@ class Modeller(object):
# Identify the template to use for each residue.
# Identify the template to use for each residue.
templates
=
forcefield
.
_matchAllResiduesToTemplates
(
ForceField
.
_SystemData
(
self
.
topology
),
self
.
topology
,
{}
,
False
,
True
,
False
)
templates
=
forcefield
.
_matchAllResiduesToTemplates
(
ForceField
.
_SystemData
(
self
.
topology
),
self
.
topology
,
residueTemplates
,
False
,
True
,
False
)
# Create the new Topology.
# Create the new Topology.
...
@@ -1206,7 +1230,7 @@ class Modeller(object):
...
@@ -1206,7 +1230,7 @@ class Modeller(object):
# There were particles whose position we couldn't identify before, since they were neither virtual sites nor Drude particles.
# There were particles whose position we couldn't identify before, since they were neither virtual sites nor Drude particles.
# Try to figure them out based on bonds. First, use the ForceField to create a list of every bond involving one of them.
# Try to figure them out based on bonds. First, use the ForceField to create a list of every bond involving one of them.
system
=
forcefield
.
createSystem
(
newTopology
,
constraints
=
AllBonds
)
system
=
forcefield
.
createSystem
(
newTopology
,
constraints
=
AllBonds
,
residueTemplates
=
residueTemplates
)
bonds
=
[]
bonds
=
[]
for
i
in
range
(
system
.
getNumConstraints
()):
for
i
in
range
(
system
.
getNumConstraints
()):
bond
=
system
.
getConstraintParameters
(
i
)
bond
=
system
.
getConstraintParameters
(
i
)
...
@@ -1234,7 +1258,7 @@ class Modeller(object):
...
@@ -1234,7 +1258,7 @@ class Modeller(object):
self
.
positions
=
newPositions
self
.
positions
=
newPositions
def
addMembrane
(
self
,
forcefield
,
lipidType
=
'POPC'
,
membraneCenterZ
=
0
*
nanometer
,
minimumPadding
=
1
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
def
addMembrane
(
self
,
forcefield
,
lipidType
=
'POPC'
,
membraneCenterZ
=
0
*
nanometer
,
minimumPadding
=
1
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
,
residueTemplates
=
dict
()
):
"""Add a lipid membrane to the model.
"""Add a lipid membrane to the model.
This method actually adds both a membrane and a water box. It is best to build them together,
This method actually adds both a membrane and a water box. It is best to build them together,
...
@@ -1286,6 +1310,12 @@ class Modeller(object):
...
@@ -1286,6 +1310,12 @@ class Modeller(object):
Note that only monovalent ions are currently supported.
Note that only monovalent ions are currently supported.
neutralize : bool=True
neutralize : bool=True
whether to add ions to neutralize the system
whether to add ions to neutralize the system
residueTemplates : dict=dict()
specifies which template the ForceField should use for particular residues. The keys
should be Residue objects from the Topology, and the values should be the names of the
templates to use for them. This is useful when a ForceField contains multiple templates
that can match the same residue (e.g Fe2+ and Fe3+ templates in the ForceField for a
monoatomic iron ion in the Topology).
"""
"""
if
'topology'
in
dir
(
lipidType
)
and
'positions'
in
dir
(
lipidType
):
if
'topology'
in
dir
(
lipidType
)
and
'positions'
in
dir
(
lipidType
):
patch
=
lipidType
patch
=
lipidType
...
@@ -1451,8 +1481,8 @@ class Modeller(object):
...
@@ -1451,8 +1481,8 @@ class Modeller(object):
# Create a System for the lipids, then add in the protein as stationary particles.
# Create a System for the lipids, then add in the protein as stationary particles.
system
=
forcefield
.
createSystem
(
membraneTopology
,
nonbondedMethod
=
CutoffPeriodic
)
system
=
forcefield
.
createSystem
(
membraneTopology
,
nonbondedMethod
=
CutoffPeriodic
,
residueTemplates
=
residueTemplates
)
proteinSystem
=
forcefield
.
createSystem
(
self
.
topology
,
nonbondedMethod
=
CutoffNonPeriodic
)
proteinSystem
=
forcefield
.
createSystem
(
self
.
topology
,
nonbondedMethod
=
CutoffNonPeriodic
,
residueTemplates
=
residueTemplates
)
numMembraneParticles
=
system
.
getNumParticles
()
numMembraneParticles
=
system
.
getNumParticles
()
numProteinParticles
=
proteinSystem
.
getNumParticles
()
numProteinParticles
=
proteinSystem
.
getNumParticles
()
for
i
in
range
(
numProteinParticles
):
for
i
in
range
(
numProteinParticles
):
...
@@ -1520,7 +1550,7 @@ class Modeller(object):
...
@@ -1520,7 +1550,7 @@ class Modeller(object):
needExtraWater
=
(
boxSizeZ
>
patchSize
[
2
])
needExtraWater
=
(
boxSizeZ
>
patchSize
[
2
])
if
needExtraWater
:
if
needExtraWater
:
modeller
.
addSolvent
(
forcefield
,
neutralize
=
False
)
modeller
.
addSolvent
(
forcefield
,
neutralize
=
False
,
residueTemplates
=
residueTemplates
)
# Record the positions of all waters that have been added.
# Record the positions of all waters that have been added.
...
@@ -1587,7 +1617,7 @@ class Modeller(object):
...
@@ -1587,7 +1617,7 @@ class Modeller(object):
if
lowerZBoundary
<
waterZ
.
value_in_unit
(
nanometer
)
<
upperZBoundary
:
if
lowerZBoundary
<
waterZ
.
value_in_unit
(
nanometer
)
<
upperZBoundary
:
del
waterPos
[
wRes
]
del
waterPos
[
wRes
]
self
.
_addIons
(
forcefield
,
numTotalWaters
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
)
self
.
_addIons
(
forcefield
,
numTotalWaters
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
,
residueTemplates
=
residueTemplates
)
class
_CellList
(
object
):
class
_CellList
(
object
):
...
...
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