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
4e62a24f
Commit
4e62a24f
authored
Feb 06, 2015
by
Peter Eastman
Browse files
Adding triclinic box support to Python layer
parent
83ed602e
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
191 additions
and
29 deletions
+191
-29
wrappers/python/CMakeLists.txt
wrappers/python/CMakeLists.txt
+1
-0
wrappers/python/simtk/openmm/app/forcefield.py
wrappers/python/simtk/openmm/app/forcefield.py
+4
-4
wrappers/python/simtk/openmm/app/gromacsgrofile.py
wrappers/python/simtk/openmm/app/gromacsgrofile.py
+26
-3
wrappers/python/simtk/openmm/app/internal/pdbstructure.py
wrappers/python/simtk/openmm/app/internal/pdbstructure.py
+30
-6
wrappers/python/simtk/openmm/app/modeller.py
wrappers/python/simtk/openmm/app/modeller.py
+6
-6
wrappers/python/simtk/openmm/app/pdbfile.py
wrappers/python/simtk/openmm/app/pdbfile.py
+1
-1
wrappers/python/simtk/openmm/app/pdbxfile.py
wrappers/python/simtk/openmm/app/pdbxfile.py
+17
-2
wrappers/python/simtk/openmm/app/topology.py
wrappers/python/simtk/openmm/app/topology.py
+40
-6
wrappers/python/tests/TestForceField.py
wrappers/python/tests/TestForceField.py
+13
-1
wrappers/python/tests/TestGromacsGroFile.py
wrappers/python/tests/TestGromacsGroFile.py
+42
-0
wrappers/python/tests/systems/triclinic.gro
wrappers/python/tests/systems/triclinic.gro
+11
-0
No files found.
wrappers/python/CMakeLists.txt
View file @
4e62a24f
...
@@ -58,6 +58,7 @@ foreach(SUBDIR ${SUBDIRS})
...
@@ -58,6 +58,7 @@ foreach(SUBDIR ${SUBDIRS})
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.prm"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.prm"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.inpcrd"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.inpcrd"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.crd"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.crd"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.gro"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.parm7"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.parm7"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.rst7"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.rst7"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.ncrst"
"
${
CMAKE_CURRENT_SOURCE_DIR
}
/
${
SUBDIR
}
/*.ncrst"
...
...
wrappers/python/simtk/openmm/app/forcefield.py
View file @
4e62a24f
...
@@ -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
4
Stanford University and the Authors.
Portions copyright (c) 2012-201
5
Stanford University and the Authors.
Authors: Peter Eastman, Mark Friedrichs
Authors: Peter Eastman, Mark Friedrichs
Contributors:
Contributors:
...
@@ -403,9 +403,9 @@ class ForceField(object):
...
@@ -403,9 +403,9 @@ class ForceField(object):
# Set periodic boundary conditions.
# Set periodic boundary conditions.
box
Size
=
topology
.
get
UnitCellDimension
s
()
box
Vectors
=
topology
.
get
PeriodicBoxVector
s
()
if
box
Size
is
not
None
:
if
box
Vectors
is
not
None
:
sys
.
setDefaultPeriodicBoxVectors
(
(
box
Size
[
0
],
0
,
0
),
(
0
,
boxSize
[
1
],
0
),
(
0
,
0
,
boxSize
[
2
])
)
sys
.
setDefaultPeriodicBoxVectors
(
box
Vectors
[
0
],
boxVectors
[
1
],
boxVectors
[
2
])
elif
nonbondedMethod
is
not
NoCutoff
and
nonbondedMethod
is
not
CutoffNonPeriodic
:
elif
nonbondedMethod
is
not
NoCutoff
and
nonbondedMethod
is
not
CutoffNonPeriodic
:
raise
ValueError
(
'Requested periodic boundary conditions for a Topology that does not specify periodic box dimensions'
)
raise
ValueError
(
'Requested periodic boundary conditions for a Topology that does not specify periodic box dimensions'
)
...
...
wrappers/python/simtk/openmm/app/gromacsgrofile.py
View file @
4e62a24f
...
@@ -89,6 +89,18 @@ def _is_gro_box(line):
...
@@ -89,6 +89,18 @@ def _is_gro_box(line):
else
:
else
:
return
0
return
0
def
_construct_box_vectors
(
line
):
"""Create the periodic box vectors based on the values stored in the file.
@param[in] line The line containing the description
"""
sline
=
line
.
split
()
values
=
[
float
(
i
)
for
i
in
sline
]
if
len
(
sline
)
==
3
:
return
(
Vec3
(
values
[
0
],
0
,
0
),
Vec3
(
0
,
values
[
1
],
0
),
Vec3
(
0
,
0
,
values
[
2
]))
*
nanometers
return
(
Vec3
(
values
[
0
],
values
[
3
],
values
[
4
]),
Vec3
(
values
[
5
],
values
[
1
],
values
[
6
]),
Vec3
(
values
[
7
],
values
[
8
],
values
[
2
]))
*
nanometers
class
GromacsGroFile
(
object
):
class
GromacsGroFile
(
object
):
"""GromacsGroFile parses a Gromacs .gro file and constructs a set of atom positions from it.
"""GromacsGroFile parses a Gromacs .gro file and constructs a set of atom positions from it.
...
@@ -140,7 +152,7 @@ class GromacsGroFile(object):
...
@@ -140,7 +152,7 @@ class GromacsGroFile(object):
xyz
.
append
(
Vec3
(
pos
[
0
],
pos
[
1
],
pos
[
2
]))
xyz
.
append
(
Vec3
(
pos
[
0
],
pos
[
1
],
pos
[
2
]))
elif
_is_gro_box
(
line
)
and
ln
==
na
+
2
:
elif
_is_gro_box
(
line
)
and
ln
==
na
+
2
:
sline
=
line
.
split
()
sline
=
line
.
split
()
boxes
.
append
(
tuple
([
float
(
i
)
for
i
in
sline
])
*
nanometers
)
boxes
.
append
(
_construct_box_vectors
(
line
)
)
xyzs
.
append
(
xyz
*
nanometers
)
xyzs
.
append
(
xyz
*
nanometers
)
xyz
=
[]
xyz
=
[]
ln
=
-
1
ln
=
-
1
...
@@ -160,7 +172,7 @@ class GromacsGroFile(object):
...
@@ -160,7 +172,7 @@ class GromacsGroFile(object):
## A list containing the name of the residue that each atom belongs to
## A list containing the name of the residue that each atom belongs to
self
.
residueNames
=
resname
self
.
residueNames
=
resname
self
.
_positions
=
xyzs
self
.
_positions
=
xyzs
self
.
_
unitCellDimension
s
=
boxes
self
.
_
periodicBoxVector
s
=
boxes
self
.
_numpyPositions
=
None
self
.
_numpyPositions
=
None
def
getNumFrames
(
self
):
def
getNumFrames
(
self
):
...
@@ -182,10 +194,21 @@ class GromacsGroFile(object):
...
@@ -182,10 +194,21 @@ class GromacsGroFile(object):
return
self
.
_numpyPositions
[
frame
]
return
self
.
_numpyPositions
[
frame
]
return
self
.
_positions
[
frame
]
return
self
.
_positions
[
frame
]
def
getPeriodicBoxVectors
(
self
,
frame
=
0
):
"""Get the vectors defining the periodic box.
Parameters:
- frame (int=0) the index of the frame for which to get the box vectors
"""
return
self
.
_periodicBoxVectors
[
frame
]
def
getUnitCellDimensions
(
self
,
frame
=
0
):
def
getUnitCellDimensions
(
self
,
frame
=
0
):
"""Get the dimensions of the crystallographic unit cell.
"""Get the dimensions of the crystallographic unit cell.
Parameters:
Parameters:
- frame (int=0) the index of the frame for which to get the unit cell dimensions
- frame (int=0) the index of the frame for which to get the unit cell dimensions
"""
"""
return
self
.
_unitCellDimensions
[
frame
]
xsize
=
self
.
_periodicBoxVectors
[
frame
][
0
][
0
].
value_in_unit
(
nanometers
)
ysize
=
self
.
_periodicBoxVectors
[
frame
][
1
][
1
].
value_in_unit
(
nanometers
)
zsize
=
self
.
_periodicBoxVectors
[
frame
][
2
][
2
].
value_in_unit
(
nanometers
)
return
Vec3
(
xsize
,
ysize
,
zsize
)
*
nanometers
wrappers/python/simtk/openmm/app/internal/pdbstructure.py
View file @
4e62a24f
...
@@ -39,6 +39,7 @@ import simtk.unit as unit
...
@@ -39,6 +39,7 @@ import simtk.unit as unit
from
..
import
element
from
..
import
element
import
warnings
import
warnings
import
sys
import
sys
import
math
class
PdbStructure
(
object
):
class
PdbStructure
(
object
):
"""
"""
...
@@ -137,7 +138,7 @@ class PdbStructure(object):
...
@@ -137,7 +138,7 @@ class PdbStructure(object):
self
.
_current_model
=
None
self
.
_current_model
=
None
self
.
default_model
=
None
self
.
default_model
=
None
self
.
models_by_number
=
{}
self
.
models_by_number
=
{}
self
.
_
unit_cell_dimension
s
=
None
self
.
_
periodic_box_vector
s
=
None
self
.
sequences
=
[]
self
.
sequences
=
[]
self
.
modified_residues
=
[]
self
.
modified_residues
=
[]
# read file
# read file
...
@@ -170,7 +171,7 @@ class PdbStructure(object):
...
@@ -170,7 +171,7 @@ class PdbStructure(object):
self
.
_current_model
.
_current_chain
.
_add_ter_record
()
self
.
_current_model
.
_current_chain
.
_add_ter_record
()
self
.
_reset_residue_numbers
()
self
.
_reset_residue_numbers
()
elif
(
pdb_line
.
find
(
"CRYST1"
)
==
0
):
elif
(
pdb_line
.
find
(
"CRYST1"
)
==
0
):
self
.
_
unit_cell_dimensions
=
Vec3
(
float
(
pdb_line
[
6
:
15
]),
float
(
pdb_line
[
15
:
24
]),
float
(
pdb_line
[
24
:
33
]))
*
unit
.
angstroms
self
.
_
compute_periodic_box_vectors
(
pdb_line
)
elif
(
pdb_line
.
find
(
"CONECT"
)
==
0
):
elif
(
pdb_line
.
find
(
"CONECT"
)
==
0
):
atoms
=
[
int
(
pdb_line
[
6
:
11
])]
atoms
=
[
int
(
pdb_line
[
6
:
11
])]
for
pos
in
(
11
,
16
,
21
,
26
):
for
pos
in
(
11
,
16
,
21
,
26
):
...
@@ -187,7 +188,30 @@ class PdbStructure(object):
...
@@ -187,7 +188,30 @@ class PdbStructure(object):
elif
(
pdb_line
.
find
(
"MODRES"
)
==
0
):
elif
(
pdb_line
.
find
(
"MODRES"
)
==
0
):
self
.
modified_residues
.
append
(
ModifiedResidue
(
pdb_line
[
16
],
int
(
pdb_line
[
18
:
22
]),
pdb_line
[
12
:
15
].
strip
(),
pdb_line
[
24
:
27
].
strip
()))
self
.
modified_residues
.
append
(
ModifiedResidue
(
pdb_line
[
16
],
int
(
pdb_line
[
18
:
22
]),
pdb_line
[
12
:
15
].
strip
(),
pdb_line
[
24
:
27
].
strip
()))
self
.
_finalize
()
self
.
_finalize
()
def
_compute_periodic_box_vectors
(
self
,
line
):
"""Parse a CRYST1 record to compute the periodic box vectors."""
a_length
=
float
(
line
[
6
:
15
])
b_length
=
float
(
line
[
15
:
24
])
c_length
=
float
(
line
[
24
:
33
])
alpha
=
float
(
line
[
33
:
40
])
*
math
.
pi
/
180.0
beta
=
float
(
line
[
40
:
47
])
*
math
.
pi
/
180.0
gamma
=
float
(
line
[
47
:
54
])
*
math
.
pi
/
180.0
a
=
[
a_length
,
0
,
0
]
b
=
[
b_length
*
math
.
cos
(
gamma
),
b_length
*
math
.
sin
(
gamma
),
0
]
cx
=
c_length
*
math
.
cos
(
beta
)
cy
=
c_length
*
(
math
.
cos
(
alpha
)
-
math
.
cos
(
beta
)
*
math
.
cos
(
gamma
))
cz
=
math
.
sqrt
(
c_length
*
c_length
-
cx
*
cx
-
cy
*
cy
)
c
=
[
cx
,
cy
,
cz
]
for
i
in
range
(
3
):
if
abs
(
a
[
i
])
<
1e-6
:
a
[
i
]
=
0.0
if
abs
(
b
[
i
])
<
1e-6
:
b
[
i
]
=
0.0
if
abs
(
c
[
i
])
<
1e-6
:
c
[
i
]
=
0.0
self
.
_periodic_box_vectors
=
(
Vec3
(
*
a
),
Vec3
(
*
b
),
Vec3
(
*
c
))
*
unit
.
angstroms
def
_reset_atom_numbers
(
self
):
def
_reset_atom_numbers
(
self
):
self
.
_atom_numbers_are_hex
=
False
self
.
_atom_numbers_are_hex
=
False
self
.
_next_atom_number
=
1
self
.
_next_atom_number
=
1
...
@@ -283,9 +307,9 @@ class PdbStructure(object):
...
@@ -283,9 +307,9 @@ class PdbStructure(object):
for
model
in
self
.
models
:
for
model
in
self
.
models
:
model
.
_finalize
()
model
.
_finalize
()
def
get_
unit_cell_dimension
s
(
self
):
def
get_
periodic_box_vector
s
(
self
):
"""Get the
dimensions of
the crystallographic unit cell (may be None)."""
"""Get the
vectors defining
the crystallographic unit cell (may be None)."""
return
self
.
_
unit_cell_dimension
s
return
self
.
_
periodic_box_vector
s
class
Sequence
(
object
):
class
Sequence
(
object
):
...
...
wrappers/python/simtk/openmm/app/modeller.py
View file @
4e62a24f
...
@@ -94,7 +94,7 @@ class Modeller(object):
...
@@ -94,7 +94,7 @@ class Modeller(object):
# Copy over the existing model.
# Copy over the existing model.
newTopology
=
Topology
()
newTopology
=
Topology
()
newTopology
.
setUnitCellDimensions
(
deepcopy
(
self
.
topology
.
getUnitCellDimensions
())
)
newTopology
.
setUnitCellDimensions
(
self
.
topology
.
getUnitCellDimensions
())
newAtoms
=
{}
newAtoms
=
{}
newPositions
=
[]
*
nanometer
newPositions
=
[]
*
nanometer
for
chain
in
self
.
topology
.
chains
():
for
chain
in
self
.
topology
.
chains
():
...
@@ -140,7 +140,7 @@ class Modeller(object):
...
@@ -140,7 +140,7 @@ class Modeller(object):
- toDelete (list) a list of Atoms, Residues, Chains, and bonds (specified as tuples of Atoms) to delete
- toDelete (list) a list of Atoms, Residues, Chains, and bonds (specified as tuples of Atoms) to delete
"""
"""
newTopology
=
Topology
()
newTopology
=
Topology
()
newTopology
.
setUnitCellDimensions
(
deepcopy
(
self
.
topology
.
getUnitCellDimensions
())
)
newTopology
.
setUnitCellDimensions
(
self
.
topology
.
getUnitCellDimensions
())
newAtoms
=
{}
newAtoms
=
{}
newPositions
=
[]
*
nanometer
newPositions
=
[]
*
nanometer
deleteSet
=
set
(
toDelete
)
deleteSet
=
set
(
toDelete
)
...
@@ -189,7 +189,7 @@ class Modeller(object):
...
@@ -189,7 +189,7 @@ class Modeller(object):
else
:
else
:
raise
ValueError
(
'Unknown water model: %s'
%
model
)
raise
ValueError
(
'Unknown water model: %s'
%
model
)
newTopology
=
Topology
()
newTopology
=
Topology
()
newTopology
.
setUnitCellDimensions
(
deepcopy
(
self
.
topology
.
getUnitCellDimensions
())
)
newTopology
.
setUnitCellDimensions
(
self
.
topology
.
getUnitCellDimensions
())
newAtoms
=
{}
newAtoms
=
{}
newPositions
=
[]
*
nanometer
newPositions
=
[]
*
nanometer
for
chain
in
self
.
topology
.
chains
():
for
chain
in
self
.
topology
.
chains
():
...
@@ -472,7 +472,7 @@ class Modeller(object):
...
@@ -472,7 +472,7 @@ class Modeller(object):
for
atom2
in
molAtoms
:
for
atom2
in
molAtoms
:
if
atom2
.
element
==
elem
.
hydrogen
:
if
atom2
.
element
==
elem
.
hydrogen
:
newTopology
.
addBond
(
atom1
,
atom2
)
newTopology
.
addBond
(
atom1
,
atom2
)
newTopology
.
setUnitCellDimensions
(
deepcopy
(
box
)
*
nanometer
)
newTopology
.
setUnitCellDimensions
(
box
*
nanometer
)
self
.
topology
=
newTopology
self
.
topology
=
newTopology
self
.
positions
=
newPositions
self
.
positions
=
newPositions
...
@@ -610,7 +610,7 @@ class Modeller(object):
...
@@ -610,7 +610,7 @@ class Modeller(object):
# Loop over residues.
# Loop over residues.
newTopology
=
Topology
()
newTopology
=
Topology
()
newTopology
.
setUnitCellDimensions
(
deepcopy
(
self
.
topology
.
getUnitCellDimensions
())
)
newTopology
.
setUnitCellDimensions
(
self
.
topology
.
getUnitCellDimensions
())
newAtoms
=
{}
newAtoms
=
{}
newPositions
=
[]
*
nanometer
newPositions
=
[]
*
nanometer
newIndices
=
[]
newIndices
=
[]
...
@@ -883,7 +883,7 @@ class Modeller(object):
...
@@ -883,7 +883,7 @@ class Modeller(object):
# Create the new Topology.
# Create the new Topology.
newTopology
=
Topology
()
newTopology
=
Topology
()
newTopology
.
setUnitCellDimensions
(
deepcopy
(
self
.
topology
.
getUnitCellDimensions
())
)
newTopology
.
setUnitCellDimensions
(
self
.
topology
.
getUnitCellDimensions
())
newAtoms
=
{}
newAtoms
=
{}
newPositions
=
[]
*
nanometer
newPositions
=
[]
*
nanometer
for
chain
in
self
.
topology
.
chains
():
for
chain
in
self
.
topology
.
chains
():
...
...
wrappers/python/simtk/openmm/app/pdbfile.py
View file @
4e62a24f
...
@@ -142,7 +142,7 @@ class PDBFile(object):
...
@@ -142,7 +142,7 @@ class PDBFile(object):
self
.
_positions
.
append
(
coords
*
nanometers
)
self
.
_positions
.
append
(
coords
*
nanometers
)
## The atom positions read from the PDB file. If the file contains multiple frames, these are the positions in the first frame.
## The atom positions read from the PDB file. If the file contains multiple frames, these are the positions in the first frame.
self
.
positions
=
self
.
_positions
[
0
]
self
.
positions
=
self
.
_positions
[
0
]
self
.
topology
.
set
UnitCellDimensions
(
pdb
.
get_unit_cell_dimension
s
())
self
.
topology
.
set
PeriodicBoxVectors
(
pdb
.
get_periodic_box_vector
s
())
self
.
topology
.
createStandardBonds
()
self
.
topology
.
createStandardBonds
()
self
.
topology
.
createDisulfideBonds
(
self
.
positions
)
self
.
topology
.
createDisulfideBonds
(
self
.
positions
)
self
.
_numpyPositions
=
None
self
.
_numpyPositions
=
None
...
...
wrappers/python/simtk/openmm/app/pdbxfile.py
View file @
4e62a24f
...
@@ -33,6 +33,7 @@ __version__ = "1.0"
...
@@ -33,6 +33,7 @@ __version__ = "1.0"
import
os
import
os
import
sys
import
sys
import
math
from
simtk.openmm
import
Vec3
from
simtk.openmm
import
Vec3
from
simtk.openmm.app.internal.pdbx.reader.PdbxReader
import
PdbxReader
from
simtk.openmm.app.internal.pdbx.reader.PdbxReader
import
PdbxReader
from
simtk.openmm.app
import
Topology
from
simtk.openmm.app
import
Topology
...
@@ -145,8 +146,22 @@ class PDBxFile(object):
...
@@ -145,8 +146,22 @@ class PDBxFile(object):
cell
=
block
.
getObj
(
'cell'
)
cell
=
block
.
getObj
(
'cell'
)
if
cell
is
not
None
and
cell
.
getRowCount
()
>
0
:
if
cell
is
not
None
and
cell
.
getRowCount
()
>
0
:
row
=
cell
.
getRow
(
0
)
row
=
cell
.
getRow
(
0
)
cellSize
=
[
float
(
row
[
cell
.
getAttributeIndex
(
attribute
)])
for
attribute
in
(
'length_a'
,
'length_b'
,
'length_c'
)]
*
angstroms
(
a
,
b
,
c
)
=
[
float
(
row
[
cell
.
getAttributeIndex
(
attribute
)])
for
attribute
in
(
'length_a'
,
'length_b'
,
'length_c'
)]
self
.
topology
.
setUnitCellDimensions
(
cellSize
)
(
alpha
,
beta
,
gamma
)
=
[
float
(
row
[
cell
.
getAttributeIndex
(
attribute
)])
for
attribute
in
(
'angle_alpha'
,
'angle_beta'
,
'angle_gamma'
)
*
math
.
pi
/
180.0
]
a
=
[
a_length
,
0
,
0
]
b
=
[
b_length
*
math
.
cos
(
gamma
),
b_length
*
math
.
sin
(
gamma
),
0
]
cx
=
c_length
*
math
.
cos
(
beta
)
cy
=
c_length
*
(
math
.
cos
(
alpha
)
-
math
.
cos
(
beta
)
*
math
.
cos
(
gamma
))
cz
=
math
.
sqrt
(
c_length
*
c_length
-
cx
*
cx
-
cy
*
cy
)
c
=
[
cx
,
cy
,
cz
]
for
i
in
range
(
3
):
if
abs
(
a
[
i
])
<
1e-6
:
a
[
i
]
=
0.0
if
abs
(
b
[
i
])
<
1e-6
:
b
[
i
]
=
0.0
if
abs
(
c
[
i
])
<
1e-6
:
c
[
i
]
=
0.0
self
.
topology
.
setPeriodicBoxVectors
((
Vec3
(
*
a
),
Vec3
(
*
b
),
Vec3
(
*
c
))
*
unit
.
angstroms
)
# Add bonds based on struct_conn records.
# Add bonds based on struct_conn records.
...
...
wrappers/python/simtk/openmm/app/topology.py
View file @
4e62a24f
...
@@ -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
3
Stanford University and the Authors.
Portions copyright (c) 2012-201
5
Stanford University and the Authors.
Authors: Peter Eastman
Authors: Peter Eastman
Contributors:
Contributors:
...
@@ -33,7 +33,9 @@ __version__ = "1.0"
...
@@ -33,7 +33,9 @@ __version__ = "1.0"
import
os
import
os
import
xml.etree.ElementTree
as
etree
import
xml.etree.ElementTree
as
etree
from
simtk.unit
import
nanometers
,
sqrt
from
simtk.openmm.vec3
import
Vec3
from
simtk.unit
import
nanometers
,
sqrt
,
is_quantity
from
copy
import
deepcopy
class
Topology
(
object
):
class
Topology
(
object
):
"""Topology stores the topological information about a system.
"""Topology stores the topological information about a system.
...
@@ -55,7 +57,7 @@ class Topology(object):
...
@@ -55,7 +57,7 @@ class Topology(object):
self
.
_numResidues
=
0
self
.
_numResidues
=
0
self
.
_numAtoms
=
0
self
.
_numAtoms
=
0
self
.
_bonds
=
[]
self
.
_bonds
=
[]
self
.
_
unitCellDimension
s
=
None
self
.
_
periodicBoxVector
s
=
None
def
addChain
(
self
):
def
addChain
(
self
):
"""Create a new Chain and add it to the Topology.
"""Create a new Chain and add it to the Topology.
...
@@ -123,16 +125,48 @@ class Topology(object):
...
@@ -123,16 +125,48 @@ class Topology(object):
"""Iterate over all bonds (each represented as a tuple of two Atoms) in the Topology."""
"""Iterate over all bonds (each represented as a tuple of two Atoms) in the Topology."""
return
iter
(
self
.
_bonds
)
return
iter
(
self
.
_bonds
)
def
getPeriodicBoxVectors
(
self
):
"""Get the vectors defining the periodic box.
The return value may be None if this Topology does not represent a periodic structure."""
return
self
.
_periodicBoxVectors
def
setPeriodicBoxVectors
(
self
,
vectors
):
"""Set the vectors defining the periodic box."""
if
vectors
is
not
None
:
if
not
is_quantity
(
vectors
[
0
][
0
]):
vectors
=
vectors
*
nanometers
if
vectors
[
0
][
1
]
!=
0
*
nanometers
or
vectors
[
0
][
2
]
!=
0
*
nanometers
:
raise
ValueError
(
"First periodic box vector must be parallel to x."
);
if
vectors
[
1
][
2
]
!=
0
*
nanometers
:
raise
ValueError
(
"Second periodic box vector must be in the x-y plane."
);
if
vectors
[
0
][
0
]
<=
0
*
nanometers
or
vectors
[
1
][
1
]
<=
0
*
nanometers
or
vectors
[
2
][
2
]
<=
0
*
nanometers
or
vectors
[
0
][
0
]
<
2
*
abs
(
vectors
[
1
][
0
])
or
vectors
[
0
][
0
]
<
2
*
abs
(
vectors
[
2
][
0
])
or
vectors
[
1
][
1
]
<
2
*
abs
(
vectors
[
2
][
1
]):
raise
ValueError
(
"Periodic box vectors must be in reduced form."
);
self
.
_periodicBoxVectors
=
deepcopy
(
vectors
)
def
getUnitCellDimensions
(
self
):
def
getUnitCellDimensions
(
self
):
"""Get the dimensions of the crystallographic unit cell.
"""Get the dimensions of the crystallographic unit cell.
The return value may be None if this Topology does not represent a periodic structure.
The return value may be None if this Topology does not represent a periodic structure.
"""
"""
return
self
.
_unitCellDimensions
if
self
.
_periodicBoxVectors
is
None
:
return
None
xsize
=
self
.
_periodicBoxVectors
[
0
][
0
].
value_in_unit
(
nanometers
)
ysize
=
self
.
_periodicBoxVectors
[
1
][
1
].
value_in_unit
(
nanometers
)
zsize
=
self
.
_periodicBoxVectors
[
2
][
2
].
value_in_unit
(
nanometers
)
return
Vec3
(
xsize
,
ysize
,
zsize
)
*
nanometers
def
setUnitCellDimensions
(
self
,
dimensions
):
def
setUnitCellDimensions
(
self
,
dimensions
):
"""Set the dimensions of the crystallographic unit cell."""
"""Set the dimensions of the crystallographic unit cell.
self
.
_unitCellDimensions
=
dimensions
This method is an alternative to setPeriodicBoxVectors() for the case of a rectangular box. It sets
the box vectors to be orthogonal to each other and to have the specified lengths."""
if
dimensions
is
None
:
self
.
_periodicBoxVectors
=
None
else
:
if
is_quantity
(
dimensions
):
dimensions
=
dimensions
.
value_in_unit
(
nanometers
)
self
.
_periodicBoxVectors
=
(
Vec3
(
dimensions
[
0
],
0
,
0
),
Vec3
(
0
,
dimensions
[
1
],
0
),
Vec3
(
0
,
0
,
dimensions
[
2
]))
*
nanometers
@
staticmethod
@
staticmethod
def
loadBondDefinitions
(
file
):
def
loadBondDefinitions
(
file
):
...
...
wrappers/python/tests/TestForceField.py
View file @
4e62a24f
...
@@ -20,7 +20,7 @@ class TestForceField(unittest.TestCase):
...
@@ -20,7 +20,7 @@ class TestForceField(unittest.TestCase):
self
.
topology1
=
self
.
pdb1
.
topology
self
.
topology1
=
self
.
pdb1
.
topology
self
.
topology1
.
setUnitCellDimensions
(
Vec3
(
2
,
2
,
2
))
self
.
topology1
.
setUnitCellDimensions
(
Vec3
(
2
,
2
,
2
))
# ala
l
nine dipeptide with implicit water
# alanine dipeptide with implicit water
self
.
pdb2
=
PDBFile
(
'systems/alanine-dipeptide-implicit.pdb'
)
self
.
pdb2
=
PDBFile
(
'systems/alanine-dipeptide-implicit.pdb'
)
self
.
forcefield2
=
ForceField
(
'amber99sb.xml'
,
'amber99_obc.xml'
)
self
.
forcefield2
=
ForceField
(
'amber99sb.xml'
,
'amber99_obc.xml'
)
...
@@ -186,6 +186,18 @@ class TestForceField(unittest.TestCase):
...
@@ -186,6 +186,18 @@ class TestForceField(unittest.TestCase):
system2
=
ff2
.
createSystem
(
modeller
.
topology
)
system2
=
ff2
.
createSystem
(
modeller
.
topology
)
self
.
assertEqual
(
XmlSerializer
.
serialize
(
system1
),
XmlSerializer
.
serialize
(
system2
))
self
.
assertEqual
(
XmlSerializer
.
serialize
(
system1
),
XmlSerializer
.
serialize
(
system2
))
def
test_PeriodicBoxVectors
(
self
):
"""Test setting the periodic box vectors."""
vectors
=
(
Vec3
(
5
,
0
,
0
),
Vec3
(
-
1.5
,
4.5
,
0
),
Vec3
(
0.4
,
0.8
,
7.5
))
*
nanometers
self
.
pdb1
.
topology
.
setPeriodicBoxVectors
(
vectors
)
self
.
assertEqual
(
Vec3
(
5
,
4.5
,
7.5
)
*
nanometers
,
self
.
pdb1
.
topology
.
getUnitCellDimensions
())
system
=
self
.
forcefield1
.
createSystem
(
self
.
pdb1
.
topology
)
for
i
in
range
(
3
):
self
.
assertEqual
(
vectors
[
i
],
self
.
pdb1
.
topology
.
getPeriodicBoxVectors
()[
i
])
self
.
assertEqual
(
vectors
[
i
],
system
.
getDefaultPeriodicBoxVectors
()[
i
])
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."""
...
...
wrappers/python/tests/TestGromacsGroFile.py
0 → 100644
View file @
4e62a24f
import
unittest
from
simtk.openmm.app
import
*
from
simtk.openmm
import
*
from
simtk.unit
import
*
import
simtk.openmm.app.element
as
elem
class
TestGromacsGroFile
(
unittest
.
TestCase
):
"""Test the Gromacs GRO file parser"""
def
test_Triclinic
(
self
):
"""Test parsing a file that describes a triclinic box."""
gro
=
GromacsGroFile
(
'systems/triclinic.gro'
)
self
.
assertEqual
(
len
(
gro
.
positions
),
8
)
expectedPositions
=
[
Vec3
(
1.744
,
2.788
,
3.162
),
Vec3
(
1.048
,
0.762
,
2.340
),
Vec3
(
2.489
,
1.570
,
2.817
),
Vec3
(
1.027
,
1.893
,
3.271
),
Vec3
(
0.937
,
0.825
,
0.009
),
Vec3
(
2.290
,
1.887
,
3.352
),
Vec3
(
1.266
,
1.111
,
2.894
),
Vec3
(
0.933
,
1.862
,
3.490
)]
*
nanometers
for
(
p1
,
p2
)
in
zip
(
expectedPositions
,
gro
.
positions
):
self
.
assertEqual
(
p1
,
p2
)
expectedVectors
=
[
Vec3
(
2.5
,
0
,
0
),
Vec3
(
0.5
,
3.0
,
0
),
Vec3
(
0.7
,
0.9
,
3.5
)]
*
nanometers
for
(
v1
,
v2
)
in
zip
(
expectedVectors
,
gro
.
getPeriodicBoxVectors
()):
self
.
assertEqual
(
v1
,
v2
)
self
.
assertEqual
(
Vec3
(
2.5
,
3.0
,
3.5
)
*
nanometers
,
gro
.
getUnitCellDimensions
())
for
i
in
range
(
4
):
self
.
assertEqual
(
elem
.
chlorine
,
gro
.
elements
[
i
])
self
.
assertEqual
(
'Cl'
,
gro
.
atomNames
[
i
])
self
.
assertEqual
(
'Cl'
,
gro
.
residueNames
[
i
])
for
i
in
range
(
4
,
8
):
self
.
assertEqual
(
elem
.
sodium
,
gro
.
elements
[
i
])
self
.
assertEqual
(
'Na'
,
gro
.
atomNames
[
i
])
self
.
assertEqual
(
'Na'
,
gro
.
residueNames
[
i
])
if
__name__
==
'__main__'
:
unittest
.
main
()
wrappers/python/tests/systems/triclinic.gro
0 → 100644
View file @
4e62a24f
Triclinic test system
8
1Cl Cl 1 1.744 2.788 3.162
2Cl Cl 2 1.048 0.762 2.340
3Cl Cl 3 2.489 1.570 2.817
4Cl Cl 4 1.027 1.893 3.271
5Na Na 5 0.937 0.825 0.009
6Na Na 6 2.290 1.887 3.352
7Na Na 7 1.266 1.111 2.894
8Na Na 8 0.933 1.862 3.490
2.50000 3.00000 3.50000 0.00000 0.00000 0.50000 0.00000 0.70000 0.90000
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