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):
...
@@ -120,88 +120,101 @@ class ForceField(object):
self
.
_forces
=
[]
self
.
_forces
=
[]
self
.
_scripts
=
[]
self
.
_scripts
=
[]
self
.
_templateGenerators
=
[]
self
.
_templateGenerators
=
[]
for
file
in
files
:
self
.
loadFile
(
files
)
self
.
loadFile
(
file
)
def
loadFile
(
self
,
file
):
def
loadFile
(
self
,
file
s
):
"""Load an XML file and add the definitions from it to this ForceField.
"""Load an XML file and add the definitions from it to this ForceField.
Parameters
Parameters
----------
----------
file : string or file
file
s
: string or file
or tuple
An XML file containing force field definitions.
It may be either an
An XML file
or tuple of XML files
containing force field definitions.
absolute file path, a path relative to the current working
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
directory, a path relative to this module's data subdirectory (for
built in force fields), or an open file-like object with a read()
built in force fields), or an open file-like object with a read()
method from which the forcefield XML data can be loaded.
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.
# Load the atom types.
if
tree
.
getroot
().
find
(
'AtomTypes'
)
is
not
None
:
for
tree
in
trees
:
for
type
in
tree
.
getroot
().
find
(
'AtomTypes'
).
findall
(
'Type'
):
if
tree
.
getroot
().
find
(
'AtomTypes'
)
is
not
None
:
self
.
registerAtomType
(
type
.
attrib
)
for
type
in
tree
.
getroot
().
find
(
'AtomTypes'
).
findall
(
'Type'
):
self
.
registerAtomType
(
type
.
attrib
)
# Load the residue templates.
# Load the residue templates.
if
tree
.
getroot
().
find
(
'Residues'
)
is
not
None
:
for
tree
in
trees
:
for
residue
in
root
.
find
(
'Residues'
).
findall
(
'Residue'
):
if
tree
.
getroot
().
find
(
'Residues'
)
is
not
None
:
resName
=
residue
.
attrib
[
'name'
]
for
residue
in
tree
.
getroot
().
find
(
'Residues'
).
findall
(
'Residue'
):
template
=
ForceField
.
_TemplateData
(
resName
)
resName
=
residue
.
attrib
[
'name'
]
atomIndices
=
{}
template
=
ForceField
.
_TemplateData
(
resName
)
for
atom
in
residue
.
findall
(
'Atom'
):
if
'overload'
in
residue
.
attrib
:
params
=
{}
template
.
overloadLevel
=
int
(
residue
.
attrib
[
'overload'
])
for
key
in
atom
.
attrib
:
atomIndices
=
{}
if
key
not
in
(
'name'
,
'type'
):
for
atom
in
residue
.
findall
(
'Atom'
):
params
[
key
]
=
_convertParameterToNumber
(
atom
.
attrib
[
key
])
params
=
{}
atomName
=
atom
.
attrib
[
'name'
]
for
key
in
atom
.
attrib
:
if
atomName
in
atomIndices
:
if
key
not
in
(
'name'
,
'type'
):
raise
ValueError
(
'Residue '
+
resName
+
' contains multiple atoms named '
+
atomName
)
params
[
key
]
=
_convertParameterToNumber
(
atom
.
attrib
[
key
])
atomIndices
[
atomName
]
=
len
(
template
.
atoms
)
atomName
=
atom
.
attrib
[
'name'
]
typeName
=
atom
.
attrib
[
'type'
]
if
atomName
in
atomIndices
:
template
.
atoms
.
append
(
ForceField
.
_TemplateAtomData
(
atomName
,
typeName
,
self
.
_atomTypes
[
typeName
].
element
,
params
))
raise
ValueError
(
'Residue '
+
resName
+
' contains multiple atoms named '
+
atomName
)
for
site
in
residue
.
findall
(
'VirtualSite'
):
atomIndices
[
atomName
]
=
len
(
template
.
atoms
)
template
.
virtualSites
.
append
(
ForceField
.
_VirtualSiteData
(
site
,
atomIndices
))
typeName
=
atom
.
attrib
[
'type'
]
for
bond
in
residue
.
findall
(
'Bond'
):
template
.
atoms
.
append
(
ForceField
.
_TemplateAtomData
(
atomName
,
typeName
,
self
.
_atomTypes
[
typeName
].
element
,
params
))
if
'atomName1'
in
bond
.
attrib
:
for
site
in
residue
.
findall
(
'VirtualSite'
):
template
.
addBondByName
(
bond
.
attrib
[
'atomName1'
],
bond
.
attrib
[
'atomName2'
])
template
.
virtualSites
.
append
(
ForceField
.
_VirtualSiteData
(
site
,
atomIndices
))
else
:
for
bond
in
residue
.
findall
(
'Bond'
):
template
.
addBond
(
int
(
bond
.
attrib
[
'from'
]),
int
(
bond
.
attrib
[
'to'
]))
if
'atomName1'
in
bond
.
attrib
:
for
bond
in
residue
.
findall
(
'ExternalBond'
):
template
.
addBondByName
(
bond
.
attrib
[
'atomName1'
],
bond
.
attrib
[
'atomName2'
])
if
'atomName'
in
bond
.
attrib
:
else
:
template
.
addExternalBondByName
(
bond
.
attrib
[
'atomName'
])
template
.
addBond
(
int
(
bond
.
attrib
[
'from'
]),
int
(
bond
.
attrib
[
'to'
]))
else
:
for
bond
in
residue
.
findall
(
'ExternalBond'
):
template
.
addExternalBond
(
int
(
bond
.
attrib
[
'from'
]))
if
'atomName'
in
bond
.
attrib
:
self
.
registerResidueTemplate
(
template
)
template
.
addExternalBondByName
(
bond
.
attrib
[
'atomName'
])
else
:
template
.
addExternalBond
(
int
(
bond
.
attrib
[
'from'
]))
self
.
registerResidueTemplate
(
template
)
# Load force definitions
# Load force definitions
for
child
in
root
:
for
tree
in
trees
:
if
child
.
tag
in
parsers
:
for
child
in
tree
.
getroot
():
parsers
[
child
.
tag
](
child
,
self
)
if
child
.
tag
in
parsers
:
parsers
[
child
.
tag
](
child
,
self
)
# Load scripts
# Load scripts
for
node
in
tree
.
getroot
().
findall
(
'Script'
):
for
tree
in
trees
:
self
.
registerScript
(
node
.
text
)
for
node
in
tree
.
getroot
().
findall
(
'Script'
):
self
.
registerScript
(
node
.
text
)
def
getGenerators
(
self
):
def
getGenerators
(
self
):
"""Get the list of all registered generators."""
"""Get the list of all registered generators."""
...
@@ -237,7 +250,25 @@ class ForceField(object):
...
@@ -237,7 +250,25 @@ class ForceField(object):
self
.
_templates
[
template
.
name
]
=
template
self
.
_templates
[
template
.
name
]
=
template
signature
=
_createResidueSignature
([
atom
.
element
for
atom
in
template
.
atoms
])
signature
=
_createResidueSignature
([
atom
.
element
for
atom
in
template
.
atoms
])
if
signature
in
self
.
_templateSignatures
:
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
:
else
:
self
.
_templateSignatures
[
signature
]
=
[
template
]
self
.
_templateSignatures
[
signature
]
=
[
template
]
...
@@ -379,6 +410,7 @@ class ForceField(object):
...
@@ -379,6 +410,7 @@ class ForceField(object):
self
.
virtualSites
=
[]
self
.
virtualSites
=
[]
self
.
bonds
=
[]
self
.
bonds
=
[]
self
.
externalBonds
=
[]
self
.
externalBonds
=
[]
self
.
overloadLevel
=
0
def
getAtomIndexByName
(
self
,
atom_name
):
def
getAtomIndexByName
(
self
,
atom_name
):
"""Look up an atom index by atom name, providing a helpful error message if not found."""
"""Look up an atom index by atom name, providing a helpful error message if not found."""
...
@@ -566,11 +598,16 @@ class ForceField(object):
...
@@ -566,11 +598,16 @@ class ForceField(object):
matches
=
None
matches
=
None
signature
=
_createResidueSignature
([
atom
.
element
for
atom
in
res
.
atoms
()])
signature
=
_createResidueSignature
([
atom
.
element
for
atom
in
res
.
atoms
()])
if
signature
in
self
.
_templateSignatures
:
if
signature
in
self
.
_templateSignatures
:
allMatches
=
[]
for
t
in
self
.
_templateSignatures
[
signature
]:
for
t
in
self
.
_templateSignatures
[
signature
]:
matches
=
_matchResidue
(
res
,
t
,
bondedToAtom
)
match
=
_matchResidue
(
res
,
t
,
bondedToAtom
)
if
matches
is
not
None
:
if
match
is
not
None
:
template
=
t
allMatches
.
append
((
t
,
match
))
break
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
]
return
[
template
,
matches
]
def
_buildBondedToAtomList
(
self
,
topology
):
def
_buildBondedToAtomList
(
self
,
topology
):
...
@@ -703,7 +740,7 @@ class ForceField(object):
...
@@ -703,7 +740,7 @@ class ForceField(object):
return
[
templates
,
unique_unmatched_residues
]
return
[
templates
,
unique_unmatched_residues
]
def
createSystem
(
self
,
topology
,
nonbondedMethod
=
NoCutoff
,
nonbondedCutoff
=
1.0
*
unit
.
nanometer
,
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.
"""Construct an OpenMM System representing a Topology with this force field.
Parameters
Parameters
...
@@ -727,6 +764,13 @@ class ForceField(object):
...
@@ -727,6 +764,13 @@ class ForceField(object):
The mass to use for hydrogen atoms bound to heavy atoms. Any mass
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
added to a hydrogen is subtracted from the heavy atom to keep
their total mass the same.
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
args
Arbitrary additional keyword arguments may also be specified.
Arbitrary additional keyword arguments may also be specified.
This allows extra parameters to be specified that are specific to
This allows extra parameters to be specified that are specific to
...
@@ -765,8 +809,15 @@ class ForceField(object):
...
@@ -765,8 +809,15 @@ class ForceField(object):
for
chain
in
topology
.
chains
():
for
chain
in
topology
.
chains
():
for
res
in
chain
.
residues
():
for
res
in
chain
.
residues
():
# Attempt to match one of the existing templates.
if
res
in
residueTemplates
:
[
template
,
matches
]
=
self
.
_getResidueTemplateMatches
(
res
,
bondedToAtom
)
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
:
if
matches
is
None
:
# No existing templates match. Try any registered residue template generators.
# No existing templates match. Try any registered residue template generators.
for
generator
in
self
.
_templateGenerators
:
for
generator
in
self
.
_templateGenerators
:
...
@@ -1183,8 +1234,12 @@ class HarmonicBondGenerator(object):
...
@@ -1183,8 +1234,12 @@ class HarmonicBondGenerator(object):
@
staticmethod
@
staticmethod
def
parseElement
(
element
,
ff
):
def
parseElement
(
element
,
ff
):
generator
=
HarmonicBondGenerator
(
ff
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
HarmonicBondGenerator
)]
ff
.
registerGenerator
(
generator
)
if
len
(
existing
)
==
0
:
generator
=
HarmonicBondGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
bond
in
element
.
findall
(
'Bond'
):
for
bond
in
element
.
findall
(
'Bond'
):
generator
.
registerBond
(
bond
.
attrib
)
generator
.
registerBond
(
bond
.
attrib
)
...
@@ -1236,8 +1291,12 @@ class HarmonicAngleGenerator(object):
...
@@ -1236,8 +1291,12 @@ class HarmonicAngleGenerator(object):
@
staticmethod
@
staticmethod
def
parseElement
(
element
,
ff
):
def
parseElement
(
element
,
ff
):
generator
=
HarmonicAngleGenerator
(
ff
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
HarmonicAngleGenerator
)]
ff
.
registerGenerator
(
generator
)
if
len
(
existing
)
==
0
:
generator
=
HarmonicAngleGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
angle
in
element
.
findall
(
'Angle'
):
for
angle
in
element
.
findall
(
'Angle'
):
generator
.
registerAngle
(
angle
.
attrib
)
generator
.
registerAngle
(
angle
.
attrib
)
...
@@ -1320,8 +1379,12 @@ class PeriodicTorsionGenerator(object):
...
@@ -1320,8 +1379,12 @@ class PeriodicTorsionGenerator(object):
@
staticmethod
@
staticmethod
def
parseElement
(
element
,
ff
):
def
parseElement
(
element
,
ff
):
generator
=
PeriodicTorsionGenerator
(
ff
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
PeriodicTorsionGenerator
)]
ff
.
registerGenerator
(
generator
)
if
len
(
existing
)
==
0
:
generator
=
PeriodicTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
torsion
in
element
.
findall
(
'Proper'
):
for
torsion
in
element
.
findall
(
'Proper'
):
generator
.
registerProperTorsion
(
torsion
.
attrib
)
generator
.
registerProperTorsion
(
torsion
.
attrib
)
for
torsion
in
element
.
findall
(
'Improper'
):
for
torsion
in
element
.
findall
(
'Improper'
):
...
@@ -1419,8 +1482,12 @@ class RBTorsionGenerator(object):
...
@@ -1419,8 +1482,12 @@ class RBTorsionGenerator(object):
@
staticmethod
@
staticmethod
def
parseElement
(
element
,
ff
):
def
parseElement
(
element
,
ff
):
generator
=
RBTorsionGenerator
(
ff
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
RBTorsionGenerator
)]
ff
.
registerGenerator
(
generator
)
if
len
(
existing
)
==
0
:
generator
=
RBTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
torsion
in
element
.
findall
(
'Proper'
):
for
torsion
in
element
.
findall
(
'Proper'
):
types
=
ff
.
_findAtomTypes
(
torsion
.
attrib
,
4
)
types
=
ff
.
_findAtomTypes
(
torsion
.
attrib
,
4
)
if
None
not
in
types
:
if
None
not
in
types
:
...
@@ -1523,8 +1590,12 @@ class CMAPTorsionGenerator(object):
...
@@ -1523,8 +1590,12 @@ class CMAPTorsionGenerator(object):
@
staticmethod
@
staticmethod
def
parseElement
(
element
,
ff
):
def
parseElement
(
element
,
ff
):
generator
=
CMAPTorsionGenerator
(
ff
)
existing
=
[
f
for
f
in
ff
.
_forces
if
isinstance
(
f
,
CMAPTorsionGenerator
)]
ff
.
registerGenerator
(
generator
)
if
len
(
existing
)
==
0
:
generator
=
CMAPTorsionGenerator
(
ff
)
ff
.
registerGenerator
(
generator
)
else
:
generator
=
existing
[
0
]
for
map
in
element
.
findall
(
'Map'
):
for
map
in
element
.
findall
(
'Map'
):
values
=
[
float
(
x
)
for
x
in
map
.
text
.
split
()]
values
=
[
float
(
x
)
for
x
in
map
.
text
.
split
()]
size
=
sqrt
(
len
(
values
))
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
...
@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
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
Authors: Peter Eastman
Contributors: Jason Swails
Contributors: Jason Swails
...
@@ -814,7 +814,7 @@ class GromacsTopFile(object):
...
@@ -814,7 +814,7 @@ class GromacsTopFile(object):
map
=
[]
map
=
[]
for
i
in
range
(
mapSize
):
for
i
in
range
(
mapSize
):
for
j
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
)
map
=
tuple
(
map
)
if
map
not
in
mapIndices
:
if
map
not
in
mapIndices
:
mapIndices
[
map
]
=
cmap
.
addMap
(
mapSize
,
map
)
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):
...
@@ -335,7 +335,7 @@ def _mbondi3_radii(topology):
def
_createEnergyTerms
(
force
,
solventDielectric
,
soluteDielectric
,
SA
,
cutoff
,
kappa
,
offset
):
def
_createEnergyTerms
(
force
,
solventDielectric
,
soluteDielectric
,
SA
,
cutoff
,
kappa
,
offset
):
# Add the energy terms to the CustomGBForce. These are identical for all the GB models.
# 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
)
params
=
"; solventDielectric=%.16g; soluteDielectric=%.16g; kappa=%.16g; offset=%.16g"
%
(
solventDielectric
,
soluteDielectric
,
kappa
,
offset
)
if
cutoff
is
not
None
:
if
cutoff
is
not
None
:
params
+=
"; cutoff=%.16g"
%
cutoff
params
+=
"; cutoff=%.16g"
%
cutoff
...
@@ -535,7 +535,7 @@ class GBSAGBnForce(CustomAmberGBForce):
...
@@ -535,7 +535,7 @@ class GBSAGBnForce(CustomAmberGBForce):
def
addParticle
(
self
,
parameters
):
def
addParticle
(
self
,
parameters
):
parameters
=
CustomAmberGBForce
.
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'
)
raise
ValueError
(
'Radii must be between 1 and 2 Angstroms for neck lookup'
)
def
setParticleParameters
(
self
,
idx
,
parameters
):
def
setParticleParameters
(
self
,
idx
,
parameters
):
...
...
wrappers/python/simtk/openmm/app/modeller.py
View file @
73183c61
...
@@ -35,7 +35,7 @@ __author__ = "Peter Eastman"
...
@@ -35,7 +35,7 @@ __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
,
_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.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
,
LocalEnergyMinimizer
...
@@ -857,7 +857,7 @@ class Modeller(object):
...
@@ -857,7 +857,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
)
system
=
forcefield
.
createSystem
(
newTopology
,
rigidWater
=
False
,
nonbondedMethod
=
CutoffNonPeriodic
)
atoms
=
list
(
newTopology
.
atoms
())
atoms
=
list
(
newTopology
.
atoms
())
for
i
in
range
(
system
.
getNumParticles
()):
for
i
in
range
(
system
.
getNumParticles
()):
if
atoms
[
i
].
element
!=
elem
.
hydrogen
:
if
atoms
[
i
].
element
!=
elem
.
hydrogen
:
...
@@ -869,6 +869,8 @@ class Modeller(object):
...
@@ -869,6 +869,8 @@ class Modeller(object):
system
=
System
()
system
=
System
()
nonbonded
=
CustomNonbondedForce
(
'100/((r/0.1)^4+1)'
)
nonbonded
=
CustomNonbondedForce
(
'100/((r/0.1)^4+1)'
)
nonbonded
.
setNonbondedMethod
(
CustomNonbondedForce
.
CutoffNonPeriodic
);
nonbonded
.
setCutoffDistance
(
1
*
nanometer
)
bonds
=
HarmonicBondForce
()
bonds
=
HarmonicBondForce
()
angles
=
HarmonicAngleForce
()
angles
=
HarmonicAngleForce
()
system
.
addForce
(
nonbonded
)
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
...
@@ -6,7 +6,7 @@ Simbios, the NIH National Center for Physics-Based Simulation of
Biological Structures at Stanford, funded under the NIH Roadmap for
Biological Structures at Stanford, funded under the NIH Roadmap for
Medical Research, grant U54 GM072970. See https://simtk.org.
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
Authors: Peter Eastman
Contributors:
Contributors:
...
@@ -58,6 +58,9 @@ class PDBFile(object):
...
@@ -58,6 +58,9 @@ class PDBFile(object):
_residueNameReplacements
=
{}
_residueNameReplacements
=
{}
_atomNameReplacements
=
{}
_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'
):
def
__init__
(
self
,
file
,
extraParticleIdentifier
=
'EP'
):
"""Load a PDB file.
"""Load a PDB file.
...
@@ -75,10 +78,6 @@ class PDBFile(object):
...
@@ -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'
,
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'
]
'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
()
top
=
Topology
()
## The Topology read from the PDB file
## The Topology read from the PDB file
self
.
topology
=
top
self
.
topology
=
top
...
@@ -173,9 +172,9 @@ class PDBFile(object):
...
@@ -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
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
:
if
atomByNumber
[
i
].
element
.
symbol
not
in
metalElements
and
atomByNumber
[
j
].
element
.
symbol
not
in
metalElements
:
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
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
]))
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
]))
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
else
:
else
:
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
connectBonds
.
append
((
atomByNumber
[
i
],
atomByNumber
[
j
]))
...
@@ -331,6 +330,8 @@ class PDBFile(object):
...
@@ -331,6 +330,8 @@ class PDBFile(object):
raise
ValueError
(
'Particle position is NaN'
)
raise
ValueError
(
'Particle position is NaN'
)
if
any
(
math
.
isinf
(
norm
(
pos
))
for
pos
in
positions
):
if
any
(
math
.
isinf
(
norm
(
pos
))
for
pos
in
positions
):
raise
ValueError
(
'Particle position is infinite'
)
raise
ValueError
(
'Particle position is infinite'
)
nonHeterogens
=
PDBFile
.
_standardResidues
[:]
nonHeterogens
.
remove
(
'HOH'
)
atomIndex
=
1
atomIndex
=
1
posIndex
=
0
posIndex
=
0
if
modelIndex
is
not
None
:
if
modelIndex
is
not
None
:
...
@@ -350,6 +351,10 @@ class PDBFile(object):
...
@@ -350,6 +351,10 @@ class PDBFile(object):
resId
=
res
.
id
resId
=
res
.
id
else
:
else
:
resId
=
"%4d"
%
((
resIndex
+
1
)
%
10000
)
resId
=
"%4d"
%
((
resIndex
+
1
)
%
10000
)
if
res
.
name
in
nonHeterogens
:
recordName
=
"ATOM "
else
:
recordName
=
"HETATM"
for
atom
in
res
.
atoms
():
for
atom
in
res
.
atoms
():
if
atom
.
element
is
not
None
:
if
atom
.
element
is
not
None
:
symbol
=
atom
.
element
.
symbol
symbol
=
atom
.
element
.
symbol
...
@@ -362,8 +367,8 @@ class PDBFile(object):
...
@@ -362,8 +367,8 @@ class PDBFile(object):
else
:
else
:
atomName
=
atom
.
name
atomName
=
atom
.
name
coords
=
positions
[
posIndex
]
coords
=
positions
[
posIndex
]
line
=
"
ATOM
%5d %-4s %3s %s%4s %s%s%s 1.00 0.00 %2s "
%
(
line
=
"
%s
%5d %-4s %3s %s%4s %s%s%s 1.00 0.00 %2s "
%
(
atomIndex
%
100000
,
atomName
,
resName
,
chainName
,
resId
,
_format_83
(
coords
[
0
]),
recordName
,
atomIndex
%
100000
,
atomName
,
resName
,
chainName
,
resId
,
_format_83
(
coords
[
0
]),
_format_83
(
coords
[
1
]),
_format_83
(
coords
[
2
]),
symbol
)
_format_83
(
coords
[
1
]),
_format_83
(
coords
[
2
]),
symbol
)
assert
len
(
line
)
==
80
,
'Fixed width overflow detected'
assert
len
(
line
)
==
80
,
'Fixed width overflow detected'
print
(
line
,
file
=
file
)
print
(
line
,
file
=
file
)
...
@@ -388,12 +393,9 @@ class PDBFile(object):
...
@@ -388,12 +393,9 @@ class PDBFile(object):
"""
"""
# Identify bonds that should be listed as CONECT records.
# 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
=
[]
conectBonds
=
[]
for
atom1
,
atom2
in
topology
.
bonds
():
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
))
conectBonds
.
append
((
atom1
,
atom2
))
elif
atom1
.
name
==
'SG'
and
atom2
.
name
==
'SG'
and
atom1
.
residue
.
name
==
'CYS'
and
atom2
.
residue
.
name
==
'CYS'
:
elif
atom1
.
name
==
'SG'
and
atom2
.
name
==
'SG'
and
atom1
.
residue
.
name
==
'CYS'
and
atom2
.
residue
.
name
==
'CYS'
:
conectBonds
.
append
((
atom1
,
atom2
))
conectBonds
.
append
((
atom1
,
atom2
))
...
...
wrappers/python/tests/TestAmberPrmtopFile.py
View file @
73183c61
...
@@ -361,5 +361,17 @@ class TestAmberPrmtopFile(unittest.TestCase):
...
@@ -361,5 +361,17 @@ class TestAmberPrmtopFile(unittest.TestCase):
# Make sure it says something about chamber
# Make sure it says something about chamber
self
.
assertTrue
(
'chamber'
in
str
(
e
).
lower
())
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__'
:
if
__name__
==
'__main__'
:
unittest
.
main
()
unittest
.
main
()
wrappers/python/tests/TestForceField.py
View file @
73183c61
...
@@ -449,6 +449,183 @@ class TestForceField(unittest.TestCase):
...
@@ -449,6 +449,183 @@ class TestForceField(unittest.TestCase):
self
.
assertEqual
(
templates
[
1
].
name
,
'ALA'
)
self
.
assertEqual
(
templates
[
1
].
name
,
'ALA'
)
self
.
assertEqual
(
templates
[
2
].
name
,
'CALA'
)
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
):
class
AmoebaTestForceField
(
unittest
.
TestCase
):
"""Test the ForceField.createSystem() method with the AMOEBA forcefield."""
"""Test the ForceField.createSystem() method with the AMOEBA forcefield."""
...
@@ -539,11 +716,9 @@ class AmoebaTestForceField(unittest.TestCase):
...
@@ -539,11 +716,9 @@ class AmoebaTestForceField(unittest.TestCase):
def
test_LennardJones_generator
(
self
):
def
test_LennardJones_generator
(
self
):
""" Test the LennardJones generator"""
""" Test the LennardJones generator"""
warnings
.
filterwarnings
(
'ignore'
,
category
=
CharmmPSFWarning
)
warnings
.
filterwarnings
(
'ignore'
,
category
=
CharmmPSFWarning
)
psf
=
CharmmPsfFile
(
'systems/methanol_ions.psf'
)
psf
=
CharmmPsfFile
(
'systems/ions.psf'
)
pdb
=
PDBFile
(
'systems/methanol_ions.pdb'
)
pdb
=
PDBFile
(
'systems/ions.pdb'
)
params
=
CharmmParameterSet
(
'systems/top_all36_cgenff.rtf'
,
params
=
CharmmParameterSet
(
'systems/toppar_water_ions.str'
'systems/par_all36_cgenff.prm'
,
'systems/toppar_water_ions.str'
)
)
# Box dimensions (found from bounding box)
# Box dimensions (found from bounding box)
...
@@ -565,27 +740,10 @@ class AmoebaTestForceField(unittest.TestCase):
...
@@ -565,27 +740,10 @@ class AmoebaTestForceField(unittest.TestCase):
xml
=
"""
xml
=
"""
<ForceField>
<ForceField>
<AtomTypes>
<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="SOD" class="SOD" element="Na" mass="22.98977"/>
<Type name="CLA" class="CLA" element="Cl" mass="35.45"/>
<Type name="CLA" class="CLA" element="Cl" mass="35.45"/>
</AtomTypes>
</AtomTypes>
<Residues>
<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">
<Residue name="CLA">
<Atom name="CLA" type="CLA" charge="0.0"/>
<Atom name="CLA" type="CLA" charge="0.0"/>
</Residue>
</Residue>
...
@@ -593,37 +751,12 @@ class AmoebaTestForceField(unittest.TestCase):
...
@@ -593,37 +751,12 @@ class AmoebaTestForceField(unittest.TestCase):
<Atom name="SOD" type="SOD" charge="0.0"/>
<Atom name="SOD" type="SOD" charge="0.0"/>
</Residue>
</Residue>
</Residues>
</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">
<NonbondedForce coulomb14scale="1.0" lj14scale="1.0">
<UseAttributeFromResidue name="charge"/>
<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="SOD" sigma="1.0" epsilon="0.0"/>
<Atom type="CLA" sigma="1.0" epsilon="0.0"/>
<Atom type="CLA" sigma="1.0" epsilon="0.0"/>
</NonbondedForce>
</NonbondedForce>
<LennardJonesForce lj14scale="1.0">
<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="CLA" sigma="0.404468018036" epsilon="0.6276"/>
<Atom type="SOD" sigma="0.251367073323" epsilon="0.1962296"/>
<Atom type="SOD" sigma="0.251367073323" epsilon="0.1962296"/>
<NBFixPair type1="CLA" type2="SOD" emin="0.350933" rmin="0.3731"/>
<NBFixPair type1="CLA" type2="SOD" emin="0.350933" rmin="0.3731"/>
...
@@ -641,50 +774,5 @@ class AmoebaTestForceField(unittest.TestCase):
...
@@ -641,50 +774,5 @@ class AmoebaTestForceField(unittest.TestCase):
ene2
=
state2
.
getPotentialEnergy
().
value_in_unit
(
kilocalories_per_mole
)
ene2
=
state2
.
getPotentialEnergy
().
value_in_unit
(
kilocalories_per_mole
)
self
.
assertAlmostEqual
(
ene
,
ene2
)
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__'
:
if
__name__
==
'__main__'
:
unittest
.
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