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
f2eb95d0
Commit
f2eb95d0
authored
Sep 02, 2014
by
peastman
Browse files
Merge pull request #603 from peastman/scripts
Added scripts for generating force field XML files
parents
5376e6f2
2781f518
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
2229 additions
and
0 deletions
+2229
-0
devtools/forcefield-scripts/makeAmberGB.py
devtools/forcefield-scripts/makeAmberGB.py
+66
-0
devtools/forcefield-scripts/processAmberForceField.py
devtools/forcefield-scripts/processAmberForceField.py
+414
-0
devtools/forcefield-scripts/processCharmmForceField.py
devtools/forcefield-scripts/processCharmmForceField.py
+490
-0
devtools/forcefield-scripts/processTinkerForceField.py
devtools/forcefield-scripts/processTinkerForceField.py
+1259
-0
No files found.
devtools/forcefield-scripts/makeAmberGB.py
0 → 100644
View file @
f2eb95d0
import
sys
import
xml.etree.ElementTree
as
etree
gbvalues
=
{
'CT'
:(
0.19
,
0.72
),
'CX'
:(
0.19
,
0.72
),
'CI'
:(
0.19
,
0.72
),
'C'
:(
0.1875
,
0.72
),
'CA'
:(
0.1875
,
0.72
),
'CM'
:(
0.1875
,
0.72
),
'CS'
:(
0.1875
,
0.72
),
'C4'
:(
0.1875
,
0.72
),
'CC'
:(
0.1875
,
0.72
),
'CV'
:(
0.1875
,
0.72
),
'CW'
:(
0.1875
,
0.72
),
'CR'
:(
0.1875
,
0.72
),
'CB'
:(
0.1875
,
0.72
),
'C*'
:(
0.1875
,
0.72
),
'CN'
:(
0.1875
,
0.72
),
'CK'
:(
0.1875
,
0.72
),
'CP'
:(
0.1875
,
0.72
),
'C5'
:(
0.1875
,
0.72
),
'CQ'
:(
0.1875
,
0.72
),
'N'
:(
0.1706
,
0.79
),
'NA'
:(
0.1706
,
0.79
),
'NB'
:(
0.1706
,
0.79
),
'NC'
:(
0.1706
,
0.79
),
'N*'
:(
0.1706
,
0.79
),
'N2'
:(
0.1706
,
0.79
),
'N3'
:(
0.1625
,
0.79
),
'OW'
:(
0.1535
,
0.85
),
'OH'
:(
0.1535
,
0.85
),
'OS'
:(
0.1535
,
0.85
),
'O'
:(
0.148
,
0.85
),
'O2'
:(
0.148
,
0.85
),
'S'
:(
0.1775
,
0.96
),
'SH'
:(
0.1775
,
0.96
),
'H'
:(
0.115
,
0.85
),
'HW'
:(
0.105
,
0.85
),
'HO'
:(
0.105
,
0.85
),
'HS'
:(
0.125
,
0.85
),
'HA'
:(
0.125
,
0.85
),
'HC'
:(
0.125
,
0.85
),
'H0'
:(
0.125
,
0.85
),
'H1'
:(
0.125
,
0.85
),
'H2'
:(
0.125
,
0.85
),
'H3'
:(
0.125
,
0.85
),
'HP'
:(
0.125
,
0.85
),
'H4'
:(
0.125
,
0.85
),
'H5'
:(
0.125
,
0.85
)}
tree
=
etree
.
parse
(
sys
.
argv
[
1
])
typeMap
=
{}
for
type
in
tree
.
getroot
().
find
(
'AtomTypes'
).
findall
(
'Type'
):
typeMap
[
type
.
attrib
[
'name'
]]
=
type
.
attrib
[
'class'
]
print
(
"<ForceField>"
)
print
(
" <GBSAOBCForce>"
)
for
atom
in
tree
.
getroot
().
find
(
'NonbondedForce'
).
findall
(
'Atom'
):
type
=
atom
.
attrib
[
'type'
]
if
type
in
typeMap
:
atomClass
=
typeMap
[
type
]
if
atomClass
in
gbvalues
:
values
=
gbvalues
[
atomClass
]
print
(
""" <Atom type="%s" charge="%s" radius="%g" scale="%g"/>"""
%
(
type
,
atom
.
attrib
[
'charge'
],
values
[
0
],
values
[
1
]))
print
(
" </GBSAOBCForce>"
)
print
(
"</ForceField>"
)
devtools/forcefield-scripts/processAmberForceField.py
0 → 100644
View file @
f2eb95d0
import
sys
import
math
import
simtk.openmm.app.element
as
element
import
simtk.unit
as
unit
elements
=
{}
for
elem
in
element
.
Element
.
_elements_by_symbol
.
values
():
num
=
elem
.
atomic_number
if
num
not
in
elements
or
elem
.
mass
<
elements
[
num
].
mass
:
elements
[
num
]
=
elem
OTHER
=
0
ATOMS
=
1
CONNECT
=
2
CONNECTIVITY
=
3
RESIDUECONNECT
=
4
section
=
OTHER
residueAtoms
=
{}
residueBonds
=
{}
residueConnections
=
{}
types
=
[]
masses
=
{}
resAtomTypes
=
{}
vdwEquivalents
=
{}
vdw
=
{}
charge
=
{}
bonds
=
[]
angles
=
[]
torsions
=
[]
impropers
=
[]
charge14scale
=
1.0
/
1.2
epsilon14scale
=
0.5
skipResidues
=
[
'CIO'
,
'IB'
]
# "Generic" ions defined by Amber, which are identical to other real ions
skipClasses
=
[
'OW'
,
'HW'
]
# Skip water atoms, since we define these in separate files
def
addAtom
(
residue
,
atomName
,
atomClass
,
element
,
charge
):
if
residue
is
None
:
return
residueAtoms
[
residue
].
append
([
atomName
,
len
(
types
)])
types
.
append
((
atomClass
,
element
,
charge
))
def
addBond
(
residue
,
atom1
,
atom2
):
if
residue
is
None
:
return
residueBonds
[
residue
].
append
((
atom1
,
atom2
))
def
addExternalBond
(
residue
,
atom
):
if
residue
is
None
:
return
if
atom
!=
-
1
:
residueConnections
[
residue
]
+=
[
atom
]
# Load input files.
for
inputfile
in
sys
.
argv
[
1
:]:
if
inputfile
.
endswith
(
'.lib'
)
or
inputfile
.
endswith
(
'.off'
):
# Read a library file
for
line
in
open
(
inputfile
):
if
line
.
startswith
(
'!entry'
):
fields
=
line
.
split
(
'.'
)
residue
=
fields
[
1
]
if
residue
in
skipResidues
:
residue
=
None
continue
key
=
fields
[
3
].
split
()[
0
]
if
key
==
'atoms'
:
section
=
ATOMS
residueAtoms
[
residue
]
=
[]
residueBonds
[
residue
]
=
[]
residueConnections
[
residue
]
=
[]
elif
key
==
'connect'
:
section
=
CONNECT
elif
key
==
'connectivity'
:
section
=
CONNECTIVITY
elif
key
==
'residueconnect'
:
section
=
RESIDUECONNECT
else
:
section
=
OTHER
elif
section
==
ATOMS
:
fields
=
line
.
split
()
atomName
=
fields
[
0
][
1
:
-
1
]
atomClass
=
fields
[
1
][
1
:
-
1
]
if
fields
[
6
]
==
'-1'
:
# Workaround for bug in some Amber files.
if
atomClass
[
0
]
==
'C'
:
elem
=
elements
[
6
]
elif
atomClass
[
0
]
==
'H'
:
elem
=
elements
[
1
]
else
:
raise
ValueError
(
'Illegal atomic number: '
+
line
)
else
:
elem
=
elements
[
int
(
fields
[
6
])]
charge
=
float
(
fields
[
7
])
addAtom
(
residue
,
atomName
,
atomClass
,
elem
,
charge
)
elif
section
==
CONNECT
:
addExternalBond
(
residue
,
int
(
line
)
-
1
)
elif
section
==
CONNECTIVITY
:
fields
=
line
.
split
()
addBond
(
residue
,
int
(
fields
[
0
])
-
1
,
int
(
fields
[
1
])
-
1
)
elif
section
==
RESIDUECONNECT
:
# Some Amber files have errors in them, incorrectly listing atoms that should not be
# connected in the first two positions. We therefore rely on the "connect" section for
# those, using this block only for other external connections.
for
atom
in
[
int
(
x
)
-
1
for
x
in
line
.
split
()[
2
:]]:
addExternalBond
(
residue
,
atom
)
elif
inputfile
.
endswith
(
'.in'
):
lines
=
open
(
inputfile
).
read
().
split
(
'
\n
'
)
i
=
2
while
True
:
if
lines
[
i
].
strip
()
==
'STOP'
:
break
i
+=
1
residue
=
lines
[
i
].
strip
()
# Hack to get unique residue names, since different files use the same names.
if
inputfile
.
endswith
(
'nt.in'
):
residue
=
'N'
+
residue
if
inputfile
.
endswith
(
'ct.in'
):
residue
=
'C'
+
residue
residueAtoms
[
residue
]
=
[]
residueBonds
[
residue
]
=
[]
residueConnections
[
residue
]
=
[]
atoms
=
[]
mainchain
=
[]
i
+=
7
while
len
(
lines
[
i
].
rstrip
())
>
0
:
fields
=
lines
[
i
].
split
()
atoms
.
append
((
fields
[
1
],
fields
[
2
],
float
(
fields
[
10
])))
# (name, type, charge)
if
fields
[
3
]
==
'M'
:
mainchain
.
append
(
len
(
atoms
)
-
1
)
bondedTo
=
int
(
fields
[
4
])
-
4
if
bondedTo
>=
0
:
addBond
(
residue
,
len
(
atoms
)
-
1
,
bondedTo
)
i
+=
1
while
True
:
if
lines
[
i
].
strip
()
==
'LOOP'
:
i
+=
1
while
len
(
lines
[
i
].
rstrip
())
>
0
:
fields
=
lines
[
i
].
strip
().
split
()
bondFrom
=
[
j
for
j
in
range
(
len
(
atoms
))
if
fields
[
0
]
==
atoms
[
j
][
0
]][
0
]
bondTo
=
[
j
for
j
in
range
(
len
(
atoms
))
if
fields
[
1
]
==
atoms
[
j
][
0
]][
0
]
addBond
(
residue
,
bondFrom
,
bondTo
)
i
+=
1
if
lines
[
i
].
strip
()
!=
'DONE'
:
i
+=
1
continue
for
atom
in
atoms
:
try
:
el
=
element
.
Element
.
getBySymbol
(
atom
[
1
][
0
])
except
:
el
=
None
addAtom
(
residue
,
atom
[
0
],
atom
[
1
],
el
,
atom
[
2
])
# Hack for figuring out external bonds. We'll have to fix up disulfide bonds and capping groups manually.
if
len
(
mainchain
)
>
0
and
not
inputfile
.
endswith
(
'nt.in'
):
addExternalBond
(
residue
,
mainchain
[
0
])
if
len
(
mainchain
)
>
1
and
not
inputfile
.
endswith
(
'ct.in'
):
addExternalBond
(
residue
,
mainchain
[
-
1
])
i
+=
1
break
elif
inputfile
.
endswith
(
'.dat'
):
# Read a force field file.
block
=
0
continueTorsion
=
False
for
line
in
open
(
inputfile
):
line
=
line
.
strip
()
if
block
==
0
:
# Title
block
+=
1
elif
block
==
1
:
# Mass
fields
=
line
.
split
()
if
len
(
fields
)
==
0
:
block
+=
1
else
:
masses
[
fields
[
0
]]
=
float
(
fields
[
1
])
elif
block
==
2
:
# Hydrophilic atoms
block
+=
1
elif
block
==
3
:
# Bonds
if
len
(
line
)
==
0
:
block
+=
1
elif
'-'
in
line
:
fields
=
line
[
5
:].
split
()
bonds
.
append
((
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
fields
[
0
],
fields
[
1
]))
elif
block
==
4
:
# Angles
if
len
(
line
)
==
0
:
block
+=
1
else
:
fields
=
line
[
8
:].
split
()
angles
.
append
((
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
line
[
6
:
8
].
strip
(),
fields
[
0
],
fields
[
1
]))
elif
block
==
5
:
# Torsions
if
len
(
line
)
==
0
:
block
+=
1
else
:
fields
=
line
[
11
:].
split
()
periodicity
=
int
(
float
(
fields
[
3
]))
if
continueTorsion
:
torsions
[
-
1
]
+=
[
float
(
fields
[
1
])
/
float
(
fields
[
0
]),
fields
[
2
],
abs
(
periodicity
)]
else
:
torsions
.
append
([
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
line
[
6
:
8
].
strip
(),
line
[
9
:
11
].
strip
(),
float
(
fields
[
1
])
/
float
(
fields
[
0
]),
fields
[
2
],
abs
(
periodicity
)])
continueTorsion
=
(
periodicity
<
0
)
elif
block
==
6
:
# Improper torsions
if
len
(
line
)
==
0
:
block
+=
1
else
:
fields
=
line
[
11
:].
split
()
impropers
.
append
((
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
line
[
6
:
8
].
strip
(),
line
[
9
:
11
].
strip
(),
fields
[
0
],
fields
[
1
],
fields
[
2
]))
elif
block
==
7
:
# 10-12 hbond potential
if
len
(
line
)
==
0
:
block
+=
1
elif
block
==
8
:
# VDW equivalents
if
len
(
line
)
==
0
:
block
+=
1
else
:
fields
=
line
.
split
()
for
atom
in
fields
[
1
:]:
vdwEquivalents
[
atom
]
=
fields
[
0
]
elif
block
==
9
:
# VDW type
block
+=
1
vdwType
=
line
.
split
()[
1
]
if
vdwType
not
in
[
'RE'
,
'AC'
]:
raise
ValueError
(
'Nonbonded type (KINDNB) must be RE or AC'
)
elif
block
==
10
:
# VDW parameters
if
len
(
line
)
==
0
:
block
+=
1
else
:
fields
=
line
.
split
()
vdw
[
fields
[
0
]]
=
(
fields
[
1
],
fields
[
2
])
else
:
# Assume it's a frcmod file.
block
=
''
continueTorsion
=
False
first
=
True
for
line
in
open
(
inputfile
):
line
=
line
.
strip
()
if
len
(
line
)
==
0
or
first
:
block
=
None
first
=
False
elif
block
is
None
:
block
=
line
elif
block
.
startswith
(
'MASS'
):
fields
=
line
.
split
()
masses
[
fields
[
0
]]
=
float
(
fields
[
1
])
elif
block
.
startswith
(
'BOND'
):
fields
=
line
[
5
:].
split
()
bonds
.
append
((
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
fields
[
0
],
fields
[
1
]))
elif
block
.
startswith
(
'ANGL'
):
fields
=
line
[
8
:].
split
()
angles
.
append
((
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
line
[
6
:
8
].
strip
(),
fields
[
0
],
fields
[
1
]))
elif
block
.
startswith
(
'DIHE'
):
fields
=
line
[
11
:].
split
()
periodicity
=
int
(
float
(
fields
[
3
]))
if
continueTorsion
:
torsions
[
-
1
]
+=
[
float
(
fields
[
1
])
/
float
(
fields
[
0
]),
fields
[
2
],
abs
(
periodicity
)]
else
:
torsions
.
append
([
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
line
[
6
:
8
].
strip
(),
line
[
9
:
11
].
strip
(),
float
(
fields
[
1
])
/
float
(
fields
[
0
]),
fields
[
2
],
abs
(
periodicity
)])
continueTorsion
=
(
periodicity
<
0
)
elif
block
.
startswith
(
'IMPR'
):
fields
=
line
[
11
:].
split
()
impropers
.
append
((
line
[:
2
].
strip
(),
line
[
3
:
5
].
strip
(),
line
[
6
:
8
].
strip
(),
line
[
9
:
11
].
strip
(),
fields
[
0
],
fields
[
1
],
fields
[
2
]))
elif
block
.
startswith
(
'NONB'
):
fields
=
line
.
split
()
vdw
[
fields
[
0
]]
=
(
fields
[
1
],
fields
[
2
])
# Reduce the list of atom types. If multiple hydrogens are bound to the same heavy atom,
# they should all use the same type.
removeType
=
[
False
]
*
len
(
types
)
for
res
in
residueAtoms
:
if
res
not
in
residueBonds
:
continue
atomBonds
=
[[]
for
atom
in
residueAtoms
[
res
]]
for
bond
in
residueBonds
[
res
]:
atomBonds
[
bond
[
0
]].
append
(
bond
[
1
])
atomBonds
[
bond
[
1
]].
append
(
bond
[
0
])
for
index
,
atom
in
enumerate
(
residueAtoms
[
res
]):
hydrogens
=
[
x
for
x
in
atomBonds
[
index
]
if
types
[
residueAtoms
[
res
][
x
][
1
]][
1
]
==
element
.
hydrogen
]
for
h
in
hydrogens
[
1
:]:
removeType
[
residueAtoms
[
res
][
h
][
1
]]
=
True
residueAtoms
[
res
][
h
][
1
]
=
residueAtoms
[
res
][
hydrogens
[
0
]][
1
]
newTypes
=
[]
replaceWithType
=
[
0
]
*
len
(
types
)
for
i
in
range
(
len
(
types
)):
if
not
removeType
[
i
]:
newTypes
.
append
(
types
[
i
])
replaceWithType
[
i
]
=
len
(
newTypes
)
-
1
types
=
newTypes
for
res
in
residueAtoms
:
for
atom
in
residueAtoms
[
res
]:
atom
[
1
]
=
replaceWithType
[
atom
[
1
]]
# Create the XML output.
def
fix
(
atomClass
):
if
atomClass
==
'X'
:
return
''
return
atomClass
print
"<ForceField>"
print
" <AtomTypes>"
for
index
,
type
in
enumerate
(
types
):
if
type
[
1
]
is
None
:
el
=
""
mass
=
0
else
:
el
=
type
[
1
].
symbol
mass
=
type
[
1
].
mass
.
value_in_unit
(
unit
.
amu
)
print
""" <Type name="%d" class="%s" element="%s" mass="%s"/>"""
%
(
index
,
type
[
0
],
el
,
mass
)
print
" </AtomTypes>"
print
" <Residues>"
for
res
in
sorted
(
residueAtoms
):
print
""" <Residue name="%s">"""
%
res
for
atom
in
residueAtoms
[
res
]:
print
" <Atom name=
\"
%s
\"
type=
\"
%d
\"
/>"
%
tuple
(
atom
)
if
res
in
residueBonds
:
for
bond
in
residueBonds
[
res
]:
print
""" <Bond from="%d" to="%d"/>"""
%
bond
if
res
in
residueConnections
:
for
bond
in
residueConnections
[
res
]:
print
""" <ExternalBond from="%d"/>"""
%
bond
print
" </Residue>"
print
" </Residues>"
print
" <HarmonicBondForce>"
processed
=
set
()
for
bond
in
bonds
:
signature
=
(
bond
[
0
],
bond
[
1
])
if
signature
in
processed
:
continue
if
any
([
c
in
skipClasses
for
c
in
signature
]):
continue
processed
.
add
(
signature
)
length
=
float
(
bond
[
3
])
*
0.1
k
=
float
(
bond
[
2
])
*
2
*
100
*
4.184
print
""" <Bond class1="%s" class2="%s" length="%s" k="%s"/>"""
%
(
bond
[
0
],
bond
[
1
],
str
(
length
),
str
(
k
))
print
" </HarmonicBondForce>"
print
" <HarmonicAngleForce>"
processed
=
set
()
for
angle
in
angles
:
signature
=
(
angle
[
0
],
angle
[
1
],
angle
[
2
])
if
signature
in
processed
:
continue
if
any
([
c
in
skipClasses
for
c
in
signature
]):
continue
processed
.
add
(
signature
)
theta
=
float
(
angle
[
4
])
*
math
.
pi
/
180.0
k
=
float
(
angle
[
3
])
*
2
*
4.184
print
""" <Angle class1="%s" class2="%s" class3="%s" angle="%s" k="%s"/>"""
%
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
str
(
theta
),
str
(
k
))
print
" </HarmonicAngleForce>"
print
" <PeriodicTorsionForce>"
processed
=
set
()
for
tor
in
reversed
(
torsions
):
signature
=
(
fix
(
tor
[
0
]),
fix
(
tor
[
1
]),
fix
(
tor
[
2
]),
fix
(
tor
[
3
]))
if
signature
in
processed
:
continue
if
any
([
c
in
skipClasses
for
c
in
signature
]):
continue
processed
.
add
(
signature
)
tag
=
" <Proper class1=
\"
%s
\"
class2=
\"
%s
\"
class3=
\"
%s
\"
class4=
\"
%s
\"
"
%
signature
i
=
4
while
i
<
len
(
tor
):
index
=
i
/
3
periodicity
=
int
(
float
(
tor
[
i
+
2
]))
phase
=
float
(
tor
[
i
+
1
])
*
math
.
pi
/
180.0
k
=
tor
[
i
]
*
4.184
tag
+=
" periodicity%d=
\"
%d
\"
phase%d=
\"
%s
\"
k%d=
\"
%s
\"
"
%
(
index
,
periodicity
,
index
,
str
(
phase
),
index
,
str
(
k
))
i
+=
3
tag
+=
"/>"
print
tag
processed
=
set
()
for
tor
in
reversed
(
impropers
):
signature
=
(
fix
(
tor
[
2
]),
fix
(
tor
[
0
]),
fix
(
tor
[
1
]),
fix
(
tor
[
3
]))
if
signature
in
processed
:
continue
if
any
([
c
in
skipClasses
for
c
in
signature
]):
continue
processed
.
add
(
signature
)
tag
=
" <Improper class1=
\"
%s
\"
class2=
\"
%s
\"
class3=
\"
%s
\"
class4=
\"
%s
\"
"
%
signature
i
=
4
while
i
<
len
(
tor
):
index
=
i
/
3
periodicity
=
int
(
float
(
tor
[
i
+
2
]))
phase
=
float
(
tor
[
i
+
1
])
*
math
.
pi
/
180.0
k
=
float
(
tor
[
i
])
*
4.184
tag
+=
" periodicity%d=
\"
%d
\"
phase%d=
\"
%s
\"
k%d=
\"
%s
\"
"
%
(
index
,
periodicity
,
index
,
str
(
phase
),
index
,
str
(
k
))
i
+=
3
tag
+=
"/>"
print
tag
print
" </PeriodicTorsionForce>"
print
""" <NonbondedForce coulomb14scale="%g" lj14scale="%s">"""
%
(
charge14scale
,
epsilon14scale
)
sigmaScale
=
0.1
*
2.0
/
(
2.0
**
(
1.0
/
6.0
))
for
index
,
type
in
enumerate
(
types
):
atomClass
=
type
[
0
]
q
=
type
[
2
]
if
atomClass
in
vdwEquivalents
:
atomClass
=
vdwEquivalents
[
atomClass
]
if
atomClass
in
vdw
:
params
=
[
float
(
x
)
for
x
in
vdw
[
atomClass
]]
if
vdwType
==
'RE'
:
sigma
=
params
[
0
]
*
sigmaScale
epsilon
=
params
[
1
]
*
4.184
else
:
sigma
=
(
params
[
0
]
/
params
[
1
])
**
(
1.0
/
6.0
)
epsilon
=
4.184
*
params
[
1
]
*
params
[
1
]
/
(
4
*
params
[
0
])
else
:
sigma
=
0
epsilon
=
0
if
q
!=
0
or
epsilon
!=
0
:
print
""" <Atom type="%d" charge="%s" sigma="%s" epsilon="%s"/>"""
%
(
index
,
q
,
sigma
,
epsilon
)
print
" </NonbondedForce>"
print
"</ForceField>"
devtools/forcefield-scripts/processCharmmForceField.py
0 → 100644
View file @
f2eb95d0
from
__future__
import
print_function
import
sys
import
math
import
copy
from
simtk.unit
import
*
section
=
None
atomTypes
=
[]
atomClasses
=
{}
residue
=
None
residues
=
[]
patches
=
{}
category
=
None
bonds
=
[]
angles
=
[]
ubs
=
[]
dihedrals
=
{}
impropers
=
[]
cmaps
=
[]
cmap
=
None
nonbondeds
=
{}
nbfixes
=
{}
def
getFieldPairs
(
fields
):
pairs
=
[]
for
i
in
range
(
len
(
fields
)
/
2
):
pairs
.
append
((
fields
[
2
*
i
],
fields
[
2
*
i
+
1
]))
return
pairs
class
Residue
(
object
):
def
__init__
(
self
,
name
):
self
.
name
=
name
self
.
atoms
=
[]
self
.
atomMap
=
{}
self
.
deletions
=
[]
self
.
bonds
=
[]
self
.
externalBonds
=
[
'N'
,
'C'
]
if
name
==
'GLY'
:
self
.
patches
=
[
'NTER'
,
'CTEG'
]
elif
name
==
'PRO'
:
self
.
patches
=
[
'NTER'
,
'CTEP'
]
else
:
self
.
patches
=
[
'NTER'
,
'CTER'
]
self
.
lonepairs
=
[]
def
addAtom
(
self
,
atom
):
self
.
atomMap
[
atom
.
name
]
=
len
(
self
.
atoms
)
self
.
atoms
.
append
(
atom
)
def
setAtomAnisotropy
(
self
,
fields
):
atom1
=
[
a
for
a
in
self
.
atoms
if
a
.
name
==
fields
[
1
]][
0
]
atom2
=
[
a
for
a
in
self
.
atoms
if
a
.
name
==
fields
[
2
]][
0
]
atom3
=
[
a
for
a
in
self
.
atoms
if
a
.
name
==
fields
[
3
]][
0
]
atom4
=
[
a
for
a
in
self
.
atoms
if
a
.
name
==
fields
[
4
]][
0
]
for
param
,
value
in
getFieldPairs
(
fields
[
5
:]):
if
param
==
'A11'
:
a11
=
float
(
value
)
elif
param
==
'A22'
:
a22
=
float
(
value
)
atom1
.
anisotropic
=
True
atom1
.
anisotropy
=
(
atom2
.
type
,
atom3
.
type
,
atom4
.
type
,
a11
,
a22
)
def
createPatchedResidue
(
residue
,
patch
):
r
=
Residue
(
patch
.
name
+
'-'
+
residue
.
name
)
for
atom
in
patch
.
atoms
:
r
.
addAtom
(
atom
)
atomNames
=
set
(
atom
.
name
for
atom
in
r
.
atoms
)
for
atom
in
residue
.
atoms
:
if
atom
.
name
not
in
patch
.
deletions
:
if
atom
.
name
not
in
atomNames
:
r
.
addAtom
(
atom
)
atomNames
.
add
(
atom
.
name
)
else
:
# We're using the version from the patch, but we still need to take anisotropy information from the original residue.
for
i
in
range
(
len
(
r
.
atoms
)):
if
r
.
atoms
[
i
].
name
==
atom
.
name
:
newAtom
=
copy
.
deepcopy
(
r
.
atoms
[
i
])
newAtom
.
anisotropic
=
atom
.
anisotropic
if
atom
.
anisotropic
:
name2
=
[
a
for
a
in
residue
.
atoms
if
a
.
type
==
atom
.
anisotropy
[
0
]][
0
].
name
name3
=
[
a
for
a
in
residue
.
atoms
if
a
.
type
==
atom
.
anisotropy
[
1
]][
0
].
name
name4
=
[
a
for
a
in
residue
.
atoms
if
a
.
type
==
atom
.
anisotropy
[
2
]][
0
].
name
atom2
=
[
a
for
a
in
r
.
atoms
if
a
.
name
==
name2
][
0
]
atom3
=
[
a
for
a
in
r
.
atoms
if
a
.
name
==
name3
][
0
]
atom4
=
[
a
for
a
in
r
.
atoms
if
a
.
name
==
name4
][
0
]
newAtom
.
anisotropy
=
(
atom2
.
type
,
atom3
.
type
,
atom4
.
type
,
atom
.
anisotropy
[
3
],
atom
.
anisotropy
[
4
])
r
.
atoms
[
i
]
=
newAtom
for
bond
in
residue
.
bonds
:
if
all
(
atom
in
atomNames
for
atom
in
bond
):
r
.
bonds
.
append
(
bond
)
for
bond
in
patch
.
bonds
:
r
.
bonds
.
append
(
bond
)
for
lp
in
residue
.
lonepairs
:
if
all
(
atom
in
atomNames
for
atom
in
lp
[:
4
]):
r
.
lonepairs
.
append
(
lp
)
for
lp
in
patch
.
lonepairs
:
r
.
lonepairs
.
append
(
lp
)
return
r
class
Atom
(
object
):
def
__init__
(
self
,
fields
):
self
.
name
=
fields
[
1
]
self
.
atomClass
=
fields
[
2
]
self
.
charge
=
float
(
fields
[
3
])
self
.
polarizable
=
False
self
.
anisotropic
=
False
for
param
,
value
in
getFieldPairs
(
fields
[
4
:]):
if
param
==
'ALPHA'
:
self
.
polarizable
=
True
self
.
alpha
=
float
(
value
)
*
angstrom
**
3
/
(
138.935456
*
kilojoules_per_mole
*
nanometer
)
elif
param
==
'THOLE'
:
self
.
thole
=
float
(
value
)
elif
param
==
'TYPE'
:
self
.
drudeType
=
value
if
'drudeType'
not
in
dir
(
self
):
self
.
drudeType
=
'DRUD'
if
self
.
polarizable
:
sign
=
1
if
self
.
alpha
<
0
*
nanometers
**
2
/
kilojoules_per_mole
:
self
.
alpha
=
-
self
.
alpha
sign
=
-
1
self
.
drudeCharge
=
sign
*
math
.
sqrt
(
self
.
alpha
*
2
*
(
500
*
kilocalories_per_mole
/
angstrom
**
2
))
self
.
charge
-=
self
.
drudeCharge
if
'thole'
not
in
dir
(
self
):
self
.
thole
=
1.3
self
.
type
=
len
(
atomTypes
)
atomTypes
.
append
(
self
)
class
Cmap
(
object
):
def
__init__
(
self
,
fields
):
if
fields
[
1
]
!=
fields
[
4
]
or
fields
[
2
]
!=
fields
[
5
]
or
fields
[
3
]
!=
fields
[
6
]:
raise
ValueError
(
'Invalid CMAP atoms: '
+
(
' '
.
join
(
fields
[:
8
])))
self
.
classes
=
[
fields
[
0
],
fields
[
1
],
fields
[
2
],
fields
[
3
],
fields
[
7
]]
self
.
size
=
int
(
fields
[
8
])
self
.
values
=
[]
class
Nonbonded
(
object
):
def
__init__
(
self
,
fields
):
self
.
atomClass
=
fields
[
0
]
values
=
[
float
(
x
)
for
x
in
fields
[
1
:]]
if
values
[
1
]
>
0
or
(
len
(
values
)
>
3
and
values
[
4
]
>
0
):
raise
ValueError
(
'Unsupported nonbonded type'
)
self
.
epsilon
=
-
values
[
1
]
*
kilocalories_per_mole
self
.
sigma
=
values
[
2
]
*
angstroms
if
len
(
values
)
>
3
:
self
.
epsilon14
=
-
values
[
4
]
*
kilocalories_per_mole
self
.
sigma14
=
values
[
5
]
*
angstroms
else
:
self
.
epsilon14
=
self
.
epsilon
self
.
sigma14
=
self
.
sigma
def
getLennardJonesParams
(
class1
,
class2
,
is14
):
nbfixParams
=
None
if
(
class1
,
class2
)
in
nbfixes
:
nbfixParams
=
nbfixes
[(
class1
,
class2
)]
elif
(
class2
,
class1
)
in
nbfixes
:
nbfixParams
=
nbfixes
[(
class2
,
class1
)]
if
nbfixParams
is
not
None
:
if
is14
and
len
(
nbfixParams
)
>
2
:
return
nbfixParams
[
2
:
3
]
return
nbfixParams
if
class1
not
in
nonbondeds
or
class2
not
in
nonbondeds
:
# Probably a Drude particle
return
(
0
*
kilojoules_per_mole
,
1
*
nanometers
)
params1
=
nonbondeds
[
class1
]
params2
=
nonbondeds
[
class2
]
if
is14
:
return
(
sqrt
(
params1
.
epsilon14
*
params2
.
epsilon14
),
params1
.
sigma14
+
params2
.
sigma14
)
return
(
sqrt
(
params1
.
epsilon
*
params2
.
epsilon
),
params1
.
sigma
+
params2
.
sigma
)
continuedLine
=
None
for
inputfile
in
sys
.
argv
[
1
:]:
for
line
in
open
(
inputfile
):
if
continuedLine
is
not
None
:
line
=
continuedLine
+
' '
+
line
continuedLine
=
None
if
line
.
find
(
'!'
)
>
-
1
:
line
=
line
[:
line
.
find
(
'!'
)]
line
=
line
.
strip
()
if
line
.
endswith
(
'-'
):
continuedLine
=
line
[:
-
1
]
continue
fields
=
line
.
split
()
if
len
(
fields
)
==
0
:
continue
if
line
==
'read rtf card'
:
section
=
'rtf'
elif
line
==
'read para card'
:
section
=
'para'
elif
line
==
'end'
:
section
=
None
elif
section
==
'rtf'
:
if
fields
[
0
]
==
'MASS'
:
atomClasses
[
fields
[
2
]]
=
(
float
(
fields
[
3
]),
fields
[
4
])
elif
fields
[
0
]
==
'RESI'
:
residue
=
Residue
(
fields
[
1
])
residues
.
append
(
residue
)
elif
fields
[
0
]
==
'PRES'
:
residue
=
Residue
(
fields
[
1
])
patches
[
residue
.
name
]
=
residue
elif
fields
[
0
]
==
'ATOM'
:
residue
.
addAtom
(
Atom
(
fields
))
elif
fields
[
0
].
startswith
(
'DELE'
)
and
fields
[
1
]
==
'ATOM'
:
residue
.
deletions
.
append
(
fields
[
2
])
elif
fields
[
0
]
==
'BOND'
:
for
name1
,
name2
in
getFieldPairs
(
fields
[
1
:]):
residue
.
bonds
.
append
((
name1
,
name2
))
elif
fields
[
0
].
startswith
(
'PATC'
):
for
pos
,
name
in
getFieldPairs
(
fields
[
1
:]):
if
pos
.
startswith
(
'FIRS'
):
residue
.
patches
[
0
]
=
name
elif
pos
==
'LAST'
:
residue
.
patches
[
1
]
=
name
elif
fields
[
0
]
==
'ANISOTROPY'
:
residue
.
setAtomAnisotropy
(
fields
)
elif
fields
[
0
]
==
'LONEPAIR'
:
params
=
dict
(
getFieldPairs
(
fields
[
6
:]))
residue
.
lonepairs
.
append
(
fields
[
2
:
6
]
+
[
fields
[
1
],
float
(
params
[
'distance'
])
*
angstrom
,
float
(
params
[
'angle'
])
*
degrees
,
float
(
params
[
'dihe'
])
*
degrees
])
elif
section
==
'para'
:
if
fields
[
0
]
in
(
'BONDS'
,
'ANGLES'
,
'DIHEDRALS'
,
'IMPROPER'
,
'CMAP'
,
'NONBONDED'
,
'NBFIX'
,
'THOLE'
):
category
=
fields
[
0
]
residue
=
None
elif
category
==
'BONDS'
:
bonds
.
append
((
fields
[
0
],
fields
[
1
],
2
*
float
(
fields
[
2
])
*
kilocalories_per_mole
/
angstrom
**
2
,
float
(
fields
[
3
])
*
angstroms
))
elif
category
==
'ANGLES'
:
if
len
(
fields
)
==
5
:
angles
.
append
((
fields
[
0
],
fields
[
1
],
fields
[
2
],
2
*
float
(
fields
[
3
])
*
kilocalories_per_mole
/
radian
**
2
,
float
(
fields
[
4
])
*
degrees
))
else
:
ubs
.
append
((
fields
[
0
],
fields
[
1
],
fields
[
2
],
2
*
float
(
fields
[
3
])
*
kilocalories_per_mole
/
radian
**
2
,
float
(
fields
[
4
])
*
degrees
,
2
*
float
(
fields
[
5
])
*
kilocalories_per_mole
/
angstrom
**
2
,
float
(
fields
[
6
])
*
angstroms
))
elif
category
==
'DIHEDRALS'
:
key
=
(
fields
[
0
],
fields
[
1
],
fields
[
2
],
fields
[
3
])
if
key
not
in
dihedrals
:
dihedrals
[
key
]
=
[]
dihedrals
[
key
].
append
((
float
(
fields
[
4
])
*
kilocalories_per_mole
,
int
(
fields
[
5
]),
float
(
fields
[
6
])
*
degrees
))
elif
category
==
'IMPROPER'
:
impropers
.
append
((
fields
[
0
],
fields
[
1
],
fields
[
2
],
fields
[
3
],
float
(
fields
[
4
])
*
kilocalories_per_mole
/
radian
**
2
,
float
(
fields
[
6
])
*
degrees
))
elif
category
==
'CMAP'
:
if
cmap
is
None
:
cmap
=
Cmap
(
fields
)
cmaps
.
append
(
cmap
)
else
:
cmap
.
values
+=
[
float
(
x
)
for
x
in
fields
]
if
len
(
cmap
.
values
)
>
cmap
.
size
*
cmap
.
size
:
raise
ValueError
(
'Too many values for CMAP'
)
if
len
(
cmap
.
values
)
==
cmap
.
size
*
cmap
.
size
:
cmap
=
None
elif
category
==
'NONBONDED'
:
nb
=
Nonbonded
(
fields
)
nonbondeds
[
nb
.
atomClass
]
=
nb
elif
category
==
'NBFIX'
:
nbfixes
[(
fields
[
0
],
fields
[
1
])]
=
(
-
float
(
fields
[
2
])
*
kilocalories_per_mole
,
float
(
fields
[
3
])
*
angstroms
)
# Apply patches to create terminal residues.
patchedResidues
=
[]
for
residue
in
residues
:
patchedResidues
.
append
(
residue
)
if
residue
.
patches
[
0
]
in
patches
:
patched
=
createPatchedResidue
(
residue
,
patches
[
residue
.
patches
[
0
]])
patched
.
externalBonds
[
0
]
=
''
patchedResidues
.
append
(
patched
)
if
residue
.
patches
[
1
]
in
patches
:
patched
=
createPatchedResidue
(
residue
,
patches
[
residue
.
patches
[
1
]])
patched
.
externalBonds
[
1
]
=
''
patchedResidues
.
append
(
patched
)
residues
=
patchedResidues
# Build a list of all unique maps used in CMAP terms.
uniqueCmaps
=
{}
for
cmap
in
cmaps
:
cmap
.
values
=
tuple
(
cmap
.
values
)
if
cmap
.
values
not
in
uniqueCmaps
:
uniqueCmaps
[
cmap
.
values
]
=
len
(
uniqueCmaps
)
# Create Drude particles.
drudes
=
{}
for
residue
in
residues
:
atoms2
=
residue
.
atoms
[:]
for
atom
in
residue
.
atoms
:
if
atom
.
polarizable
:
drude
=
Atom
((
''
,
'D'
+
atom
.
name
,
atom
.
drudeType
,
atom
.
drudeCharge
))
atoms2
.
append
(
drude
)
if
atom
.
anisotropic
:
aniso
=
atom
.
anisotropy
else
:
aniso
=
None
drudes
[(
drude
.
type
,
atom
.
type
)]
=
(
138.935456
*
atom
.
alpha
.
value_in_unit
(
nanometers
**
2
/
kilojoules_per_mole
),
atom
.
thole
,
atom
.
drudeCharge
,
aniso
)
residue
.
atoms
=
atoms2
# Create the XML file.
print
(
'<ForceField>'
)
print
(
' <AtomTypes>'
)
masslessTypes
=
set
()
for
type
in
atomTypes
:
(
mass
,
elem
)
=
atomClasses
[
type
.
atomClass
]
if
mass
==
0.0
:
elementSpec
=
''
masslessTypes
.
add
(
type
.
type
)
else
:
elementSpec
=
' element="%s"'
%
elem
print
(
' <Type name="%d" class="%s"%s mass="%f"/>'
%
(
type
.
type
,
type
.
atomClass
,
elementSpec
,
mass
))
print
(
' </AtomTypes>'
)
print
(
' <Residues>'
)
for
residue
in
residues
:
print
(
' <Residue name="%s">'
%
residue
.
name
)
masslessAtoms
=
set
()
for
atom
in
residue
.
atoms
:
print
(
' <Atom name="%s" type="%d"/>'
%
(
atom
.
name
,
atom
.
type
))
if
atom
.
type
in
masslessTypes
:
masslessAtoms
.
add
(
atom
.
name
)
for
name1
,
name2
in
residue
.
bonds
:
if
name1
in
residue
.
atomMap
and
name2
in
residue
.
atomMap
:
if
name1
not
in
masslessAtoms
and
name2
not
in
masslessAtoms
:
# CHARMM lists bonds for lone pairs, which we don't want
print
(
' <Bond from="%d" to="%d"/>'
%
(
residue
.
atomMap
[
name1
],
residue
.
atomMap
[
name2
]))
for
external
in
residue
.
externalBonds
:
if
external
in
residue
.
atomMap
:
print
(
' <ExternalBond from="%d"/>'
%
residue
.
atomMap
[
external
])
for
lp
in
residue
.
lonepairs
:
atoms
=
[
residue
.
atomMap
[
lp
[
0
]],
residue
.
atomMap
[
lp
[
1
]],
residue
.
atomMap
[
lp
[
3
]],
residue
.
atomMap
[
lp
[
2
]],
residue
.
atomMap
[
lp
[
1
]]]
if
lp
[
4
]
==
'relative'
:
xweights
=
[
-
1.0
,
0.0
,
1.0
]
elif
lp
[
4
]
==
'bisector'
:
xweights
=
[
-
1.0
,
0.5
,
0.5
]
else
:
raise
ValueError
(
'Unknown lonepair type: '
+
lp
[
4
])
r
=
lp
[
5
].
value_in_unit
(
nanometer
)
theta
=
lp
[
6
].
value_in_unit
(
radian
)
phi
=
(
180
*
degrees
-
lp
[
7
]).
value_in_unit
(
radian
)
p
=
[
r
*
math
.
cos
(
theta
),
r
*
math
.
sin
(
theta
)
*
math
.
cos
(
phi
),
r
*
math
.
sin
(
theta
)
*
math
.
sin
(
phi
)]
p
=
[
x
if
abs
(
x
)
>
1e-10
else
0
for
x
in
p
]
# Avoid tiny numbers caused by roundoff error
print
(
' <VirtualSite type="localCoords" index="%d" atom1="%d" atom2="%d" atom3="%d" excludeWith="%d" wo1="1" wo2="0" wo3="0" wx1="%g" wx2="%g" wx3="%g" wy1="0" wy2="-1" wy3="1" p1="%g" p2="%g" p3="%g"/>'
%
tuple
(
atoms
+
xweights
+
p
))
print
(
' </Residue>'
)
print
(
' </Residues>'
)
print
(
' <HarmonicBondForce>'
)
for
bond
in
bonds
:
print
(
' <Bond class1="%s" class2="%s" length="%g" k="%g"/>'
%
(
bond
[
0
],
bond
[
1
],
bond
[
3
].
value_in_unit
(
nanometer
),
bond
[
2
].
value_in_unit
(
kilojoules_per_mole
/
nanometer
**
2
)))
print
(
' </HarmonicBondForce>'
)
print
(
' <HarmonicAngleForce>'
)
for
angle
in
angles
:
print
(
' <Angle class1="%s" class2="%s" class3="%s" angle="%.12g" k="%g"/>'
%
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
angle
[
4
].
value_in_unit
(
radian
),
angle
[
3
].
value_in_unit
(
kilojoules_per_mole
/
radian
**
2
)))
for
angle
in
ubs
:
print
(
' <Angle class1="%s" class2="%s" class3="%s" angle="%.12g" k="%g"/>'
%
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
angle
[
4
].
value_in_unit
(
radian
),
angle
[
3
].
value_in_unit
(
kilojoules_per_mole
/
radian
**
2
)))
print
(
' </HarmonicAngleForce>'
)
print
(
' <PeriodicTorsionForce>'
)
for
dihedral
in
dihedrals
:
values
=
dihedrals
[
dihedral
]
params
=
''
for
(
i
,
(
k
,
n
,
phase
))
in
enumerate
(
values
):
params
+=
' periodicity%d="%d" phase%d="%.12g" k%d="%g"'
%
(
i
+
1
,
n
,
i
+
1
,
phase
.
value_in_unit
(
radians
),
i
+
1
,
k
.
value_in_unit
(
kilojoules_per_mole
))
print
(
' <Proper class1="%s" class2="%s" class3="%s" class4="%s"%s/>'
%
(
dihedral
[
0
],
dihedral
[
1
],
dihedral
[
2
],
dihedral
[
3
],
params
))
print
(
' </PeriodicTorsionForce>'
)
print
(
' <CustomTorsionForce energy="k*(theta-theta0)^2">'
)
print
(
' <PerTorsionParameter name="k"/>'
)
print
(
' <PerTorsionParameter name="theta0"/>'
)
for
improper
in
impropers
:
print
(
' <Improper class1="%s" class2="%s" class3="%s" class4="%s" k="%g" theta0="%.12g"/>'
%
(
improper
[
0
],
improper
[
1
],
improper
[
2
],
improper
[
3
],
improper
[
4
].
value_in_unit
(
kilojoules_per_mole
/
radian
**
2
),
improper
[
5
].
value_in_unit
(
radian
)))
print
(
' </CustomTorsionForce>'
)
print
(
' <CMAPTorsionForce>'
)
for
values
in
sorted
(
uniqueCmaps
,
key
=
lambda
x
:
uniqueCmaps
[
x
]):
print
(
' <Map>'
)
size
=
int
(
math
.
sqrt
(
len
(
values
)))
shift
=
size
/
2
scale
=
kilocalories_per_mole
.
conversion_factor_to
(
kilojoules_per_mole
)
# Convert the ordering from the one used by CHARMM to the one used by OpenMM.
reordered
=
[
0
]
*
len
(
values
)
for
i
in
range
(
size
):
i2
=
(
i
+
shift
)
%
size
for
j
in
range
(
size
):
j2
=
(
j
+
shift
)
%
size
reordered
[
j2
*
size
+
i2
]
=
scale
*
values
[
i
*
size
+
j
]
for
i
in
range
(
size
):
v
=
reordered
[
i
*
size
:(
i
+
1
)
*
size
]
print
(
' '
+
(
' '
.
join
(
'%g'
%
x
for
x
in
v
)))
print
(
' </Map>'
)
for
map
in
cmaps
:
print
(
' <Torsion map="%d" class1="%s" class2="%s" class3="%s" class4="%s" class5="%s"/>'
%
(
uniqueCmaps
[
map
.
values
],
map
.
classes
[
0
],
map
.
classes
[
1
],
map
.
classes
[
2
],
map
.
classes
[
3
],
map
.
classes
[
4
]))
print
(
' </CMAPTorsionForce>'
)
print
(
' <NonbondedForce coulomb14scale="1.0" lj14scale="1.0">'
)
for
type
in
atomTypes
:
print
(
' <Atom type="%d" charge="%g" sigma="1.0" epsilon="1.0"/>'
%
(
type
.
type
,
type
.
charge
))
print
(
' </NonbondedForce>'
)
if
len
(
drudes
)
>
0
:
print
(
' <DrudeForce>'
)
for
key
in
drudes
:
(
type1
,
type2
)
=
key
(
alpha
,
thole
,
charge
,
aniso
)
=
drudes
[
key
]
if
aniso
is
None
:
print
(
' <Particle type1="%s" type2="%s" charge="%g" polarizability="%g" thole="%g"/>'
%
(
type1
,
type2
,
charge
,
alpha
,
thole
))
else
:
print
(
' <Particle type1="%s" type2="%s" type3="%s" type4="%s" type5="%s" charge="%g" polarizability="%g" thole="%g" aniso12="%g" aniso34="%s"/>'
%
(
type1
,
type2
,
aniso
[
0
],
aniso
[
1
],
aniso
[
2
],
charge
,
alpha
,
thole
,
aniso
[
3
],
aniso
[
4
]))
print
(
' </DrudeForce>'
)
print
(
' <Script>'
)
print
(
"""import simtk.openmm as mm
harmonicBondForce = [f for f in [sys.getForce(i) for i in range(sys.getNumForces())] if type(f) == mm.HarmonicBondForce][0]
nonbondedForce = [f for f in [sys.getForce(i) for i in range(sys.getNumForces())] if type(f) == mm.NonbondedForce][0]
numAtomClasses = %d"""
%
len
(
atomClasses
))
print
(
"""
# Conversion from atom types to atom classes.
typeToClass = {"""
)
classOrder
=
dict
((
c
,
i
)
for
i
,
c
in
enumerate
(
atomClasses
))
for
type
in
atomTypes
:
print
(
" '%s':%s,"
%
(
type
.
type
,
classOrder
[
type
.
atomClass
]))
print
(
"""}
# Urey-Bradley parameters.
ubParams = {"""
)
for
angle
in
ubs
:
length
=
angle
[
6
].
value_in_unit
(
nanometer
)
k
=
angle
[
5
].
value_in_unit
(
kilojoules_per_mole
/
nanometer
**
2
)
if
k
!=
0.0
:
print
(
' (%d, %d, %d):(%g, %g),'
%
(
classOrder
[
angle
[
0
]],
classOrder
[
angle
[
1
]],
classOrder
[
angle
[
2
]],
length
,
k
))
print
(
"""}
# Add bonds for the Urey-Bradley terms.
for (angle, isConstrained) in zip(data.angles, data.isAngleConstrained):
if isConstrained:
continue
class1 = typeToClass[data.atomType[data.atoms[angle[0]]]]
class2 = typeToClass[data.atomType[data.atoms[angle[1]]]]
class3 = typeToClass[data.atomType[data.atoms[angle[2]]]]
params = None
if (class1, class2, class3) in ubParams:
params = ubParams[(class1, class2, class3)]
elif (class3, class2, class1) in ubParams:
params = ubParams[(class3, class2, class1)]
if params is not None:
harmonicBondForce.addBond(angle[0], angle[2], params[0], params[1])
# Lennard-Jones parameters by atom types.
epsilon = ["""
)
sigmaScale
=
0.5
**
(
1.0
/
6.0
)
for
class1
in
atomClasses
:
for
class2
in
atomClasses
:
print
(
'%g, '
%
getLennardJonesParams
(
class1
,
class2
,
False
)[
0
].
value_in_unit
(
kilojoules_per_mole
),
end
=
''
)
print
()
print
(
"""]
sigma = ["""
)
for
class1
in
atomClasses
:
for
class2
in
atomClasses
:
print
(
'%g, '
%
(
sigmaScale
*
getLennardJonesParams
(
class1
,
class2
,
False
)[
1
].
value_in_unit
(
nanometers
)),
end
=
''
)
print
()
print
(
"""]
epsilon14 = ["""
)
for
class1
in
atomClasses
:
for
class2
in
atomClasses
:
print
(
'%g, '
%
getLennardJonesParams
(
class1
,
class2
,
True
)[
0
].
value_in_unit
(
kilojoules_per_mole
),
end
=
''
)
print
()
print
(
"""]
sigma14 = ["""
)
for
class1
in
atomClasses
:
for
class2
in
atomClasses
:
print
(
'%g, '
%
(
sigmaScale
*
getLennardJonesParams
(
class1
,
class2
,
True
)[
1
].
value_in_unit
(
nanometers
)),
end
=
''
)
print
()
print
(
"""]
# Create a CustomNonbondedForce to compute Lennard-Jones interactions.
customNonbondedForce = mm.CustomNonbondedForce('4*eps*((sig/r)^12-(sig/r)^6); eps=epsilon(type1, type2); sig=sigma(type1, type2)')
customNonbondedForce.setNonbondedMethod(min(nonbondedForce.getNonbondedMethod(), 2))
customNonbondedForce.addTabulatedFunction('epsilon', mm.Discrete2DFunction(numAtomClasses, numAtomClasses, epsilon))
customNonbondedForce.addTabulatedFunction('sigma', mm.Discrete2DFunction(numAtomClasses, numAtomClasses, sigma))
customNonbondedForce.addPerParticleParameter('type')
for atom in data.atoms:
customNonbondedForce.addParticle([typeToClass[data.atomType[atom]]])
sys.addForce(customNonbondedForce)
# Update the NonbondedForce to have correct Lennard-Jones parameters.
for i in range(nonbondedForce.getNumParticles()):
(q, sig, eps) = nonbondedForce.getParticleParameters(i)
nonbondedForce.setParticleParameters(i, q, 1, 0)
for i in range(nonbondedForce.getNumExceptions()):
(p1, p2, q, sig, eps) = nonbondedForce.getExceptionParameters(i)
class1 = typeToClass[data.atomType[data.atoms[p1]]]
class2 = typeToClass[data.atomType[data.atoms[p2]]]
index = class1*numAtomClasses+class2
if eps._value != 0.0:
eps = epsilon14[index]
nonbondedForce.setExceptionParameters(i, p1, p2, q, sigma14[index], eps)
customNonbondedForce.addExclusion(p1, p2)
"""
)
print
(
' </Script>'
)
print
(
'</ForceField>'
)
devtools/forcefield-scripts/processTinkerForceField.py
0 → 100644
View file @
f2eb95d0
#=============================================================================================
# MODULE DOCSTRING
#=============================================================================================
"""
processTinkerForceField.py
Convert TINKER force field files into xml files for use by pyopenmm
(1) read residue template file
(2) read TINKER parameter file
(3) assign biotypes to each atom in residue template file
(4) output force-field parameter file
"""
#=============================================================================================
# GLOBAL IMPORTS
#=============================================================================================
import
os
import
xml.etree.ElementTree
as
etree
import
sys
import
shlex
import
math
import
datetime
import
os.path
#=============================================================================================
# Ion list
#=============================================================================================
# biotype 2003 NA "Sodium Ion" 250
# biotype 2004 K "Potassium Ion" 251
# biotype 2005 MG "Magnesium Ion" 255
# biotype 2006 CA "Calcium Ion" 256
# biotype 2007 CL "Chloride Ion" 258
ions
=
{
'Li+'
:
[
'LI'
,
249
,
249
],
'Na+'
:
[
'NA'
,
250
,
2003
],
'K+'
:
[
'K'
,
251
,
2004
],
'Rb+'
:
[
'RB'
,
252
,
252
],
'Cs+'
:
[
'CS'
,
253
,
253
],
'Be+'
:
[
'BE'
,
254
,
254
],
'Mg+'
:
[
'MG'
,
255
,
2005
],
'Ca+'
:
[
'CA'
,
256
,
2006
],
'Zn+'
:
[
'ZN'
,
257
,
257
],
'Cl-'
:
[
'Cl'
,
258
,
2007
]
}
atomTypes
=
{}
bioTypes
=
{}
#=============================================================================================
# Default 'constructor' for atoms
#=============================================================================================
def
getDefaultAtom
(
):
atom
=
dict
();
atom
[
'tinkerLookupName'
]
=
'XXX'
atom
[
'numberOfBonds'
]
=
-
1
atom
[
'type'
]
=
-
1
atom
[
'bonds'
]
=
dict
()
return
atom
#=============================================================================================
# Add bond to atomDict[]; atoms are added to atomDict[] if missing
#=============================================================================================
def
addBond
(
atomDict
,
atom1
,
atom2
):
if
(
atom1
not
in
atomDict
):
atomDict
[
atom1
]
=
getDefaultAtom
()
if
(
atom2
not
in
atomDict
):
atomDict
[
atom2
]
=
getDefaultAtom
()
atomDict
[
atom2
][
'bonds'
][
atom1
]
=
1
atomDict
[
atom1
][
'bonds'
][
atom2
]
=
1
#=============================================================================================
# Get atom dictionary from xml atom list
#=============================================================================================
def
getXmlAtoms
(
atoms
):
atomInfo
=
dict
();
for
atom
in
atoms
:
name
=
atom
.
attrib
[
'name'
]
atomInfo
[
name
]
=
getDefaultAtom
()
atomInfo
[
name
][
'tinkerLookupName'
]
=
atom
.
attrib
[
'tinkerLookupName'
]
atomInfo
[
name
][
'numberOfBonds'
]
=
atom
.
attrib
[
'bonds'
]
return
atomInfo
#=============================================================================================
# Get bond dictionary from xml bond list
#=============================================================================================
def
getXmlBonds
(
bonds
):
bondInfo
=
dict
();
for
bond
in
bonds
:
atom1
=
bond
.
attrib
[
'from'
]
atom2
=
bond
.
attrib
[
'to'
]
if
(
atom1
not
in
bondInfo
):
bondInfo
[
atom1
]
=
dict
()
if
(
atom2
not
in
bondInfo
):
bondInfo
[
atom2
]
=
dict
()
bondInfo
[
atom1
][
atom2
]
=
1
bondInfo
[
atom2
][
atom1
]
=
1
return
bondInfo
#=============================================================================================
# Read residue xml file
#=============================================================================================
def
buildResidueDict
(
residueXmlFileName
):
residueTree
=
etree
.
parse
(
residueXmlFileName
)
root
=
residueTree
.
getroot
()
residueDict
=
dict
()
# residueDict[residueName] = dict()
# ['loc']
# ['type']
# ['atoms'] = dict()
# [atomName] = dict()
# ['bonds'] = dict{}
for
residue
in
root
.
findall
(
'Residue'
):
residueName
=
residue
.
attrib
[
'name'
]
type
=
residue
.
attrib
[
'type'
]
fullName
=
residue
.
attrib
[
'fullName'
]
if
(
type
==
'protein'
):
isProtein
=
1
else
:
isProtein
=
0
bondInfo
=
getXmlBonds
(
residue
.
findall
(
'Bond'
)
)
# if residue is an amino acid, then create CALA and NALA residues, in addition to non-termianal residue, and include approriate atoms
# HXT is excluded from all residues
if
(
isProtein
):
cResidueName
=
'C'
+
residueName
nResidueName
=
'N'
+
residueName
residueDict
[
residueName
]
=
dict
()
residueDict
[
cResidueName
]
=
dict
()
residueDict
[
nResidueName
]
=
dict
()
residueDict
[
residueName
][
'atoms'
]
=
dict
()
residueDict
[
residueName
][
'type'
]
=
'protein'
residueDict
[
residueName
][
'loc'
]
=
'middle'
residueDict
[
residueName
][
'tinkerLookupName'
]
=
fullName
residueDict
[
residueName
][
'fullName'
]
=
fullName
residueDict
[
residueName
][
'include'
]
=
1
residueDict
[
cResidueName
][
'atoms'
]
=
dict
()
residueDict
[
cResidueName
][
'type'
]
=
'protein'
residueDict
[
cResidueName
][
'loc'
]
=
'C-Terminal'
residueDict
[
cResidueName
][
'loc'
]
=
'C-Terminal'
residueDict
[
cResidueName
][
'tinkerLookupName'
]
=
'C-Terminal '
+
residueName
residueDict
[
cResidueName
][
'fullName'
]
=
fullName
residueDict
[
nResidueName
][
'atoms'
]
=
dict
()
residueDict
[
nResidueName
][
'type'
]
=
'protein'
residueDict
[
nResidueName
][
'loc'
]
=
'N-Terminal'
residueDict
[
cResidueName
][
'tinkerLookupName'
]
=
'N-Terminal '
+
residueName
residueDict
[
cResidueName
][
'fullName'
]
=
fullName
residueList
=
[
residueDict
[
residueName
][
'atoms'
],
residueDict
[
cResidueName
][
'atoms'
]
,
residueDict
[
nResidueName
][
'atoms'
]
]
for
atom
in
bondInfo
:
if
(
atom
==
'OXT'
):
residueDict
[
cResidueName
][
'atoms'
][
atom
]
=
dict
()
elif
(
atom
==
'H2'
or
atom
==
'H3'
):
residueDict
[
nResidueName
][
'atoms'
][
atom
]
=
dict
()
elif
(
atom
!=
'HXT'
):
residueDict
[
nResidueName
][
'atoms'
][
atom
]
=
dict
()
residueDict
[
cResidueName
][
'atoms'
][
atom
]
=
dict
()
residueDict
[
residueName
][
'atoms'
][
atom
]
=
dict
()
for
atom1
in
bondInfo
:
for
atom2
in
bondInfo
[
atom1
]:
for
resDict
in
residueList
:
if
(
atom1
in
resDict
and
atom2
in
resDict
):
if
(
'bonds'
not
in
resDict
[
atom1
]
):
resDict
[
atom1
][
'bonds'
]
=
dict
()
if
(
'bonds'
not
in
resDict
[
atom2
]
):
resDict
[
atom2
][
'bonds'
]
=
dict
()
resDict
[
atom1
][
'bonds'
][
atom2
]
=
1
resDict
[
atom2
][
'bonds'
][
atom1
]
=
1
else
:
residueDict
[
residueName
]
=
dict
()
residueDict
[
residueName
][
'atoms'
]
=
dict
()
residueDict
[
residueName
][
'loc'
]
=
'unk'
residueDict
[
residueName
][
'type'
]
=
'unk'
residueDict
[
residueName
][
'include'
]
=
0
for
atom
in
bondInfo
:
if
(
atom
not
in
residueDict
[
residueName
][
'atoms'
]
):
residueDict
[
residueName
][
'atoms'
][
atom
]
=
dict
()
residueDict
[
residueName
][
'atoms'
][
atom
][
'bonds'
]
=
dict
()
for
atom2
in
bondInfo
[
atom
]:
if
(
atom2
not
in
residueDict
[
residueName
][
'atoms'
]
):
residueDict
[
residueName
][
'atoms'
][
atom2
]
=
dict
()
residueDict
[
residueName
][
'atoms'
][
atom2
][
'bonds'
]
=
dict
()
residueDict
[
residueName
][
'atoms'
][
atom2
][
'bonds'
][
atom
]
=
1
residueDict
[
residueName
][
'atoms'
][
atom
][
'bonds'
][
atom2
]
=
1
else
:
print
"File=%s does not have Residues tag."
%
(
residueXmlFileName
)
all
=
list
(
root
.
iter
()
)
for
i
in
all
:
print
"Tag <%s>"
%
(
i
.
tag
)
etree
.
dump
(
root
)
printMap
=
0
if
(
printMap
):
print
"Residue Map"
for
resName
in
sorted
(
residueDict
.
keys
()
):
residueInfo
=
residueDict
[
resName
][
'atoms'
]
print
"
\n
Residue %s %s %s"
%
(
resName
,
residueDict
[
resName
][
'type'
],
residueDict
[
resName
][
'loc'
])
for
atomName
in
sorted
(
residueInfo
.
keys
()
):
bondInfo
=
residueInfo
[
atomName
][
'bonds'
]
outputString
=
atomName
+
' { '
for
bondedAtom
in
sorted
(
bondInfo
.
keys
()
):
outputString
+=
bondedAtom
+
' '
outputString
+=
' }'
print
"%s"
%
outputString
print
"Start Lookup XML
\n\n
"
printXml
=
1
if
(
printXml
):
print
"<Residues>"
for
resName
in
sorted
(
residueDict
.
keys
()
):
if
(
'include'
in
residueDict
[
resName
]
and
residueDict
[
resName
][
'include'
]
):
type
=
residueDict
[
resName
][
'type'
]
loc
=
residueDict
[
resName
][
'loc'
]
tinkerLookupName
=
residueDict
[
resName
][
'tinkerLookupName'
]
fullName
=
residueDict
[
resName
][
'fullName'
]
outputString
=
""" <Residue abbreviation="%s" loc="%s" type="%s" tinkerLookupName="%s" fullName="%s">"""
%
(
resName
,
loc
,
type
,
tinkerLookupName
,
fullName
)
print
"%s"
%
outputString
atomsInfo
=
residueDict
[
resName
][
'atoms'
]
for
atomName
in
sorted
(
atomsInfo
.
keys
()
):
numberOfBonds
=
len
(
atomsInfo
[
atomName
][
'bonds'
]
)
outputString
=
""" <Atom name="%s" tinkerLookupName="%s" bonds=%d />"""
%
(
atomName
,
atomName
,
numberOfBonds
)
print
"%s"
%
outputString
includedBonds
=
dict
()
for
atomName
in
sorted
(
atomsInfo
.
keys
()
):
bondsInfo
=
atomsInfo
[
atomName
][
'bonds'
]
for
bondedAtom
in
bondsInfo
:
if
(
bondedAtom
not
in
includedBonds
or
atomName
not
in
includedBonds
[
bondedAtom
]
):
outputString
=
""" <Bond from="%s" to="%s" />"""
%
(
atomName
,
bondedAtom
)
if
(
atomName
not
in
includedBonds
):
includedBonds
[
atomName
]
=
dict
()
if
(
bondedAtom
not
in
includedBonds
):
includedBonds
[
bondedAtom
]
=
dict
()
includedBonds
[
atomName
][
bondedAtom
]
=
1
includedBonds
[
bondedAtom
][
atomName
]
=
1
print
"%s"
%
outputString
print
"</Residue>"
print
"</Residues>"
sys
.
exit
(
0
)
return
residueDict
#=============================================================================================
# Build entry for protein residue
#=============================================================================================
def
buildProteinResidue
(
residueDict
,
atoms
,
bondInfo
,
abbr
,
loc
,
tinkerLookupName
,
include
,
residueName
,
type
):
# residueDict[abbr] abbr=ALA, CALA, NALA, ...
# residueDict[abbr]['atoms'] list if atom dict()
# residueDict[abbr]['type'] molecule type ('protein', 'nucleic acid', ...)
# residueDict[abbr]['tinkerLookupName'] Tinker lookup name
# residueDict[abbr]['residueName'] residueName
# residueDict[abbr]['include'] include in output
residueDict
[
abbr
]
=
dict
()
residueDict
[
abbr
][
'atoms'
]
=
atoms
residueDict
[
abbr
][
'type'
]
=
type
residueDict
[
abbr
][
'loc'
]
=
loc
residueDict
[
abbr
][
'tinkerLookupName'
]
=
tinkerLookupName
residueDict
[
abbr
][
'residueName'
]
=
residueName
residueDict
[
abbr
][
'include'
]
=
include
# for each bond, add entry to
# residueDict[abbr]['atoms'][atom]['bonds']
# residueDict[abbr]['atoms'][bondedAtom]['bonds']
for
atom
in
bondInfo
:
if
(
atom
in
residueDict
[
abbr
][
'atoms'
]
):
if
(
'bonds'
not
in
residueDict
[
abbr
][
'atoms'
][
atom
]
):
residueDict
[
abbr
][
'atoms'
][
atom
][
'bonds'
]
=
dict
()
for
bondedAtom
in
bondInfo
[
atom
]:
if
(
bondedAtom
in
residueDict
[
abbr
][
'atoms'
]
):
if
(
'bonds'
not
in
residueDict
[
abbr
][
'atoms'
][
bondedAtom
]
):
residueDict
[
abbr
][
'atoms'
][
bondedAtom
][
'bonds'
]
=
dict
()
residueDict
[
abbr
][
'atoms'
][
bondedAtom
][
'bonds'
][
atom
]
=
1
residueDict
[
abbr
][
'atoms'
][
atom
][
'bonds'
][
bondedAtom
]
=
1
else
:
print
"Error: bonded atom=%s not in residue=%s"
%
(
atom
,
abbr
)
else
:
print
"Error: bonded atom=%s nt in residue=%s"
%
(
atom
,
abbr
)
return
#=============================================================================================
# Copy a bond (dict() copy)
#=============================================================================================
def
copyBonds
(
bonds
):
bondCopy
=
dict
()
for
key
in
bonds
.
keys
():
bondCopy
[
key
]
=
bonds
[
key
]
return
bondCopy
#=============================================================================================
# Copy a atom (dict() copy, including the 'bonds' list)
#=============================================================================================
def
copyAtom
(
atom
):
atomCopy
=
dict
()
for
key
in
atom
.
keys
():
if
(
key
!=
'bonds'
):
atomCopy
[
key
]
=
atom
[
key
]
else
:
atomCopy
[
'bonds'
]
=
copyBonds
(
atom
[
key
]
)
return
atomCopy
#=============================================================================================
# Copy a residue, including atom list
#=============================================================================================
def
copyProteinResidue
(
residue
):
residueCopy
=
dict
()
residueCopy
[
'atoms'
]
=
dict
()
residueCopy
[
'type'
]
=
residue
[
'type'
]
residueCopy
[
'loc'
]
=
residue
[
'loc'
]
residueCopy
[
'tinkerLookupName'
]
=
residue
[
'tinkerLookupName'
]
residueCopy
[
'residueName'
]
=
residue
[
'residueName'
]
residueCopy
[
'include'
]
=
residue
[
'include'
]
for
atom
in
residue
[
'atoms'
]:
residueCopy
[
'atoms'
][
atom
]
=
copyAtom
(
residue
[
'atoms'
][
atom
]
)
return
residueCopy
#=============================================================================================
# Build residue hash based on xml file
#=============================================================================================
def
buildResidueDictFinal
(
residueXmlFileName
):
residueTree
=
etree
.
parse
(
residueXmlFileName
)
print
"Read %s"
%
(
residueXmlFileName
)
root
=
residueTree
.
getroot
()
residueDict
=
dict
()
# residueDict[residueName] = dict()
# ['loc']
# ['type']
# ['atoms'] = dict()
# [atomName] = dict()
# ['bonds'] = dict{}
for
residue
in
root
.
findall
(
'Residue'
):
# <Residue abbreviation="MET" loc="middle" type="protein" tinkerLookupName="Methionine" fullName="Methionine">
abbr
=
residue
.
attrib
[
'abbreviation'
]
loc
=
residue
.
attrib
[
'loc'
]
type
=
residue
.
attrib
[
'type'
]
tinkerName
=
residue
.
attrib
[
'tinkerLookupName'
]
residueName
=
residue
.
attrib
[
'fullName'
]
isProtein
=
0
isWater
=
0
if
(
type
==
'protein'
):
isProtein
=
1
elif
(
type
==
'AmoebaWater'
):
isWater
=
1
else
:
continue
atoms
=
getXmlAtoms
(
residue
.
findall
(
'Atom'
)
)
bondInfo
=
getXmlBonds
(
residue
.
findall
(
'Bond'
)
)
# if residue is an amino acid, then create CALA and NALA residues, in addition to non-termianal residue, and include approriate atoms
# HXT is excluded from all residues
if
(
isWater
):
buildProteinResidue
(
residueDict
,
atoms
,
bondInfo
,
abbr
,
'x'
,
tinkerName
,
1
,
'HOH'
,
'water'
)
elif
(
isProtein
):
buildProteinResidue
(
residueDict
,
atoms
,
bondInfo
,
abbr
,
'm'
,
tinkerName
,
1
,
residueName
,
'protein'
)
cResidueName
=
'C'
+
abbr
residueDict
[
cResidueName
]
=
copyProteinResidue
(
residueDict
[
abbr
]
)
residueDict
[
cResidueName
][
'loc'
]
=
'c'
if
(
residueDict
[
abbr
][
'tinkerLookupName'
].
find
(
'('
)
>
-
1
):
begin
=
residueDict
[
abbr
][
'tinkerLookupName'
].
find
(
'('
)
end
=
residueDict
[
abbr
][
'tinkerLookupName'
].
find
(
')'
)
+
1
sub
=
residueDict
[
abbr
][
'tinkerLookupName'
][
begin
:
end
]
if
(
sub
==
'(HD)'
or
sub
==
'(HE)'
):
residueDict
[
cResidueName
][
'tinkerLookupName'
]
=
'C-Terminal '
+
'HIS '
+
sub
else
:
residueDict
[
cResidueName
][
'tinkerLookupName'
]
=
'C-Terminal '
+
abbr
+
' '
+
sub
print
"tinkerLookupName %s %s"
%
(
abbr
,
residueDict
[
cResidueName
][
'tinkerLookupName'
])
else
:
residueDict
[
cResidueName
][
'tinkerLookupName'
]
=
'C-Terminal '
+
abbr
residueDict
[
cResidueName
][
'atoms'
][
'OXT'
]
=
copyAtom
(
residueDict
[
abbr
][
'atoms'
][
'O'
]
)
residueDict
[
cResidueName
][
'atoms'
][
'OXT'
][
'tinkerLookupName'
]
=
'OXT'
residueDict
[
cResidueName
][
'atoms'
][
'O'
][
'tinkerLookupName'
]
=
'OXT'
residueDict
[
cResidueName
][
'parent'
]
=
residueDict
[
abbr
]
nResidueName
=
'N'
+
abbr
residueDict
[
nResidueName
]
=
copyProteinResidue
(
residueDict
[
abbr
]
)
residueDict
[
nResidueName
][
'loc'
]
=
'n'
residueDict
[
nResidueName
][
'tinkerLookupName'
]
=
'N-Terminal '
+
abbr
residueDict
[
nResidueName
][
'parent'
]
=
residueDict
[
abbr
]
if
(
abbr
==
'PRO'
):
#<Atom name="H" tinkerLookupName="HN" bonds="1" />
residueDict
[
nResidueName
][
'atoms'
][
'H2'
]
=
getDefaultAtom
()
residueDict
[
nResidueName
][
'atoms'
][
'H3'
]
=
getDefaultAtom
()
residueDict
[
nResidueName
][
'atoms'
][
'H2'
][
'tinkerLookupName'
]
=
'HN'
residueDict
[
nResidueName
][
'atoms'
][
'H3'
][
'tinkerLookupName'
]
=
'HN'
addBond
(
residueDict
[
nResidueName
][
'atoms'
],
'H2'
,
'N'
)
addBond
(
residueDict
[
nResidueName
][
'atoms'
],
'H3'
,
'N'
)
else
:
residueDict
[
nResidueName
][
'atoms'
][
'H2'
]
=
copyAtom
(
residueDict
[
abbr
][
'atoms'
][
'H'
]
)
residueDict
[
nResidueName
][
'atoms'
][
'H3'
]
=
copyAtom
(
residueDict
[
abbr
][
'atoms'
][
'H'
]
)
print
"Start Lookup XML FFFFinal
\n\n
"
printXml
=
1
if
(
printXml
):
print
"<Residues>"
for
resName
in
sorted
(
residueDict
.
keys
()
):
if
(
'include'
in
residueDict
[
resName
]
and
residueDict
[
resName
][
'include'
]
):
type
=
residueDict
[
resName
][
'type'
]
loc
=
residueDict
[
resName
][
'loc'
]
tinkerLookupName
=
residueDict
[
resName
][
'tinkerLookupName'
]
fullName
=
residueDict
[
resName
][
'residueName'
]
outputString
=
""" <Residue abbreviation="%s" loc="%s" type="%s" tinkerLookupName="%s" fullName="%s">"""
%
(
resName
,
loc
,
type
,
tinkerLookupName
,
fullName
)
print
"%s"
%
outputString
atomsInfo
=
residueDict
[
resName
][
'atoms'
]
for
atomName
in
sorted
(
atomsInfo
.
keys
()
):
numberOfBonds
=
atomsInfo
[
atomName
][
'numberOfBonds'
]
tinkerLookupName
=
atomsInfo
[
atomName
][
'tinkerLookupName'
]
outputString
=
""" <Atom name="%s" tinkerLookupName="%s" bonds="%s" />"""
%
(
atomName
,
tinkerLookupName
,
numberOfBonds
)
print
"%s"
%
outputString
includedBonds
=
dict
()
for
atomName
in
sorted
(
atomsInfo
.
keys
()
):
bondsInfo
=
atomsInfo
[
atomName
][
'bonds'
]
for
bondedAtom
in
bondsInfo
:
if
(
bondedAtom
not
in
includedBonds
or
atomName
not
in
includedBonds
[
bondedAtom
]
):
outputString
=
""" <Bond from="%s" to="%s" />"""
%
(
atomName
,
bondedAtom
)
if
(
atomName
not
in
includedBonds
):
includedBonds
[
atomName
]
=
dict
()
if
(
bondedAtom
not
in
includedBonds
):
includedBonds
[
bondedAtom
]
=
dict
()
includedBonds
[
atomName
][
bondedAtom
]
=
1
includedBonds
[
bondedAtom
][
atomName
]
=
1
print
"%s"
%
outputString
print
"</Residue>"
print
"</Residues>"
return
residueDict
#=============================================================================================
# Set biotype for each atom in residueDict
#=============================================================================================
def
setBioTypes
(
bioTypes
,
residueDict
):
for
res
in
residueDict
:
for
atom
in
residueDict
[
res
][
'atoms'
]:
lookupName
=
residueDict
[
res
][
'atoms'
][
atom
][
'tinkerLookupName'
]
+
'_'
+
residueDict
[
res
][
'tinkerLookupName'
]
if
(
lookupName
in
bioTypes
):
residueDict
[
res
][
'atoms'
][
atom
][
'type'
]
=
bioTypes
[
lookupName
][
3
]
else
:
print
"For %s lookupName=%s not in biotype"
%
(
atom
,
lookupName
)
if
(
'parent'
in
residueDict
[
res
]
):
lookupName
=
residueDict
[
res
][
'atoms'
][
atom
][
'tinkerLookupName'
]
+
'_'
+
residueDict
[
res
][
'parent'
][
'tinkerLookupName'
]
if
(
lookupName
in
bioTypes
):
residueDict
[
res
][
'atoms'
][
atom
][
'type'
]
=
bioTypes
[
lookupName
][
3
]
else
:
print
"Missing lookupName=%s from biotype"
%
(
lookupName
)
return
0
#=============================================================================================
# Add multipole for forces[]; added entry is a list of axis info [kz, kx, ky] and another
# list of multipoles [charge, dipole, quadrupole]
#=============================================================================================
def
addMultipole
(
lineIndex
,
allLines
,
forces
):
if
(
'multipole'
not
in
forces
):
forces
[
'multipole'
]
=
[]
# axis indices and charge
fields
=
allLines
[
lineIndex
]
multipoles
=
[
fields
[
-
1
]
]
axisInfo
=
fields
[
1
:
-
1
]
# dipole
lineIndex
+=
1
fields
=
allLines
[
lineIndex
]
multipoles
.
append
(
fields
[
0
]
)
multipoles
.
append
(
fields
[
1
]
)
multipoles
.
append
(
fields
[
2
]
)
# quadrupole
lineIndex
+=
1
fields
=
allLines
[
lineIndex
]
multipoles
.
append
(
fields
[
0
]
)
lineIndex
+=
1
fields
=
allLines
[
lineIndex
]
multipoles
.
append
(
fields
[
0
]
)
multipoles
.
append
(
fields
[
1
]
)
lineIndex
+=
1
fields
=
allLines
[
lineIndex
]
multipoles
.
append
(
fields
[
0
]
)
multipoles
.
append
(
fields
[
1
]
)
multipoles
.
append
(
fields
[
2
]
)
lineIndex
+=
1
# save info
multipoleInfo
=
[
axisInfo
,
multipoles
]
forces
[
'multipole'
].
append
(
multipoleInfo
)
return
(
lineIndex
)
#=============================================================================================
# Add tortor parameters/grid to forces[]; format of each entry is [ first tortor line, grid ]
#=============================================================================================
def
addTorTor
(
lineIndex
,
allLines
,
forces
):
if
(
'tortors'
not
in
forces
):
forces
[
'tortors'
]
=
[]
fields
=
allLines
[
lineIndex
]
tortorInfo
=
fields
[
1
:]
# read grid lines
lastGridLine
=
lineIndex
+
int
(
fields
[
6
])
*
int
(
fields
[
7
])
grid
=
[]
while
(
lineIndex
<
lastGridLine
):
lineIndex
+=
1
grid
.
append
(
allLines
[
lineIndex
]
)
forces
[
'tortors'
].
append
(
[
tortorInfo
,
grid
]
)
return
(
lineIndex
)
#=============================================================================================
old
=
0
if
(
old
):
residueXmlFileName
=
'/home/friedrim/source/pyTinker/residues.xml'
residueXmlFileName
=
'/home/friedrim/source/pyTinker/residues.xml'
residueDict
=
buildResidueDict
(
residueXmlFileName
)
else
:
residueXmlFileName
=
'residuesFinal.xml'
residueDict
=
buildResidueDictFinal
(
residueXmlFileName
)
#=============================================================================================
# recognizedForces[] contain raw list entries from TINKER parameter file
resAtomTypes
=
{}
forces
=
{}
recognizedForces
=
{}
recognizedForces
[
'bond'
]
=
1
recognizedForces
[
'angle'
]
=
1
recognizedForces
[
'strbnd'
]
=
1
recognizedForces
[
'ureybrad'
]
=
1
recognizedForces
[
'opbend'
]
=
1
recognizedForces
[
'torsion'
]
=
1
recognizedForces
[
'pitors'
]
=
1
recognizedForces
[
'vdw'
]
=
1
recognizedForces
[
'polarize'
]
=
1
recognizedForces
[
'tortors'
]
=
addTorTor
recognizedForces
[
'multipole'
]
=
addMultipole
#=============================================================================================
# recognizedScalars[] contain raw scalar entries from TINKER parameter file
scalars
=
{}
recognizedScalars
=
{}
recognizedScalars
[
'forcefield'
]
=
'-2.55'
recognizedScalars
[
'bond-cubic'
]
=
'-2.55'
recognizedScalars
[
'bond-quartic'
]
=
'3.793125'
recognizedScalars
[
'angle-cubic'
]
=
'-0.014'
recognizedScalars
[
'angle-quartic'
]
=
'0.000056'
recognizedScalars
[
'angle-pentic'
]
=
'-0.0000007'
recognizedScalars
[
'angle-sextic'
]
=
'0.000000022'
recognizedScalars
[
'opbendtype'
]
=
'ALLINGER'
recognizedScalars
[
'opbend-cubic'
]
=
'-0.014'
recognizedScalars
[
'opbend-quartic'
]
=
'0.000056'
recognizedScalars
[
'opbend-pentic'
]
=
'-0.0000007'
recognizedScalars
[
'opbend-sextic'
]
=
'0.000000022'
recognizedScalars
[
'torsionunit'
]
=
'0.5'
recognizedScalars
[
'vdwtype'
]
=
'BUFFERED-14-7'
recognizedScalars
[
'radiusrule'
]
=
'CUBIC-MEAN'
recognizedScalars
[
'radiustype'
]
=
'R-MIN'
recognizedScalars
[
'radiussize'
]
=
'DIAMETER'
recognizedScalars
[
'epsilonrule'
]
=
'HHG'
recognizedScalars
[
'dielectric'
]
=
'1.0'
recognizedScalars
[
'polarization'
]
=
'MUTUAL'
recognizedScalars
[
'vdw-13-scale'
]
=
'0.0'
recognizedScalars
[
'vdw-14-scale'
]
=
'1.0'
recognizedScalars
[
'vdw-15-scale'
]
=
'1.0'
recognizedScalars
[
'mpole-12-scale'
]
=
'0.0'
recognizedScalars
[
'mpole-13-scale'
]
=
'0.0'
recognizedScalars
[
'mpole-14-scale'
]
=
'0.4'
recognizedScalars
[
'mpole-15-scale'
]
=
'0.8'
recognizedScalars
[
'polar-12-scale'
]
=
'0.0'
recognizedScalars
[
'polar-13-scale'
]
=
'0.0'
recognizedScalars
[
'polar-14-scale'
]
=
'1.0'
recognizedScalars
[
'polar-15-scale'
]
=
'1.0'
recognizedScalars
[
'polar-14-intra'
]
=
'0.5'
recognizedScalars
[
'direct-11-scale'
]
=
'0.0'
recognizedScalars
[
'direct-12-scale'
]
=
'1.0'
recognizedScalars
[
'direct-13-scale'
]
=
'1.0'
recognizedScalars
[
'direct-14-scale'
]
=
'1.0'
recognizedScalars
[
'mutual-11-scale'
]
=
'1.0'
recognizedScalars
[
'mutual-12-scale'
]
=
'1.0'
recognizedScalars
[
'mutual-13-scale'
]
=
'1.0'
recognizedScalars
[
'mutual-14-scale'
]
=
'1.0'
#=============================================================================================
# get all 'interesting' lines in file
allLines
=
[]
for
line
in
open
(
sys
.
argv
[
1
]):
try
:
fields
=
shlex
.
split
(
line
)
except
:
continue
if
len
(
fields
)
==
0
:
continue
if
fields
[
0
][
0
]
==
'#'
:
continue
allLines
.
append
(
fields
)
#=============================================================================================
# load lines in lists/scalar values
lineIndex
=
0
while
lineIndex
<
len
(
allLines
):
fields
=
allLines
[
lineIndex
]
if
fields
[
0
]
==
'atom'
:
if
(
fields
[
3
]
in
ions
):
ionInfo
=
ions
[
fields
[
3
]]
element
=
ionInfo
[
0
]
else
:
element
=
fields
[
3
][
0
]
atomTypes
[
int
(
fields
[
1
])]
=
(
fields
[
2
],
element
,
fields
[
6
])
lineIndex
+=
1
elif
fields
[
0
]
==
'biotype'
:
lookUp
=
fields
[
2
]
+
'_'
+
fields
[
3
]
bioTypes
[
lookUp
]
=
fields
[
1
:]
lineIndex
+=
1
elif
fields
[
0
]
in
recognizedForces
:
if
(
recognizedForces
[
fields
[
0
]]
==
1
):
if
(
fields
[
0
]
not
in
forces
):
forces
[
fields
[
0
]]
=
[]
forces
[
fields
[
0
]].
append
(
fields
[
1
:]
)
lineIndex
+=
1
else
:
lineIndex
=
recognizedForces
[
fields
[
0
]](
lineIndex
,
allLines
,
forces
)
elif
fields
[
0
]
in
recognizedScalars
:
scalars
[
fields
[
0
]]
=
fields
[
1
]
lineIndex
+=
1
else
:
print
"Field %s not recognized: line=<%s>"
%
(
fields
[
0
],
allLines
[
lineIndex
]
)
lineIndex
+=
1
#=============================================================================================
# set biotypes for all atoms
setBioTypes
(
bioTypes
,
residueDict
)
#=============================================================================================
# open force field xml file for output
tinkerXmlFileName
=
scalars
[
'forcefield'
]
tinkerXmlFileName
+=
'.xml'
tinkerXmlFile
=
open
(
tinkerXmlFileName
,
'w'
)
print
"Opened %s."
%
(
tinkerXmlFileName
)
gkXmlFileName
=
scalars
[
'forcefield'
]
gkXmlFileName
+=
'_gk.xml'
gkXmlFile
=
open
(
gkXmlFileName
,
'w'
)
print
"Opened %s."
%
(
gkXmlFileName
)
today
=
datetime
.
date
.
today
().
isoformat
()
sourceFile
=
os
.
path
.
basename
(
sys
.
argv
[
1
])
header
=
"<!-- Generated on %s from %s -->
\n\n
"
%
(
today
,
sourceFile
)
tinkerXmlFile
.
write
(
header
)
gkXmlFile
.
write
(
header
)
gkXmlFile
.
write
(
"<ForceField>
\n
"
)
tinkerXmlFile
.
write
(
"<ForceField>
\n
"
)
tinkerXmlFile
.
write
(
" <AtomTypes>
\n
"
)
if
(
scalars
[
'forcefield'
].
find
(
'AMOEBA'
)
>
-
1
):
isAmoeba
=
1
else
:
isAmoeba
=
0
#=============================================================================================
# atom type/class
# atmType class name name atomicNo. mass valence
# atom 1 1 N "Glycine N" 7 14.003 3
# atom 2 2 CA "Glycine CA" 6 12.000 4
# atom 3 3 C "Glycine C" 6 12.000 3
# atom 4 4 HN "Glycine HN" 1 1.008 1
# atom 5 5 O "Glycine O" 8 15.995 1
# atom 380 73 O "AMOEBA Water O" 8 15.999 2
# atom 381 74 H "AMOEBA Water H" 1 1.008 1
# atom 383 76 Na+ "Sodium Ion Na+" 11 22.990 0
# atom 384 77 K+ "Potassium Ion K+" 19 39.098 0
# atom 385 78 Rb+ "Rubidium Ion Rb+" 37 85.468 0
# atom 386 79 Cs+ "Cesium Ion Cs+" 55 132.905 0
# atom 387 80 Be+ "Beryllium Ion Be+2" 4 9.012 0
# atom 388 81 Mg+ "Magnesium Ion Mg+2" 12 24.305 0
# atom 389 82 Ca+ "Calcium Ion Ca+2" 20 40.078 0
# atom 390 83 Cl- "Chloride Ion Cl-" 17 35.453 0
# biotype atmType
# biotype 1 N "Glycine" 1
# biotype 2 CA "Glycine" 2
# biotype 3 C "Glycine" 3
# biotype 4 HN "Glycine" 4
# biotype 5 O "Glycine" 5
# biotype 2001 O "Water" 380
# biotype 2002 H "Water" 381
# biotype 2003 NA "Sodium Ion" 383
# biotype 2004 K "Potassium Ion" 384
# biotype 2005 MG "Magnesium Ion" 388
# biotype 2006 CA "Calcium Ion" 389
# biotype 2007 CL "Chloride Ion" 390
if
(
isAmoeba
):
for
type
in
sorted
(
atomTypes
):
outputString
=
""" <Type name="%s" class="%s" element="%s" mass="%s"/>"""
%
(
type
,
atomTypes
[
type
][
0
],
atomTypes
[
type
][
1
],
atomTypes
[
type
][
2
])
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
else
:
for
type
in
sorted
(
atomTypes
):
outputString
=
""" <Type name="%s" class="%s" mass="%s"/>"""
%
(
type
,
atomTypes
[
type
][
0
],
atomTypes
[
type
][
1
])
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AtomTypes>
\n
"
)
#=============================================================================================
# residues
tinkerXmlFile
.
write
(
" <Residues>
\n
"
)
for
res
in
sorted
(
residueDict
):
if
(
residueDict
[
res
][
'include'
]
):
outputString
=
""" <Residue name="%s">"""
%
(
res
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
atomIndex
=
dict
()
atomCount
=
0
for
atom
in
sorted
(
residueDict
[
res
][
'atoms'
].
keys
()
):
type
=
residueDict
[
res
][
'atoms'
][
atom
][
'type'
]
typeI
=
int
(
type
)
if
(
typeI
<
0
):
print
"Error: type=%s for atom=%s of residue=%s"
%
(
type
,
atom
,
res
)
tag
=
" <Atom name=
\"
%s
\"
type=
\"
%s
\"
/>"
%
(
atom
,
type
)
atomIndex
[
atom
]
=
atomCount
atomCount
+=
1
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
tag
)
)
includedBonds
=
dict
()
for
atomName
in
sorted
(
residueDict
[
res
][
'atoms'
].
keys
()
):
bondsInfo
=
residueDict
[
res
][
'atoms'
][
atomName
][
'bonds'
]
for
bondedAtom
in
bondsInfo
:
if
(
bondedAtom
not
in
includedBonds
or
atomName
not
in
includedBonds
[
bondedAtom
]
):
outputString
=
""" <Bond from="%s" to="%s" />"""
%
(
str
(
atomIndex
[
atomName
]),
str
(
atomIndex
[
bondedAtom
]))
if
(
atomName
not
in
includedBonds
):
includedBonds
[
atomName
]
=
dict
()
if
(
bondedAtom
not
in
includedBonds
):
includedBonds
[
bondedAtom
]
=
dict
()
includedBonds
[
atomName
][
bondedAtom
]
=
1
includedBonds
[
bondedAtom
][
atomName
]
=
1
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
outputStrings
=
[]
if
(
residueDict
[
res
][
'loc'
]
==
'm'
):
outputStrings
.
append
(
""" <ExternalBond from="%s" />"""
%
(
str
(
atomIndex
[
'N'
])
))
outputStrings
.
append
(
""" <ExternalBond from="%s" />"""
%
(
str
(
atomIndex
[
'C'
])
)
)
if
(
residueDict
[
res
][
'loc'
]
==
'n'
):
outputStrings
.
append
(
""" <ExternalBond from="%s" />"""
%
(
str
(
atomIndex
[
'C'
])
)
)
if
(
residueDict
[
res
][
'loc'
]
==
'c'
):
outputStrings
.
append
(
""" <ExternalBond from="%s" />"""
%
(
str
(
atomIndex
[
'N'
])
)
)
if
(
res
.
find
(
'CYX'
)
>
-
1
):
outputStrings
.
append
(
""" <ExternalBond from="%s" />"""
%
(
str
(
atomIndex
[
'SG'
])
)
)
for
outputString
in
outputStrings
:
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </Residue>
\n
"
)
# End caps
tinkerXmlFile
.
write
(
' <Residue name="ACE">
\n
'
)
tinkerXmlFile
.
write
(
' <Atom name="HH31" type="%s"/>
\n
'
%
bioTypes
[
'H_Acetyl N-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="CH3" type="%s"/>
\n
'
%
bioTypes
[
'CH3_Acetyl N-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="HH32" type="%s"/>
\n
'
%
bioTypes
[
'H_Acetyl N-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="HH33" type="%s"/>
\n
'
%
bioTypes
[
'H_Acetyl N-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="C" type="%s"/>
\n
'
%
bioTypes
[
'C_Acetyl N-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="O" type="%s"/>
\n
'
%
bioTypes
[
'O_Acetyl N-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Bond from="0" to="1"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="1" to="2"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="1" to="3"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="1" to="4"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="4" to="5"/>
\n
'
)
tinkerXmlFile
.
write
(
' <ExternalBond from="4"/>
\n
'
)
tinkerXmlFile
.
write
(
' </Residue>
\n
'
)
tinkerXmlFile
.
write
(
' <Residue name="NME">
\n
'
)
tinkerXmlFile
.
write
(
' <Atom name="N" type="%s"/>
\n
'
%
bioTypes
[
'N_N-MeAmide C-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="H" type="%s"/>
\n
'
%
bioTypes
[
'HN_N-MeAmide C-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="CH3" type="%s"/>
\n
'
%
bioTypes
[
'CH3_N-MeAmide C-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="HH31" type="%s"/>
\n
'
%
bioTypes
[
'H_N-MeAmide C-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="HH32" type="%s"/>
\n
'
%
bioTypes
[
'H_N-MeAmide C-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Atom name="HH33" type="%s"/>
\n
'
%
bioTypes
[
'H_N-MeAmide C-Terminus'
][
3
])
tinkerXmlFile
.
write
(
' <Bond from="0" to="1"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="0" to="2"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="2" to="3"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="2" to="4"/>
\n
'
)
tinkerXmlFile
.
write
(
' <Bond from="2" to="5"/>
\n
'
)
tinkerXmlFile
.
write
(
' <ExternalBond from="0"/>
\n
'
)
tinkerXmlFile
.
write
(
' </Residue>
\n
'
)
# ions
for
ion
,
ionInfo
in
ions
.
iteritems
():
outputString
=
""" <Residue name="%s">
\n
"""
%
(
ionInfo
[
0
])
outputString
+=
""" <Atom name="%s" type="%s"/>
\n
"""
%
(
ionInfo
[
0
],
str
(
ionInfo
[
1
]))
outputString
+=
""" </Residue>
\n
"""
tinkerXmlFile
.
write
(
"%s"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </Residues>
\n
"
)
radian
=
57.2957795130
if
(
isAmoeba
):
#=============================================================================================
# AmoebaBondForce
cubic
=
10.
*
float
(
scalars
[
'bond-cubic'
])
quartic
=
100.
*
float
(
scalars
[
'bond-quartic'
])
outputString
=
""" <AmoebaBondForce bond-cubic="%s" bond-quartic="%s">"""
%
(
str
(
cubic
),
str
(
quartic
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
bonds
=
forces
[
'bond'
]
for
bond
in
bonds
:
length
=
float
(
bond
[
3
])
*
0.1
k
=
float
(
bond
[
2
])
*
100.0
*
4.184
outputString
=
""" <Bond class1="%s" class2="%s" length="%s" k="%s"/>"""
%
(
bond
[
0
],
bond
[
1
],
str
(
length
),
str
(
k
))
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaBondForce>
\n
"
)
#=============================================================================================
# AmoebaAngleForce
cubic
=
float
(
scalars
[
'angle-cubic'
])
quartic
=
float
(
scalars
[
'angle-quartic'
])
pentic
=
float
(
scalars
[
'angle-pentic'
])
sextic
=
float
(
scalars
[
'angle-sextic'
])
outputString
=
""" <AmoebaAngleForce angle-cubic="%s" angle-quartic="%s" angle-pentic="%s" angle-sextic="%s">"""
%
(
str
(
cubic
),
str
(
quartic
),
str
(
pentic
),
str
(
sextic
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
angles
=
forces
[
'angle'
]
radian
=
57.2957795130
radian2
=
4.184
/
(
radian
*
radian
)
for
angle
in
angles
:
k
=
float
(
angle
[
3
])
*
radian2
outputString
=
""" <Angle class1="%s" class2="%s" class3="%s" k="%s" angle1="%s" """
%
(
angle
[
0
],
angle
[
1
],
angle
[
2
],
str
(
k
),
angle
[
4
]
)
if
(
len
(
angle
)
>
5
):
outputString
+=
""" angle2="%s" """
%
(
angle
[
5
])
if
(
len
(
angle
)
>
6
):
outputString
+=
""" angle3="%s" """
%
(
angle
[
6
])
outputString
+=
" /> "
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaAngleForce>
\n
"
)
#=============================================================================================
# AmoebaOutOfPlaneBendForce
cubic
=
float
(
scalars
[
'opbend-cubic'
])
quartic
=
float
(
scalars
[
'opbend-quartic'
])
pentic
=
float
(
scalars
[
'opbend-pentic'
])
sextic
=
float
(
scalars
[
'opbend-sextic'
])
type
=
scalars
[
'opbendtype'
]
outputString
=
""" <AmoebaOutOfPlaneBendForce type="%s" opbend-cubic="%s" opbend-quartic="%s" opbend-pentic="%s" opbend-sextic="%s">"""
%
(
type
,
str
(
cubic
),
str
(
quartic
),
str
(
pentic
),
str
(
sextic
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
opbends
=
forces
[
'opbend'
]
radian2
=
4.184
/
(
radian
*
radian
)
for
opbend
in
opbends
:
k
=
float
(
opbend
[
4
])
*
radian2
outputString
=
""" <Angle class1="%s" class2="%s" class3="%s" class4="%s" k="%s"/>"""
%
(
opbend
[
0
],
opbend
[
1
],
opbend
[
2
],
opbend
[
3
],
str
(
k
))
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaOutOfPlaneBendForce>
\n
"
)
#=============================================================================================
# AmoebaTorsionForce
torsionUnit
=
float
(
scalars
[
'torsionunit'
])
outputString
=
""" <AmoebaTorsionForce torsionUnit="%s">"""
%
(
torsionUnit
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
torsions
=
forces
[
'torsion'
]
conversion
=
4.184
*
torsionUnit
for
torsion
in
torsions
:
outputString
=
""" <Torsion class1="%s" class2="%s" class3="%s" class4="%s" """
%
(
torsion
[
0
],
torsion
[
1
],
torsion
[
2
],
torsion
[
3
])
startIndex
=
4
for
ii
in
range
(
0
,
3
):
torsionSuffix
=
str
(
ii
+
1
)
amplitudeAttributeName
=
'amp'
+
torsionSuffix
angleAttributeName
=
'angle'
+
torsionSuffix
amplitude
=
float
(
torsion
[
startIndex
])
*
conversion
angle
=
float
(
torsion
[
startIndex
+
1
])
/
radian
outputString
+=
""" %s="%s" %s="%s" """
%
(
amplitudeAttributeName
,
str
(
amplitude
),
angleAttributeName
,
str
(
angle
)
)
startIndex
+=
3
outputString
+=
"/>"
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaTorsionForce>
\n
"
)
#=============================================================================================
# AmoebaPiTorsionForce
piTorsionUnit
=
1.0
outputString
=
""" <AmoebaPiTorsionForce piTorsionUnit="%s">"""
%
(
piTorsionUnit
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
piTorsions
=
forces
[
'pitors'
]
conversion
=
4.184
*
piTorsionUnit
for
piTorsion
in
piTorsions
:
k
=
float
(
piTorsion
[
2
])
*
conversion
outputString
=
""" <PiTorsion class1="%s" class2="%s" k="%s" />"""
%
(
piTorsion
[
0
],
piTorsion
[
1
],
str
(
k
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaPiTorsionForce>
\n
"
)
#=============================================================================================
# AmoebaStretchBendForce
stretchBendUnit
=
1.0
outputString
=
""" <AmoebaStretchBendForce stretchBendUnit="%s">"""
%
(
stretchBendUnit
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
conversion
=
41.84
/
radian
stretchBends
=
forces
[
'strbnd'
]
for
stretchBend
in
stretchBends
:
k1
=
float
(
stretchBend
[
3
])
*
conversion
k2
=
float
(
stretchBend
[
4
])
*
conversion
outputString
=
""" <StretchBend class1="%s" class2="%s" class3="%s" k1="%s" k2="%s" />"""
%
(
stretchBend
[
0
],
stretchBend
[
1
],
stretchBend
[
2
],
str
(
k1
),
str
(
k2
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
"</AmoebaStretchBendForce>
\n
"
)
#=============================================================================================
# AmoebaTorsionTorsionForce
torsionTorsionUnit
=
1.0
outputString
=
""" <AmoebaTorsionTorsionForce >"""
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
conversion
=
41.84
/
radian
torsionTorsions
=
forces
[
'tortors'
]
for
(
index
,
torsionTorsion
)
in
enumerate
(
torsionTorsions
):
torInfo
=
torsionTorsion
[
0
]
grid
=
torsionTorsion
[
1
]
outputString
=
""" <TorsionTorsion class1="%s" class2="%s" class3="%s" class4="%s" class5="%s" grid="%s" nx="%s" ny="%s" />"""
%
(
torInfo
[
0
],
torInfo
[
1
],
torInfo
[
2
],
torInfo
[
3
],
torInfo
[
4
],
str
(
index
),
torInfo
[
5
],
torInfo
[
6
]
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
for
(
index
,
torsionTorsion
)
in
enumerate
(
torsionTorsions
):
torInfo
=
torsionTorsion
[
0
]
grid
=
torsionTorsion
[
1
]
outputString
=
""" <TorsionTorsionGrid grid="%s" nx="%s" ny="%s" >"""
%
(
str
(
index
),
torInfo
[
5
],
torInfo
[
6
]
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
for
(
gridIndex
,
gridEntry
)
in
enumerate
(
grid
):
print
"Gxx %d %s"
%
(
gridIndex
,
str
(
gridEntry
)
)
if
(
len
(
gridEntry
)
>
5
):
f
=
float
(
gridEntry
[
2
]
)
*
4.184
fx
=
float
(
gridEntry
[
3
]
)
*
4.184
fy
=
float
(
gridEntry
[
4
]
)
*
4.184
fxy
=
float
(
gridEntry
[
5
]
)
*
4.184
outputString
=
""" <Grid angle1="%s" angle2="%s" f="%s" fx="%s" fy="%s" fxy="%s" />"""
%
(
gridEntry
[
0
],
gridEntry
[
1
],
str
(
f
),
str
(
fx
),
str
(
fy
),
str
(
fxy
)
)
tinkerXmlFile
.
write
(
" %s
\n
"
%
(
outputString
)
)
elif
(
len
(
gridEntry
)
>
2
):
f
=
float
(
gridEntry
[
2
]
)
*
4.184
outputString
=
""" <Grid angle1="%s" angle2="%s" f="%s" />"""
%
(
gridEntry
[
0
],
gridEntry
[
1
],
str
(
f
)
)
tinkerXmlFile
.
write
(
" %s
\n
"
%
(
outputString
)
)
outputString
=
'</TorsionTorsionGrid >'
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
"</AmoebaTorsionTorsionForce>
\n
"
)
#=============================================================================================
# AmoebaVdwForce
outputString
=
""" <AmoebaVdwForce type="%s" radiusrule="%s" radiustype="%s" radiussize="%s" epsilonrule="%s" vdw-13-scale="%s" vdw-14-scale="%s" vdw-15-scale="%s" >"""
%
(
scalars
[
'vdwtype'
],
scalars
[
'radiusrule'
],
scalars
[
'radiustype'
],
scalars
[
'radiussize'
],
scalars
[
'epsilonrule'
],
scalars
[
'vdw-13-scale'
],
scalars
[
'vdw-14-scale'
],
scalars
[
'vdw-15-scale'
]
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
vdws
=
forces
[
'vdw'
]
for
vdw
in
vdws
:
sigma
=
float
(
vdw
[
1
])
*
0.1
epsilon
=
float
(
vdw
[
2
])
*
4.184
if
(
len
(
vdw
)
>
3
):
reduction
=
vdw
[
3
]
else
:
reduction
=
1.0
outputString
=
""" <Vdw class="%s" sigma="%s" epsilon="%s" reduction="%s" /> """
%
(
vdw
[
0
],
str
(
sigma
),
str
(
epsilon
),
str
(
reduction
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaVdwForce>
\n
"
)
#=============================================================================================
# AmoebaMultipoleForce
scalarList
=
dict
()
scalarList
[
'mpole12Scale'
]
=
recognizedScalars
[
'mpole-12-scale'
]
scalarList
[
'mpole13Scale'
]
=
recognizedScalars
[
'mpole-13-scale'
]
scalarList
[
'mpole14Scale'
]
=
recognizedScalars
[
'mpole-14-scale'
]
scalarList
[
'mpole15Scale'
]
=
recognizedScalars
[
'mpole-15-scale'
]
scalarList
[
'polar12Scale'
]
=
recognizedScalars
[
'polar-12-scale'
]
scalarList
[
'polar13Scale'
]
=
recognizedScalars
[
'polar-13-scale'
]
scalarList
[
'polar14Scale'
]
=
recognizedScalars
[
'polar-14-scale'
]
scalarList
[
'polar15Scale'
]
=
recognizedScalars
[
'polar-15-scale'
]
scalarList
[
'polar14Intra'
]
=
recognizedScalars
[
'polar-14-intra'
]
scalarList
[
'direct11Scale'
]
=
recognizedScalars
[
'direct-11-scale'
]
scalarList
[
'direct12Scale'
]
=
recognizedScalars
[
'direct-12-scale'
]
scalarList
[
'direct13Scale'
]
=
recognizedScalars
[
'direct-13-scale'
]
scalarList
[
'direct14Scale'
]
=
recognizedScalars
[
'direct-14-scale'
]
scalarList
[
'mutual11Scale'
]
=
recognizedScalars
[
'mutual-11-scale'
]
scalarList
[
'mutual12Scale'
]
=
recognizedScalars
[
'mutual-12-scale'
]
scalarList
[
'mutual13Scale'
]
=
recognizedScalars
[
'mutual-13-scale'
]
scalarList
[
'mutual14Scale'
]
=
recognizedScalars
[
'mutual-14-scale'
]
outputString
=
""" <AmoebaMultipoleForce """
for
key
in
sorted
(
scalarList
.
keys
()
):
outputString
+=
""" %s="%s" """
%
(
key
,
scalarList
[
key
]
)
outputString
+=
""" > """
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
multipoleArray
=
forces
[
'multipole'
]
bohr
=
0.52917720859
dipoleConversion
=
0.1
*
bohr
quadrupoleConversion
=
0.01
*
bohr
*
bohr
/
3.0
for
multipoleInfo
in
multipoleArray
:
axisInfo
=
multipoleInfo
[
0
]
multipoles
=
multipoleInfo
[
1
]
outputString
=
""" <Multipole type="%s" """
%
(
axisInfo
[
0
]
)
axisInfoLen
=
len
(
axisInfo
)
if
(
axisInfoLen
>
1
):
outputString
+=
"""kz="%s" """
%
(
axisInfo
[
1
]
)
if
(
axisInfoLen
>
2
):
outputString
+=
"""kx="%s" """
%
(
axisInfo
[
2
]
)
if
(
axisInfoLen
>
3
):
outputString
+=
"""ky="%s" """
%
(
axisInfo
[
3
]
)
outputString
+=
"""c0="%s" d1="%s" d2="%s" d3="%s" q11="%s" q21="%s" q22="%s" q31="%s" q32="%s" q33="%s" """
%
(
multipoles
[
0
],
str
(
dipoleConversion
*
float
(
multipoles
[
1
])
),
str
(
dipoleConversion
*
float
(
multipoles
[
2
])),
str
(
dipoleConversion
*
float
(
multipoles
[
3
])),
str
(
quadrupoleConversion
*
float
(
multipoles
[
4
])
),
str
(
quadrupoleConversion
*
float
(
multipoles
[
5
])),
str
(
quadrupoleConversion
*
float
(
multipoles
[
6
])),
str
(
quadrupoleConversion
*
float
(
multipoles
[
7
])
),
str
(
quadrupoleConversion
*
float
(
multipoles
[
8
])),
str
(
quadrupoleConversion
*
float
(
multipoles
[
9
]))
)
outputString
+=
"/>"
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
polarizeArray
=
forces
[
'polarize'
]
polarityConversion
=
0.001
m
=
{}
for
polarize
in
polarizeArray
:
m
[
polarize
[
0
]]
=
[]
outputString
=
""" <Polarize type="%s" polarizability="%s" thole="%s" """
%
(
polarize
[
0
],
str
(
polarityConversion
*
float
(
polarize
[
1
])),
polarize
[
2
]
)
for
ii
in
range
(
3
,
len
(
polarize
)
):
outputString
+=
"""pgrp%d="%s" """
%
(
ii
-
2
,
polarize
[
ii
])
m
[
polarize
[
0
]].
append
(
polarize
[
ii
])
outputString
+=
"/>"
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
print
m
[
polarize
[
0
]]
for
t
in
sorted
(
m
):
for
k
in
m
[
t
]:
if
t
not
in
m
[
k
]:
print
t
,
k
tinkerXmlFile
.
write
(
" </AmoebaMultipoleForce>
\n
"
)
#=============================================================================================
# AmoebaGeneralizedKirkwoodForce
solventDielectric
=
78.3
soluteDielectric
=
1.0
includeCavityTerm
=
1
probeRadius
=
0.14
surfaceAreaFactor
=
-
6.0
*
3.1415926535
*
0.0216
*
1000.0
*
0.4184
outputString
=
""" <AmoebaGeneralizedKirkwoodForce solventDielectric="%s" soluteDielectric="%s" includeCavityTerm="%s" probeRadius="%s" surfaceAreaFactor="%s">"""
%
(
str
(
solventDielectric
),
str
(
soluteDielectric
),
str
(
includeCavityTerm
),
str
(
probeRadius
),
str
(
surfaceAreaFactor
)
)
gkXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
# radii are set in forcefield.py
for
type
in
sorted
(
atomTypes
):
print
"atoom type=%s %s"
%
(
str
(
type
),
str
(
atomTypes
[
type
])
)
for
type
in
sorted
(
bioTypes
):
print
"bio type=%s %s"
%
(
str
(
type
),
str
(
bioTypes
[
type
])
)
multipoleArray
=
forces
[
'multipole'
]
for
multipoleInfo
in
multipoleArray
:
axisInfo
=
multipoleInfo
[
0
]
multipoles
=
multipoleInfo
[
1
]
type
=
int
(
axisInfo
[
0
])
shct
=
0.8
if
(
type
in
atomTypes
):
element
=
atomTypes
[
type
][
1
]
if
(
element
==
'H'
):
shct
=
0.85
elif
(
element
==
'C'
):
shct
=
0.72
elif
(
element
==
'N'
):
shct
=
0.79
elif
(
element
==
'O'
):
shct
=
0.85
elif
(
element
==
'F'
):
shct
=
0.88
elif
(
element
==
'P'
):
shct
=
0.86
elif
(
element
==
'S'
):
shct
=
0.96
elif
(
element
==
'Fe'
):
shct
=
0.88
else
:
print
"Warning no overlap scale factor for type=%d element=%s"
%
(
type
,
element
)
else
:
print
"Warning no overlap scale factor for type=%d "
%
(
type
)
outputString
=
""" <GeneralizedKirkwood type="%s" charge="%s" shct="%s" /> """
%
(
axisInfo
[
0
],
multipoles
[
0
],
str
(
shct
)
)
gkXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
gkXmlFile
.
write
(
" </AmoebaGeneralizedKirkwoodForce>
\n
"
)
#=============================================================================================
# AmoebaWcaDispersionForce
epso
=
0.1100
epsh
=
0.0135
rmino
=
1.7025
rminh
=
1.3275
awater
=
0.033428
slevy
=
1.0
dispoff
=
0.26
shctd
=
0.81
outputString
=
""" <AmoebaWcaDispersionForce epso="%s" epsh="%s" rmino="%s" rminh="%s" awater="%s" slevy="%s" dispoff="%s" shctd="%s" >"""
%
(
str
(
epso
*
4.184
),
str
(
epsh
*
4.184
),
str
(
rmino
*
0.1
),
str
(
rminh
*
0.1
),
str
(
1000.0
*
awater
),
str
(
slevy
),
str
(
0.1
*
dispoff
),
str
(
shctd
)
)
gkXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
vdws
=
forces
[
'vdw'
]
convert
=
0.1
if
(
scalars
[
'radiustype'
]
==
'SIGMA'
):
convert
*=
1.122462048309372
if
(
scalars
[
'radiussize'
]
==
'DIAMETER'
):
convert
*=
0.5
for
vdw
in
vdws
:
sigma
=
float
(
vdw
[
1
])
sigma
*=
convert
epsilon
=
float
(
vdw
[
2
])
*
4.184
outputString
=
""" <WcaDispersion class="%s" radius="%s" epsilon="%s" /> """
%
(
vdw
[
0
],
str
(
sigma
),
str
(
epsilon
)
)
gkXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
gkXmlFile
.
write
(
" </AmoebaWcaDispersionForce>
\n
"
)
#=============================================================================================
# AmoebaUreyBradleyForce
cubic
=
0.0
quartic
=
0.0
outputString
=
""" <AmoebaUreyBradleyForce cubic="%s" quartic="%s" >"""
%
(
str
(
cubic
),
str
(
quartic
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
ubs
=
forces
[
'ureybrad'
]
for
ub
in
ubs
:
k
=
float
(
ub
[
3
])
*
4.184
*
100.0
d
=
float
(
ub
[
4
])
*
0.1
outputString
=
""" <UreyBradley class1="%s" class2="%s" class3="%s" k="%s" d="%s" /> """
%
(
ub
[
0
],
ub
[
1
],
ub
[
2
],
str
(
k
),
str
(
d
)
)
tinkerXmlFile
.
write
(
"%s
\n
"
%
(
outputString
)
)
tinkerXmlFile
.
write
(
" </AmoebaUreyBradleyForce>
\n
"
)
#=============================================================================================
tinkerXmlFile
.
write
(
"</ForceField>
\n
"
)
gkXmlFile
.
write
(
"</ForceField>
\n
"
)
tinkerXmlFile
.
close
()
gkXmlFile
.
close
()
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