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
73183c61
Commit
73183c61
authored
May 31, 2016
by
ChayaSt
Browse files
resolved conflict
parents
0e218233
32e08b87
Changes
267
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
364 additions
and
189 deletions
+364
-189
wrappers/python/simtk/openmm/app/forcefield.py
wrappers/python/simtk/openmm/app/forcefield.py
+149
-78
wrappers/python/simtk/openmm/app/gromacstopfile.py
wrappers/python/simtk/openmm/app/gromacstopfile.py
+2
-2
wrappers/python/simtk/openmm/app/internal/customgbforces.py
wrappers/python/simtk/openmm/app/internal/customgbforces.py
+2
-2
wrappers/python/simtk/openmm/app/modeller.py
wrappers/python/simtk/openmm/app/modeller.py
+4
-2
wrappers/python/simtk/openmm/app/pdbfile.py
wrappers/python/simtk/openmm/app/pdbfile.py
+15
-13
wrappers/python/tests/TestAmberPrmtopFile.py
wrappers/python/tests/TestAmberPrmtopFile.py
+12
-0
wrappers/python/tests/TestForceField.py
wrappers/python/tests/TestForceField.py
+180
-92
No files found.
wrappers/python/simtk/openmm/app/forcefield.py
View file @
73183c61
...
...
@@ -120,88 +120,101 @@ class ForceField(object):
self
.
_forces
=
[]
self
.
_scripts
=
[]
self
.
_templateGenerators
=
[]
for
file
in
files
:
self
.
loadFile
(
file
)
self
.
loadFile
(
files
)
def
loadFile
(
self
,
file
):
def
loadFile
(
self
,
file
s
):
"""Load an XML file and add the definitions from it to this ForceField.
Parameters
----------
file : string or file
An XML file containing force field definitions.
It may be either an
absolute file path, a path relative to the current working
file
s
: string or file
or tuple
An XML file
or tuple of XML files
containing force field definitions.
Each entry may be either an
absolute file path, a path relative to the current working
directory, a path relative to this module's data subdirectory (for
built in force fields), or an open file-like object with a read()
method from which the forcefield XML data can be loaded.
"""
try
:
# this handles either filenames or open file-like objects
tree
=
etree
.
parse
(
file
)
except
IOError
:
tree
=
etree
.
parse
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'data'
,
file
))
except
Exception
as
e
:
# Fail with an error message about which file could not be read.
# TODO: Also handle case where fallback to 'data' directory encounters problems,
# but this is much less worrisome because we control those files.
msg
=
str
(
e
)
+
'
\n
'
if
hasattr
(
file
,
'name'
):
filename
=
file
.
name
else
:
filename
=
str
(
file
)
msg
+=
"ForceField.loadFile() encountered an error reading file '%s'
\n
"
%
filename
raise
Exception
(
msg
)
root
=
tree
.
getroot
()
if
not
isinstance
(
files
,
tuple
):
files
=
(
files
,)
trees
=
[]
for
file
in
files
:
try
:
# this handles either filenames or open file-like objects
tree
=
etree
.
parse
(
file
)
except
IOError
:
tree
=
etree
.
parse
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
'data'
,
file
))
except
Exception
as
e
:
# Fail with an error message about which file could not be read.
# TODO: Also handle case where fallback to 'data' directory encounters problems,
# but this is much less worrisome because we control those files.
msg
=
str
(
e
)
+
'
\n
'
if
hasattr
(
file
,
'name'
):
filename
=
file
.
name
else
:
filename
=
str
(
file
)
msg
+=
"ForceField.loadFile() encountered an error reading file '%s'
\n
"
%
filename
raise
Exception
(
msg
)
trees
.
append
(
tree
)
# Load the atom types.
if
tree
.
getroot
().
find
(
'AtomTypes'
)
is
not
None
:
for
type
in
tree
.
getroot
().
find
(
'AtomTypes'
).
findall
(
'Type'
):
self
.
registerAtomType
(
type
.
attrib
)
for
tree
in
trees
:
if
tree
.
getroot
().
find
(
'AtomTypes'
)
is
not
None
:
for
type
in
tree
.
getroot
().
find
(
'AtomTypes'
).
findall
(
'Type'
):
self
.
registerAtomType
(
type
.
attrib
)
# Load the residue templates.
if
tree
.
getroot
().
find
(
'Residues'
)
is
not
None
:
for
residue
in
root
.
find
(
'Residues'
).
findall
(
'Residue'
):
resName
=
residue
.
attrib
[
'name'
]
template
=
ForceField
.
_TemplateData
(
resName
)
atomIndices
=
{}
for
atom
in
residue
.
findall
(
'Atom'
):
params
=
{}
for
key
in
atom
.
attrib
:
if
key
not
in
(
'name'
,
'type'
):
params
[
key
]
=
_convertParameterToNumber
(
atom
.
attrib
[
key
])
atomName
=
atom
.
attrib
[
'name'
]
if
atomName
in
atomIndices
:
raise
ValueError
(
'Residue '
+
resName
+
' contains multiple atoms named '
+
atomName
)
atomIndices
[
atomName
]
=
len
(
template
.
atoms
)
typeName
=
atom
.
attrib
[
'type'
]
template
.
atoms
.
append
(
ForceField
.
_TemplateAtomData
(
atomName
,
typeName
,
self
.
_atomTypes
[
typeName
].
element
,
params
))
for
site
in
residue
.
findall
(
'VirtualSite'
):
template
.
virtualSites
.
append
(
ForceField
.
_VirtualSiteData
(
site
,
atomIndices
))
for
bond
in
residue
.
findall
(
'Bond'
):
if
'atomName1'
in
bond
.
attrib
:
template
.
addBondByName
(
bond
.
attrib
[
'atomName1'
],
bond
.
attrib
[
'atomName2'
])
else
:
template
.
addBond
(
int
(
bond
.
attrib
[
'from'
]),
int
(
bond
.
attrib
[
'to'
]))
for
bond
in
residue
.
findall
(
'ExternalBond'
):
if
'atomName'
in
bond
.
attrib
:
template
.
addExternalBondByName
(
bond
.
attrib
[
'atomName'
])
else
:
template
.
addExternalBond
(
int
(
bond
.
attrib
[
'from'
]))
self
.
registerResidueTemplate
(
template
)
for
tree
in
trees
:
if
tree
.
getroot
().
find
(
'Residues'
)
is
not
None
:
for
residue
in
tree
.
getroot
().
find
(
'Residues'
).
findall
(
'Residue'
):
resName
=
residue
.
attrib
[
'name'
]
template
=
ForceField
.
_TemplateData
(
resName
)
if
'overload'
in
residue
.
attrib
:
template
.
overloadLevel
=
int
(
residue
.
attrib
[
'overload'
])
atomIndices
=
{}
for
atom
in
residue
.
findall
(
'Atom'
):
params
=
{}
for
key
in
atom
.
attrib
:
if
key
not
in
(
'name'
,
'type'
):
params
[
key
]
=
_convertParameterToNumber
(
atom
.
attrib
[
key
])
atomName
=
atom
.
attrib
[
'name'
]
if
atomName
in
atomIndices
:
raise
ValueError
(
'Residue '
+
resName
+
' contains multiple atoms named '
+
atomName
)
atomIndices
[
atomName
]
=
len
(
template
.
atoms
)
typeName
=
atom
.
attrib
[
'type'
]
template
.
atoms
.
append
(
ForceField
.
_TemplateAtomData
(
atomName
,
typeName
,
self
.
_atomTypes
[
typeName
].
element
,
params
))
for
site
in
residue
.
findall
(
'VirtualSite'
):
template
.
virtualSites
.
append
(
ForceField
.
_VirtualSiteData
(
site
,
atomIndices
))
for
bond
in
residue
.
findall
(
'Bond'
):
if
'atomName1'
in
bond
.
attrib
:
template
.
addBondByName
(
bond
.
attrib
[
'atomName1'
],
bond
.
attrib
[
'atomName2'
])
else
:
template
.
addBond
(
int
(
bond
.
attrib
[
'from'
]),
int
(
bond
.
attrib
[
'to'
]))
for
bond
in
residue
.
findall
(
'ExternalBond'
):
if
'atomName'
in
bond
.
attrib
:
template
.
addExternalBondByName
(
bond
.
attrib
[
'atomName'
])
else
:
template
.
addExternalBond
(
int
(
bond
.
attrib
[
'from'
]))
self
.
registerResidueTemplate
(
template
)
# Load force definitions
for
child
in
root
:
if
child
.
tag
in
parsers
:
parsers
[
child
.
tag
](
child
,
self
)
for
tree
in
trees
:
for
child
in
tree
.
getroot
():
if
child
.
tag
in
parsers
:
parsers
[
child
.
tag
](
child
,
self
)
# Load scripts
for
node
in
tree
.
getroot
().
findall
(
'Script'
):
self
.
registerScript
(
node
.
text
)
for
tree
in
trees
:
for
node
in
tree
.
getroot
().
findall
(
'Script'
):
self
.
registerScript
(
node
.
text
)
def
getGenerators
(
self
):
"""Get the list of all registered generators."""
...
...
@@ -237,7 +250,25 @@ class ForceField(object):
self
.
_templates
[
template
.
name
]
=
template
signature
=
_createResidueSignature
([
atom
.
element
for
atom
in
template
.
atoms
])
if
signature
in
self
.
_templateSignatures
:
self
.
_templateSignatures
[
signature
].
append
(
template
)
registered
=
False
for
regtemplate
in
self
.
_templateSignatures
[
signature
]:
if
regtemplate
.
name
==
template
.
name
:
if
regtemplate
.
overloadLevel
>
template
.
overloadLevel
:
# ok to break - this is done every time a template is
# registered so there can only be one already existing
# with same name at a time
registered
=
True
break
elif
regtemplate
.
overloadLevel
<
template
.
overloadLevel
:
self
.
_templateSignatures
[
signature
].
remove
(
regtemplate
)
self
.
_templateSignatures
[
signature
].
append
(
template
)
registered
=
True
else
:
raise
Exception
(
'Residue template %s with the same overloadLevel %d already exists.'
%
(
template
.
name
,
template
.
overloadLevel
)
)
if
not
registered
:
self
.
_templateSignatures
[
signature
].
append
(
template
)
else
:
self
.
_templateSignatures
[
signature
]
=
[
template
]
...
...
@@ -379,6 +410,7 @@ class ForceField(object):
self
.
virtualSites
=
[]
self
.
bonds
=
[]
self
.
externalBonds
=
[]
self
.
overloadLevel
=
0
def
getAtomIndexByName
(
self
,
atom_name
):
"""Look up an atom index by atom name, providing a helpful error message if not found."""
...
...
@@ -566,11 +598,16 @@ class ForceField(object):
matches
=
None
signature
=
_createResidueSignature
([
atom
.
element
for
atom
in
res
.
atoms
()])
if
signature
in
self
.
_templateSignatures
:
allMatches
=
[]
for
t
in
self
.
_templateSignatures
[
signature
]:
matches
=
_matchResidue
(
res
,
t
,
bondedToAtom
)
if
matches
is
not
None
:
template
=
t
break
match
=
_matchResidue
(
res
,
t
,
bondedToAtom
)
if
match
is
not
None
:
allMatches
.
append
((
t
,
match
))
if
len
(
allMatches
)
==
1
:
template
=
allMatches
[
0
][
0
]
matches
=
allMatches
[
0
][
1
]
elif
len
(
allMatches
)
>
1
:
raise
Exception
(
'Multiple matching templates found for residue %d (%s).'
%
(
res
.
index
+
1
,
res
.
name
))
return
[
template
,
matches
]
def
_buildBondedToAtomList
(
self
,
topology
):
...
...
@@ -703,7 +740,7 @@ class ForceField(object):
return
[
templates
,
unique_unmatched_residues
]
def
createSystem
(
self
,
topology
,
nonbondedMethod
=
NoCutoff
,
nonbondedCutoff
=
1.0
*
unit
.
nanometer
,
constraints
=
None
,
rigidWater
=
True
,
removeCMMotion
=
True
,
hydrogenMass
=
None
,
**
args
):
constraints
=
None
,
rigidWater
=
True
,
removeCMMotion
=
True
,
hydrogenMass
=
None
,
residueTemplates
=
dict
(),
**
args
):
"""Construct an OpenMM System representing a Topology with this force field.
Parameters
...
...
@@ -727,6 +764,13 @@ class ForceField(object):
The mass to use for hydrogen atoms bound to heavy atoms. Any mass
added to a hydrogen is subtracted from the heavy atom to keep
their total mass the same.
residueTemplates : dict=dict()
Key: Topology Residue object
Value: string, name of _TemplateData residue template object to use for
(Key) residue
This allows user to specify which template to apply to particular Residues
in the event that multiple matching templates are available (e.g Fe2+ and Fe3+
templates in the ForceField for a monoatomic iron ion in the topology).
args
Arbitrary additional keyword arguments may also be specified.
This allows extra parameters to be specified that are specific to
...
...
@@ -765,8 +809,15 @@ class ForceField(object):
for
chain
in
topology
.
chains
():
for
res
in
chain
.
residues
():
# Attempt to match one of the existing templates.
[
template
,
matches
]
=
self
.
_getResidueTemplateMatches
(
res
,
bondedToAtom
)
if
res
in
residueTemplates
:
tname
=
residueTemplates
[
res
]
template
=
self
.
_templates
[
tname
]
matches
=
_matchResidue
(
res
,
template
,
bondedToAtom
)
if
matches
is
None
:
raise
Exception
(
'User-supplied template %s does not match the residue %d (%s)'
%
(
tname
,
res
.
index
+
1
,
res
.
name
))
else
:
# Attempt to match one of the existing templates.
[
template
,
matches
]
=
self
.
_getResidueTemplateMatches
(
res
,
bondedToAtom
)
if
matches
is
None
:
# No existing templates match. Try any registered residue template generators.
for
generator
in
self
.
_templateGenerators
:
...
...
@@ -1183,8 +1234,12 @@ class HarmonicBondGenerator(object):
@
staticmethod
def
parseElement
(
element
,
ff
):
generator
=
HarmonicBondGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
HarmonicBondGenerator
)]
if
len
(
existing
)
==
0
:
generator
=
HarmonicBondGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
bond
in
element
.
findall
(
'Bond'
):
generator
.
registerBond
(
bond
.
attrib
)
...
...
@@ -1236,8 +1291,12 @@ class HarmonicAngleGenerator(object):
@
staticmethod
def
parseElement
(
element
,
ff
):
generator
=
HarmonicAngleGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
HarmonicAngleGenerator
)]
if
len
(
existing
)
==
0
:
generator
=
HarmonicAngleGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
angle
in
element
.
findall
(
'Angle'
):
generator
.
registerAngle
(
angle
.
attrib
)
...
...
@@ -1320,8 +1379,12 @@ class PeriodicTorsionGenerator(object):
@
staticmethod
def
parseElement
(
element
,
ff
):
generator
=
PeriodicTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
PeriodicTorsionGenerator
)]
if
len
(
existing
)
==
0
:
generator
=
PeriodicTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
torsion
in
element
.
findall
(
'Proper'
):
generator
.
registerProperTorsion
(
torsion
.
attrib
)
for
torsion
in
element
.
findall
(
'Improper'
):
...
...
@@ -1419,8 +1482,12 @@ class RBTorsionGenerator(object):
@
staticmethod
def
parseElement
(
element
,
ff
):
generator
=
RBTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
RBTorsionGenerator
)]
if
len
(
existing
)
==
0
:
generator
=
RBTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
torsion
in
element
.
findall
(
'Proper'
):
types
=
ff
.
_findAtomTypes
(
torsion
.
attrib
,
4
)
if
None
not
in
types
:
...
...
@@ -1523,8 +1590,12 @@ class CMAPTorsionGenerator(object):
@
staticmethod
def
parseElement
(
element
,
ff
):
generator
=
CMAPTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
CMAPTorsionGenerator
)]
if
len
(
existing
)
==
0
:
generator
=
CMAPTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
map
in
element
.
findall
(
'Map'
):
values
=
[
float
(
x
)
for
x
in
map
.
text
.
split
()]
size
=
sqrt
(
len
(
values
))
...
...
wrappers/python/simtk/openmm/app/gromacstopfile.py
View file @
73183c61
...
...
@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012-201
5
Stanford University and the Authors.
Portions copyright (c) 2012-201
6
Stanford University and the Authors.
Authors: Peter Eastman
Contributors: Jason Swails
...
...
@@ -814,7 +814,7 @@ class GromacsTopFile(object):
map
=
[]
for
i
in
range
(
mapSize
):
for
j
in
range
(
mapSize
):
map
.
append
(
float
(
params
[
8
+
mapSize
*
((
j
+
mapSize
/
2
)
%
mapSize
)
+
((
i
+
mapSize
/
2
)
%
mapSize
)]))
map
.
append
(
float
(
params
[
8
+
mapSize
*
((
j
+
mapSize
/
/
2
)
%
mapSize
)
+
((
i
+
mapSize
/
/
2
)
%
mapSize
)]))
map
=
tuple
(
map
)
if
map
not
in
mapIndices
:
mapIndices
[
map
]
=
cmap
.
addMap
(
mapSize
,
map
)
...
...
wrappers/python/simtk/openmm/app/internal/customgbforces.py
View file @
73183c61
...
...
@@ -335,7 +335,7 @@ def _mbondi3_radii(topology):
def
_createEnergyTerms
(
force
,
solventDielectric
,
soluteDielectric
,
SA
,
cutoff
,
kappa
,
offset
):
# Add the energy terms to the CustomGBForce. These are identical for all the GB models.
params
=
"; solventDielectric=%.16g; soluteDielectric=%.16g; kappa=%.16g; offset=%.16g"
%
(
solventDielectric
,
soluteDielectric
,
kappa
,
offset
)
if
cutoff
is
not
None
:
params
+=
"; cutoff=%.16g"
%
cutoff
...
...
@@ -535,7 +535,7 @@ class GBSAGBnForce(CustomAmberGBForce):
def
addParticle
(
self
,
parameters
):
parameters
=
CustomAmberGBForce
.
addParticle
(
self
,
parameters
)
if
parameters
[
1
]
<
0.1
or
parameters
[
1
]
>
0.2
:
if
parameters
[
1
]
+
self
.
OFFSET
<
0.1
or
parameters
[
1
]
+
self
.
OFFSET
>
0.2
:
raise
ValueError
(
'Radii must be between 1 and 2 Angstroms for neck lookup'
)
def
setParticleParameters
(
self
,
idx
,
parameters
):
...
...
wrappers/python/simtk/openmm/app/modeller.py
View file @
73183c61
...
...
@@ -35,7 +35,7 @@ __author__ = "Peter Eastman"
__version__
=
"1.0"
from
simtk.openmm.app
import
Topology
,
PDBFile
,
ForceField
from
simtk.openmm.app.forcefield
import
HAngles
,
AllBonds
,
_createResidueSignature
,
_matchResidue
,
DrudeGenerator
from
simtk.openmm.app.forcefield
import
HAngles
,
AllBonds
,
CutoffNonPeriodic
,
_createResidueSignature
,
_matchResidue
,
DrudeGenerator
from
simtk.openmm.app.topology
import
Residue
from
simtk.openmm.vec3
import
Vec3
from
simtk.openmm
import
System
,
Context
,
NonbondedForce
,
CustomNonbondedForce
,
HarmonicBondForce
,
HarmonicAngleForce
,
VerletIntegrator
,
LocalEnergyMinimizer
...
...
@@ -857,7 +857,7 @@ class Modeller(object):
if
forcefield
is
not
None
:
# Use the ForceField the user specified.
system
=
forcefield
.
createSystem
(
newTopology
,
rigidWater
=
False
)
system
=
forcefield
.
createSystem
(
newTopology
,
rigidWater
=
False
,
nonbondedMethod
=
CutoffNonPeriodic
)
atoms
=
list
(
newTopology
.
atoms
())
for
i
in
range
(
system
.
getNumParticles
()):
if
atoms
[
i
].
element
!=
elem
.
hydrogen
:
...
...
@@ -869,6 +869,8 @@ class Modeller(object):
system
=
System
()
nonbonded
=
CustomNonbondedForce
(
'100/((r/0.1)^4+1)'
)
nonbonded
.
setNonbondedMethod
(
CustomNonbondedForce
.
CutoffNonPeriodic
);
nonbonded
.
setCutoffDistance
(
1
*
nanometer
)
bonds
=
HarmonicBondForce
()
angles
=
HarmonicAngleForce
()
system
.
addForce
(
nonbonded
)
...
...
wrappers/python/simtk/openmm/app/pdbfile.py
View file @
73183c61
...
...
@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
Portions copyright (c) 2012-201
5
Stanford University and the Authors.
Portions copyright (c) 2012-201
6
Stanford University and the Authors.
Authors: Peter Eastman
Contributors:
...
...
@@ -58,6 +58,9 @@ class PDBFile(object):
_residueNameReplacements
=
{}
_atomNameReplacements
=
{}
_standardResidues
=
[
'ALA'
,
'ASN'
,
'CYS'
,
'GLU'
,
'HIS'
,
'LEU'
,
'MET'
,
'PRO'
,
'THR'
,
'TYR'
,
'ARG'
,
'ASP'
,
'GLN'
,
'GLY'
,
'ILE'
,
'LYS'
,
'PHE'
,
'SER'
,
'TRP'
,
'VAL'
,
'A'
,
'G'
,
'C'
,
'U'
,
'I'
,
'DA'
,
'DG'
,
'DC'
,
'DT'
,
'DI'
,
'HOH'
]
def
__init__
(
self
,
file
,
extraParticleIdentifier
=
'EP'
):
"""Load a PDB file.
...
...
@@ -75,10 +78,6 @@ class PDBFile(object):
metalElements
=
[
'Al'
,
'As'
,
'Ba'
,
'Ca'
,
'Cd'
,
'Ce'
,
'Co'
,
'Cs'
,
'Cu'
,
'Dy'
,
'Fe'
,
'Gd'
,
'Hg'
,
'Ho'
,
'In'
,
'Ir'
,
'K'
,
'Li'
,
'Mg'
,
'Mn'
,
'Mo'
,
'Na'
,
'Ni'
,
'Pb'
,
'Pd'
,
'Pt'
,
'Rb'
,
'Rh'
,
'Sm'
,
'Sr'
,
'Te'
,
'Tl'
,
'V'
,
'W'
,
'Yb'
,
'Zn'
]
standardResidues
=
[
'ALA'
,
'ASN'
,
'CYS'
,
'GLU'
,
'HIS'
,
'LEU'
,
'MET'
,
'PRO'
,
'THR'
,
'TYR'
,
'ARG'
,
'ASP'
,
'GLN'
,
'GLY'
,
'ILE'
,
'LYS'
,
'PHE'
,
'SER'
,
'TRP'
,
'VAL'
,
'A'
,
'G'
,
'C'
,
'U'
,
'I'
,
'DA'
,
'DG'
,
'DC'
,
'DT'
,
'DI'
,
'HOH'
]
top
=
Topology
()
## The Topology read from the PDB file
self
.
topology
=
top
...
...
@@ -173,9 +172,9 @@ class PDBFile(object):
if
atomByNumber
[
i
].
element
is
not
None
and
atomByNumber
[
j
].
element
is
not
None
:
if
atomByNumber
[
i
].
element
.
symbol
not
in
metalElements
and
atomByNumber
[
j
].
element
.
symbol
not
in
metalElements
:
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
elif
atomByNumber
[
i
].
element
.
symbol
in
metalElements
and
atomByNumber
[
j
].
residue
.
name
not
in
standardResidues
:
elif
atomByNumber
[
i
].
element
.
symbol
in
metalElements
and
atomByNumber
[
j
].
residue
.
name
not
in
PDBFile
.
_
standardResidues
:
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
elif
atomByNumber
[
j
].
element
.
symbol
in
metalElements
and
atomByNumber
[
i
].
residue
.
name
not
in
standardResidues
:
elif
atomByNumber
[
j
].
element
.
symbol
in
metalElements
and
atomByNumber
[
i
].
residue
.
name
not
in
PDBFile
.
_
standardResidues
:
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
else
:
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
...
...
@@ -331,6 +330,8 @@ class PDBFile(object):
raise
ValueError
(
'Particle position is NaN'
)
if
any
(
math
.
isinf
(
norm
(
pos
))
for
pos
in
positions
):
raise
ValueError
(
'Particle position is infinite'
)
nonHeterogens
=
PDBFile
.
_standardResidues
[:]
nonHeterogens
.
remove
(
'HOH'
)
atomIndex
=
1
posIndex
=
0
if
modelIndex
is
not
None
:
...
...
@@ -350,6 +351,10 @@ class PDBFile(object):
resId
=
res
.
id
else
:
resId
=
"%4d"
%
((
resIndex
+
1
)
%
10000
)
if
res
.
name
in
nonHeterogens
:
recordName
=
"ATOM "
else
:
recordName
=
"HETATM"
for
atom
in
res
.
atoms
():
if
atom
.
element
is
not
None
:
symbol
=
atom
.
element
.
symbol
...
...
@@ -362,8 +367,8 @@ class PDBFile(object):
else
:
atomName
=
atom
.
name
coords
=
positions
[
posIndex
]
line
=
"
ATOM
%5d %-4s %3s %s%4s %s%s%s 1.00 0.00 %2s "
%
(
atomIndex
%
100000
,
atomName
,
resName
,
chainName
,
resId
,
_format_83
(
coords
[
0
]),
line
=
"
%s
%5d %-4s %3s %s%4s %s%s%s 1.00 0.00 %2s "
%
(
recordName
,
atomIndex
%
100000
,
atomName
,
resName
,
chainName
,
resId
,
_format_83
(
coords
[
0
]),
_format_83
(
coords
[
1
]),
_format_83
(
coords
[
2
]),
symbol
)
assert
len
(
line
)
==
80
,
'Fixed width overflow detected'
print
(
line
,
file
=
file
)
...
...
@@ -388,12 +393,9 @@ class PDBFile(object):
"""
# Identify bonds that should be listed as CONECT records.
standardResidues
=
[
'ALA'
,
'ASN'
,
'CYS'
,
'GLU'
,
'HIS'
,
'LEU'
,
'MET'
,
'PRO'
,
'THR'
,
'TYR'
,
'ARG'
,
'ASP'
,
'GLN'
,
'GLY'
,
'ILE'
,
'LYS'
,
'PHE'
,
'SER'
,
'TRP'
,
'VAL'
,
'A'
,
'G'
,
'C'
,
'U'
,
'I'
,
'DA'
,
'DG'
,
'DC'
,
'DT'
,
'DI'
,
'HOH'
]
conectBonds
=
[]
for
atom1
,
atom2
in
topology
.
bonds
():
if
atom1
.
residue
.
name
not
in
standardResidues
or
atom2
.
residue
.
name
not
in
standardResidues
:
if
atom1
.
residue
.
name
not
in
PDBFile
.
_
standardResidues
or
atom2
.
residue
.
name
not
in
PDBFile
.
_
standardResidues
:
conectBonds
.
append
((
atom1
,
atom2
))
elif
atom1
.
name
==
'SG'
and
atom2
.
name
==
'SG'
and
atom1
.
residue
.
name
==
'CYS'
and
atom2
.
residue
.
name
==
'CYS'
:
conectBonds
.
append
((
atom1
,
atom2
))
...
...
wrappers/python/tests/TestAmberPrmtopFile.py
View file @
73183c61
...
...
@@ -361,5 +361,17 @@ class TestAmberPrmtopFile(unittest.TestCase):
# Make sure it says something about chamber
self
.
assertTrue
(
'chamber'
in
str
(
e
).
lower
())
def
testGBneckRadii
(
self
):
""" Tests that GBneck radii limits are correctly enforced """
from
simtk.openmm.app.internal.customgbforces
import
GBSAGBnForce
f
=
GBSAGBnForce
()
# Make sure legal parameters do not raise
f
.
addParticle
([
0
,
0.1
,
0.5
])
f
.
addParticle
([
0
,
0.2
,
0.5
])
f
.
addParticle
([
0
,
0.15
,
0.5
])
# Now make sure that out-of-range parameters *do* raise
self
.
assertRaises
(
ValueError
,
lambda
:
f
.
addParticle
([
0
,
0.9
,
0.5
]))
self
.
assertRaises
(
ValueError
,
lambda
:
f
.
addParticle
([
0
,
0.21
,
0.5
]))
if
__name__
==
'__main__'
:
unittest
.
main
()
wrappers/python/tests/TestForceField.py
View file @
73183c61
...
...
@@ -449,6 +449,183 @@ class TestForceField(unittest.TestCase):
self
.
assertEqual
(
templates
[
1
].
name
,
'ALA'
)
self
.
assertEqual
(
templates
[
2
].
name
,
'CALA'
)
def
test_Wildcard
(
self
):
"""Test that PeriodicTorsionForces using wildcard ('') for atom types / classes in the ffxml are correctly registered"""
# Use wildcards in types
xml
=
"""
<ForceField>
<AtomTypes>
<Type name="C" class="C" element="C" mass="12.010000"/>
<Type name="O" class="O" element="O" mass="16.000000"/>
</AtomTypes>
<PeriodicTorsionForce>
<Proper type1="" type2="C" type3="C" type4="" periodicity1="2" phase1="3.141593" k1="15.167000"/>
<Improper type1="C" type2="" type3="" type4="O" periodicity1="2" phase1="3.141593" k1="43.932000"/>
</PeriodicTorsionForce>
</ForceField>"""
ff
=
ForceField
(
StringIO
(
xml
))
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
proper
),
1
)
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
improper
),
1
)
# Use wildcards in classes
xml
=
"""
<ForceField>
<AtomTypes>
<Type name="C" class="C" element="C" mass="12.010000"/>
<Type name="O" class="O" element="O" mass="16.000000"/>
</AtomTypes>
<PeriodicTorsionForce>
<Proper class1="" class2="C" class3="C" class4="" periodicity1="2" phase1="3.141593" k1="15.167000"/>
<Improper class1="C" class2="" class3="" class4="O" periodicity1="2" phase1="3.141593" k1="43.932000"/>
</PeriodicTorsionForce>
</ForceField>"""
ff
=
ForceField
(
StringIO
(
xml
))
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
proper
),
1
)
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
improper
),
1
)
def
test_ScalingFactorCombining
(
self
):
""" Tests that FFs can be combined if their scaling factors are very close """
forcefield
=
ForceField
(
'amber99sb.xml'
,
os
.
path
.
join
(
'systems'
,
'test_amber_ff.xml'
))
# This would raise an exception if it didn't work
def
test_MultipleFilesandForceTags
(
self
):
"""Test that the order of listing of multiple ffxmls does not matter.
Tests that one generator per force type is created and that the ffxml
defining atom types does not have to be listed first"""
ffxml
=
"""<ForceField>
<Residues>
<Residue name="ACE-Test">
<Atom name="HH31" type="710"/>
<Atom name="CH3" type="711"/>
<Atom name="HH32" type="710"/>
<Atom name="HH33" type="710"/>
<Atom name="C" type="712"/>
<Atom name="O" type="713"/>
<Bond from="0" to="1"/>
<Bond from="1" to="2"/>
<Bond from="1" to="3"/>
<Bond from="1" to="4"/>
<Bond from="4" to="5"/>
<ExternalBond from="4"/>
</Residue>
</Residues>
<PeriodicTorsionForce>
<Proper class1="C" class2="C" class3="C" class4="C" periodicity1="2" phase1="3.14159265359" k1="10.46"/>
<Improper class1="C" class2="C" class3="C" class4="C" periodicity1="2" phase1="3.14159265359" k1="43.932"/>
</PeriodicTorsionForce>
</ForceField>"""
ff1
=
ForceField
(
StringIO
(
ffxml
),
'amber99sbildn.xml'
)
ff2
=
ForceField
(
'amber99sbildn.xml'
,
StringIO
(
ffxml
))
self
.
assertEqual
(
len
(
ff1
.
_forces
),
4
)
self
.
assertEqual
(
len
(
ff2
.
_forces
),
4
)
pertorsion1
=
ff1
.
_forces
[
0
]
pertorsion2
=
ff2
.
_forces
[
2
]
self
.
assertEqual
(
len
(
pertorsion1
.
proper
),
110
)
self
.
assertEqual
(
len
(
pertorsion1
.
improper
),
42
)
self
.
assertEqual
(
len
(
pertorsion2
.
proper
),
110
)
self
.
assertEqual
(
len
(
pertorsion2
.
improper
),
42
)
def
test_ResidueTemplateUserChoice
(
self
):
"""Test createSystem does not allow multiple matching templates, unless
user has specified which template to use via residueTemplates arg"""
ffxml
=
"""<ForceField>
<AtomTypes>
<Type name="Fe2+" class="Fe2+" element="Fe" mass="55.85"/>
<Type name="Fe3+" class="Fe3+" element="Fe" mass="55.85"/>
</AtomTypes>
<Residues>
<Residue name="FE2">
<Atom name="FE2" type="Fe2+" charge="2.0"/>
</Residue>
<Residue name="FE">
<Atom name="FE" type="Fe3+" charge="3.0"/>
</Residue>
</Residues>
<NonbondedForce coulomb14scale="0.833333333333" lj14scale="0.5">
<UseAttributeFromResidue name="charge"/>
<Atom type="Fe2+" sigma="0.227535532613" epsilon="0.0150312292"/>
<Atom type="Fe3+" sigma="0.192790482606" epsilon="0.00046095128"/>
</NonbondedForce>
</ForceField>"""
pdb_string
=
"ATOM 1 FE FE A 1 20.956 27.448 -29.067 1.00 0.00 Fe"
ff
=
ForceField
(
StringIO
(
ffxml
))
pdb
=
PDBFile
(
StringIO
(
pdb_string
))
self
.
assertRaises
(
Exception
,
lambda
:
ff
.
createSystem
(
pdb
.
topology
))
sys
=
ff
.
createSystem
(
pdb
.
topology
,
residueTemplates
=
{
list
(
pdb
.
topology
.
residues
())[
0
]
:
'FE2'
})
# confirm charge
self
.
assertEqual
(
sys
.
getForce
(
0
).
getParticleParameters
(
0
)[
0
].
_value
,
2.0
)
sys
=
ff
.
createSystem
(
pdb
.
topology
,
residueTemplates
=
{
list
(
pdb
.
topology
.
residues
())[
0
]
:
'FE'
})
# confirm charge
self
.
assertEqual
(
sys
.
getForce
(
0
).
getParticleParameters
(
0
)[
0
].
_value
,
3.0
)
def
test_ResidueOverloading
(
self
):
"""Test residue overloading via overload tag in the XML"""
ffxml1
=
"""<ForceField>
<AtomTypes>
<Type name="Fe2+_tip3p_HFE" class="Fe2+_tip3p_HFE" element="Fe" mass="55.85"/>
</AtomTypes>
<Residues>
<Residue name="FE2">
<Atom name="FE2" type="Fe2+_tip3p_HFE" charge="2.0"/>
</Residue>
</Residues>
<NonbondedForce coulomb14scale="0.833333333333" lj14scale="0.5">
<UseAttributeFromResidue name="charge"/>
<Atom type="Fe2+_tip3p_HFE" sigma="0.227535532613" epsilon="0.0150312292"/>
</NonbondedForce>
</ForceField>"""
ffxml2
=
"""<ForceField>
<AtomTypes>
<Type name="Fe2+_tip3p_standard" class="Fe2+_tip3p_standard" element="Fe" mass="55.85"/>
</AtomTypes>
<Residues>
<Residue name="FE2">
<Atom name="FE2" type="Fe2+_tip3p_standard" charge="2.0"/>
</Residue>
</Residues>
<NonbondedForce coulomb14scale="0.833333333333" lj14scale="0.5">
<UseAttributeFromResidue name="charge"/>
<Atom type="Fe2+_tip3p_standard" sigma="0.241077193129" epsilon="0.03940482832"/>
</NonbondedForce>
</ForceField>"""
ffxml3
=
"""<ForceField>
<AtomTypes>
<Type name="Fe2+_tip3p_standard" class="Fe2+_tip3p_standard" element="Fe" mass="55.85"/>
</AtomTypes>
<Residues>
<Residue name="FE2" overload="1">
<Atom name="FE2" type="Fe2+_tip3p_standard" charge="2.0"/>
</Residue>
</Residues>
<NonbondedForce coulomb14scale="0.833333333333" lj14scale="0.5">
<UseAttributeFromResidue name="charge"/>
<Atom type="Fe2+_tip3p_standard" sigma="0.241077193129" epsilon="0.03940482832"/>
</NonbondedForce>
</ForceField>"""
pdb_string
=
"ATOM 1 FE FE A 1 20.956 27.448 -29.067 1.00 0.00 Fe"
pdb
=
PDBFile
(
StringIO
(
pdb_string
))
self
.
assertRaises
(
Exception
,
lambda
:
ForceField
(
StringIO
(
ffxml1
),
StringIO
(
ffxml2
)))
ff
=
ForceField
(
StringIO
(
ffxml1
),
StringIO
(
ffxml3
))
self
.
assertEqual
(
ff
.
_templates
[
'FE2'
].
atoms
[
0
].
type
,
'Fe2+_tip3p_standard'
)
ff
.
createSystem
(
pdb
.
topology
)
class
AmoebaTestForceField
(
unittest
.
TestCase
):
"""Test the ForceField.createSystem() method with the AMOEBA forcefield."""
...
...
@@ -539,11 +716,9 @@ class AmoebaTestForceField(unittest.TestCase):
def
test_LennardJones_generator
(
self
):
""" Test the LennardJones generator"""
warnings
.
filterwarnings
(
'ignore'
,
category
=
CharmmPSFWarning
)
psf
=
CharmmPsfFile
(
'systems/methanol_ions.psf'
)
pdb
=
PDBFile
(
'systems/methanol_ions.pdb'
)
params
=
CharmmParameterSet
(
'systems/top_all36_cgenff.rtf'
,
'systems/par_all36_cgenff.prm'
,
'systems/toppar_water_ions.str'
psf
=
CharmmPsfFile
(
'systems/ions.psf'
)
pdb
=
PDBFile
(
'systems/ions.pdb'
)
params
=
CharmmParameterSet
(
'systems/toppar_water_ions.str'
)
# Box dimensions (found from bounding box)
...
...
@@ -565,27 +740,10 @@ class AmoebaTestForceField(unittest.TestCase):
xml
=
"""
<ForceField>
<AtomTypes>
<Type name="CG331" class="CG331" element="C" mass="12.011"/>
<Type name="OG311" class="OG311" element="O" mass="15.9994"/>
<Type name="HGP1" class="HGP1" element="H" mass="1.008"/>
<Type name="HGA3" class="HGA3" element="H" mass="1.008"/>
<Type name="SOD" class="SOD" element="Na" mass="22.98977"/>
<Type name="CLA" class="CLA" element="Cl" mass="35.45"/>
</AtomTypes>
<Residues>
<Residue name="MEOH">
<Atom name="CB" type="CG331" charge="0.0"/>
<Atom name="OG" type="OG311" charge="0.0"/>
<Atom name="HG1" type="HGP1" charge="0.0"/>
<Atom name="HB1" type="HGA3" charge="0.0"/>
<Atom name="HB2" type="HGA3" charge="0.0"/>
<Atom name="HB3" type="HGA3" charge="0.0"/>
<Bond atomName1="CB" atomName2="OG"/>
<Bond atomName1="OG" atomName2="HG1"/>
<Bond atomName1="CB" atomName2="HB1"/>
<Bond atomName1="CB" atomName2="HB2"/>
<Bond atomName1="CB" atomName2="HB3"/>
</Residue>
<Residue name="CLA">
<Atom name="CLA" type="CLA" charge="0.0"/>
</Residue>
...
...
@@ -593,37 +751,12 @@ class AmoebaTestForceField(unittest.TestCase):
<Atom name="SOD" type="SOD" charge="0.0"/>
</Residue>
</Residues>
<HarmonicBondForce>
<Bond type1="CG331" type2="OG311" length="0.142" k="358150.4"/>
<Bond type1="CG331" type2="HGA3" length="0.1111" k="269449.6"/>
<Bond type1="OG311" type2="HGP1" length="0.096" k="456056.0"/>
</HarmonicBondForce>
<HarmonicAngleForce>
<Angle type1="HGA3" type2="CG331" type3="HGA3" angle="1.89193690916" k="297.064"/>
<Angle type1="CG331" type2="OG311" type3="HGP1" angle="1.85004900711" k="481.16"/>
<Angle type1="OG311" type2="CG331" type3="HGA3" angle="1.9004890225" k="384.0912"/>
</HarmonicAngleForce>
<!-- Urey-Bradley terms -->
<AmoebaUreyBradleyForce>
<UreyBradley type1="HGA3" type2="CG331" type3="HGA3" d="0.1802" k="2259.36"/>
</AmoebaUreyBradleyForce>
<PeriodicTorsionForce>
<Proper type1="HGA3" type2="CG331" type3="OG311" type4="HGP1" periodicity1="3" phase1="0.0" k1="0.75312"/>
</PeriodicTorsionForce>
<NonbondedForce coulomb14scale="1.0" lj14scale="1.0">
<UseAttributeFromResidue name="charge"/>
<Atom type="CG331" sigma="1.0" epsilon="0.0"/>
<Atom type="OG311" sigma="1.0" epsilon="0.0"/>
<Atom type="HGP1" sigma="1.0" epsilon="0.0"/>
<Atom type="HGA3" sigma="1.0" epsilon="0.0"/>
<Atom type="SOD" sigma="1.0" epsilon="0.0"/>
<Atom type="CLA" sigma="1.0" epsilon="0.0"/>
</NonbondedForce>
<LennardJonesForce lj14scale="1.0">
<Atom type="CG331" sigma="0.365268474438" epsilon="0.326352"/>
<Atom type="OG311" sigma="0.314487247504" epsilon="0.8037464"/>
<Atom type="HGP1" sigma="0.0400013524445" epsilon="0.192464"/>
<Atom type="HGA3" sigma="0.238760856462" epsilon="0.100416"/>
<Atom type="CLA" sigma="0.404468018036" epsilon="0.6276"/>
<Atom type="SOD" sigma="0.251367073323" epsilon="0.1962296"/>
<NBFixPair type1="CLA" type2="SOD" emin="0.350933" rmin="0.3731"/>
...
...
@@ -641,50 +774,5 @@ class AmoebaTestForceField(unittest.TestCase):
ene2
=
state2
.
getPotentialEnergy
().
value_in_unit
(
kilocalories_per_mole
)
self
.
assertAlmostEqual
(
ene
,
ene2
)
def
test_Wildcard
(
self
):
"""Test that PeriodicTorsionForces using wildcard ('') for atom types / classes in the ffxml are correctly registered"""
# Use wildcards in types
xml
=
"""
<ForceField>
<AtomTypes>
<Type name="C" class="C" element="C" mass="12.010000"/>
<Type name="O" class="O" element="O" mass="16.000000"/>
</AtomTypes>
<PeriodicTorsionForce>
<Proper type1="" type2="C" type3="C" type4="" periodicity1="2" phase1="3.141593" k1="15.167000"/>
<Improper type1="C" type2="" type3="" type4="O" periodicity1="2" phase1="3.141593" k1="43.932000"/>
</PeriodicTorsionForce>
</ForceField>"""
ff
=
ForceField
(
StringIO
(
xml
))
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
proper
),
1
)
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
improper
),
1
)
# Use wildcards in classes
xml
=
"""
<ForceField>
<AtomTypes>
<Type name="C" class="C" element="C" mass="12.010000"/>
<Type name="O" class="O" element="O" mass="16.000000"/>
</AtomTypes>
<PeriodicTorsionForce>
<Proper class1="" class2="C" class3="C" class4="" periodicity1="2" phase1="3.141593" k1="15.167000"/>
<Improper class1="C" class2="" class3="" class4="O" periodicity1="2" phase1="3.141593" k1="43.932000"/>
</PeriodicTorsionForce>
</ForceField>"""
ff
=
ForceField
(
StringIO
(
xml
))
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
proper
),
1
)
self
.
assertEqual
(
len
(
ff
.
_forces
[
0
].
improper
),
1
)
def
test_ScalingFactorCombining
(
self
):
""" Tests that FFs can be combined if their scaling factors are very close """
forcefield
=
ForceField
(
'amber99sb.xml'
,
os
.
path
.
join
(
'systems'
,
'test_amber_ff.xml'
))
# This would raise an exception if it didn't work
if
__name__
==
'__main__'
:
unittest
.
main
()
Prev
1
…
10
11
12
13
14
Next
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