Commit 0b5562ac authored by Rafal P. Wiewiora's avatar Rafal P. Wiewiora
Browse files

take everything out to a function, RBTorsion and CustomTorsion now use...

take everything out to a function, RBTorsion and CustomTorsion now use ordering=charmm as their default
parent 79261f4c
...@@ -1736,10 +1736,57 @@ def _createResidueTemplate(residue): ...@@ -1736,10 +1736,57 @@ def _createResidueTemplate(residue):
template.addExternalBondByName(atom2.name) template.addExternalBondByName(atom2.name)
return template return template
def _matchAmberImproper(types, torsion, data, hasWildcard): def _matchImproper(data, torsion, generator):
t2 = types[0] type1 = data.atomType[data.atoms[torsion[0]]]
t3 = types[1] type2 = data.atomType[data.atoms[torsion[1]]]
t4 = types[2] type3 = data.atomType[data.atoms[torsion[2]]]
type4 = data.atomType[data.atoms[torsion[3]]]
match = None
for tordef in generator.improper:
types1 = tordef.types1
types2 = tordef.types2
types3 = tordef.types3
types4 = tordef.types4
hasWildcard = (wildcard in (types1, types2, types3, types4))
if match is not None and hasWildcard:
# Prefer specific definitions over ones with wildcards
continue
if type1 in types1:
for (t2, t3, t4) in itertools.permutations(((type2, 1), (type3, 2), (type4, 3))):
if t2[0] in types2 and t3[0] in types3 and t4[0] in types4:
if tordef.ordering == 'default':
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1 = torsion[t2[1]]
a2 = torsion[t3[1]]
e1 = data.atoms[a1].element
e2 = data.atoms[a2].element
if e1 == e2 and a1 > a2:
(a1, a2) = (a2, a1)
elif e1 != elem.carbon and (e2 == elem.carbon or e1.mass < e2.mass):
(a1, a2) = (a2, a1)
match = (a1, a2, torsion[0], torsion[t4[1]], tordef)
break
elif tordef.ordering == 'charmm':
if hasWildcard:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1 = torsion[t2[1]]
a2 = torsion[t3[1]]
e1 = data.atoms[a1].element
e2 = data.atoms[a2].element
if e1 == e2 and a1 > a2:
(a1, a2) = (a2, a1)
elif e1 != elem.carbon and (e2 == elem.carbon or e1.mass < e2.mass):
(a1, a2) = (a2, a1)
match = (a1, a2, torsion[0], torsion[t4[1]], tordef)
else:
# There are no wildcards, so the order is unambiguous.
match = (torsion[0], torsion[t2[1]], torsion[t3[1]], torsion[t4[1]], tordef)
break
elif tordef.ordering == 'amber':
# topology atom indexes # topology atom indexes
a2 = torsion[t2[1]] a2 = torsion[t2[1]]
a3 = torsion[t3[1]] a3 = torsion[t3[1]]
...@@ -1787,6 +1834,7 @@ def _matchAmberImproper(types, torsion, data, hasWildcard): ...@@ -1787,6 +1834,7 @@ def _matchAmberImproper(types, torsion, data, hasWildcard):
if r2 > r3 or (r2 == r3 and ta2 > ta3): if r2 > r3 or (r2 == r3 and ta2 > ta3):
(a2, a3) = (a3, a2) (a2, a3) = (a3, a2)
match = (a2, a3, torsion[0], a4, tordef) match = (a2, a3, torsion[0], a4, tordef)
break
return match return match
# The following classes are generators that know how to create Force subclasses and add them to a System that is being # The following classes are generators that know how to create Force subclasses and add them to a System that is being
...@@ -2022,40 +2070,7 @@ class PeriodicTorsionGenerator(object): ...@@ -2022,40 +2070,7 @@ class PeriodicTorsionGenerator(object):
if match.k[i] != 0: if match.k[i] != 0:
force.addTorsion(torsion[0], torsion[1], torsion[2], torsion[3], match.periodicity[i], match.phase[i], match.k[i]) force.addTorsion(torsion[0], torsion[1], torsion[2], torsion[3], match.periodicity[i], match.phase[i], match.k[i])
for torsion in data.impropers: for torsion in data.impropers:
type1 = data.atomType[data.atoms[torsion[0]]] match = _matchImproper(data, torsion, self)
type2 = data.atomType[data.atoms[torsion[1]]]
type3 = data.atomType[data.atoms[torsion[2]]]
type4 = data.atomType[data.atoms[torsion[3]]]
match = None
for tordef in self.improper:
types1 = tordef.types1
types2 = tordef.types2
types3 = tordef.types3
types4 = tordef.types4
hasWildcard = (wildcard in (types1, types2, types3, types4))
if match is not None and hasWildcard:
# Prefer specific definitions over ones with wildcards
continue
if type1 in types1:
for (t2, t3, t4) in itertools.permutations(((type2, 1), (type3, 2), (type4, 3))):
if t2[0] in types2 and t3[0] in types3 and t4[0] in types4:
if tordef.ordering == 'default':
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1 = torsion[t2[1]]
a2 = torsion[t3[1]]
e1 = data.atoms[a1].element
e2 = data.atoms[a2].element
if e1 == e2 and a1 > a2:
(a1, a2) = (a2, a1)
elif e1 != elem.carbon and (e2 == elem.carbon or e1.mass < e2.mass):
(a1, a2) = (a2, a1)
match = (a1, a2, torsion[0], torsion[t4[1]], tordef)
break
elif tordef.ordering == 'amber':
match = _matchAmberImproper((t2, t3, t4), torsion, data, hasWildcard)
break
if match is not None: if match is not None:
(a1, a2, a3, a4, tordef) = match (a1, a2, a3, a4, tordef) = match
for i in range(len(tordef.phase)): for i in range(len(tordef.phase)):
...@@ -2069,13 +2084,13 @@ parsers["PeriodicTorsionForce"] = PeriodicTorsionGenerator.parseElement ...@@ -2069,13 +2084,13 @@ parsers["PeriodicTorsionForce"] = PeriodicTorsionGenerator.parseElement
class RBTorsion(object): class RBTorsion(object):
"""An RBTorsion records the information for a Ryckaert-Bellemans torsion definition.""" """An RBTorsion records the information for a Ryckaert-Bellemans torsion definition."""
def __init__(self, types, c, ordering='default'): def __init__(self, types, c, ordering='charmm'):
self.types1 = types[0] self.types1 = types[0]
self.types2 = types[1] self.types2 = types[1]
self.types3 = types[2] self.types3 = types[2]
self.types4 = types[3] self.types4 = types[3]
self.c = c self.c = c
if ordering == 'default' or ordering == 'amber': if ordering in ['default', 'charmm', 'amber']:
self.ordering = ordering self.ordering = ordering
else: else:
raise ValueError('Illegal ordering type for RBTorsion (%s,%s,%s,%s)' % (types[0], types[1], types[2], types[3])) raise ValueError('Illegal ordering type for RBTorsion (%s,%s,%s,%s)' % (types[0], types[1], types[2], types[3]))
...@@ -2138,44 +2153,7 @@ class RBTorsionGenerator(object): ...@@ -2138,44 +2153,7 @@ class RBTorsionGenerator(object):
if match is not None: if match is not None:
force.addTorsion(torsion[0], torsion[1], torsion[2], torsion[3], match.c[0], match.c[1], match.c[2], match.c[3], match.c[4], match.c[5]) force.addTorsion(torsion[0], torsion[1], torsion[2], torsion[3], match.c[0], match.c[1], match.c[2], match.c[3], match.c[4], match.c[5])
for torsion in data.impropers: for torsion in data.impropers:
type1 = data.atomType[data.atoms[torsion[0]]] match = _matchImproper(data, torsion, self)
type2 = data.atomType[data.atoms[torsion[1]]]
type3 = data.atomType[data.atoms[torsion[2]]]
type4 = data.atomType[data.atoms[torsion[3]]]
match = None
for tordef in self.improper:
types1 = tordef.types1
types2 = tordef.types2
types3 = tordef.types3
types4 = tordef.types4
hasWildcard = (wildcard in (types1, types2, types3, types4))
if match is not None and hasWildcard:
# Prefer specific definitions over ones with wildcards
continue
if type1 in types1:
for (t2, t3, t4) in itertools.permutations(((type2, 1), (type3, 2), (type4, 3))):
if t2[0] in types2 and t3[0] in types3 and t4[0] in types4:
if tordef.ordering == 'default':
if hasWildcard:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1 = torsion[t2[1]]
a2 = torsion[t3[1]]
e1 = data.atoms[a1].element
e2 = data.atoms[a2].element
if e1 == e2 and a1 > a2:
(a1, a2) = (a2, a1)
elif e1 != elem.carbon and (e2 == elem.carbon or e1.mass < e2.mass):
(a1, a2) = (a2, a1)
match = (a1, a2, torsion[0], torsion[t4[1]], tordef)
else:
# There are no wildcards, so the order is unambiguous.
match = (torsion[0], torsion[t2[1]], torsion[t3[1]], torsion[t4[1]], tordef)
break
elif tordef.ordering == 'amber':
match = _matchAmberImproper((t2, t3, t4), torsion, data, hasWildcard)
break
if match is not None: if match is not None:
(a1, a2, a3, a4, tordef) = match (a1, a2, a3, a4, tordef) = match
force.addTorsion(a1, a2, a3, a4, tordef.c[0], tordef.c[1], tordef.c[2], tordef.c[3], tordef.c[4], tordef.c[5]) force.addTorsion(a1, a2, a3, a4, tordef.c[0], tordef.c[1], tordef.c[2], tordef.c[3], tordef.c[4], tordef.c[5])
...@@ -2636,13 +2614,13 @@ parsers["CustomAngleForce"] = CustomAngleGenerator.parseElement ...@@ -2636,13 +2614,13 @@ parsers["CustomAngleForce"] = CustomAngleGenerator.parseElement
class CustomTorsion(object): class CustomTorsion(object):
"""A CustomTorsion records the information for a custom torsion definition.""" """A CustomTorsion records the information for a custom torsion definition."""
def __init__(self, types, paramValues, ordering='default'): def __init__(self, types, paramValues, ordering='charmm'):
self.types1 = types[0] self.types1 = types[0]
self.types2 = types[1] self.types2 = types[1]
self.types3 = types[2] self.types3 = types[2]
self.types4 = types[3] self.types4 = types[3]
self.paramValues = paramValues self.paramValues = paramValues
if ordering == 'default' or ordering == 'amber': if ordering in ['default', 'charmm', 'amber']:
self.ordering = ordering self.ordering = ordering
else: else:
raise ValueError('Illegal ordering type for CustomTorsion (%s,%s,%s,%s)' % (types[0], types[1], types[2], types[3])) raise ValueError('Illegal ordering type for CustomTorsion (%s,%s,%s,%s)' % (types[0], types[1], types[2], types[3]))
...@@ -2707,44 +2685,7 @@ class CustomTorsionGenerator(object): ...@@ -2707,44 +2685,7 @@ class CustomTorsionGenerator(object):
if match is not None: if match is not None:
force.addTorsion(torsion[0], torsion[1], torsion[2], torsion[3], match.paramValues) force.addTorsion(torsion[0], torsion[1], torsion[2], torsion[3], match.paramValues)
for torsion in data.impropers: for torsion in data.impropers:
type1 = data.atomType[data.atoms[torsion[0]]] match = _matchImproper(data, torsion, self)
type2 = data.atomType[data.atoms[torsion[1]]]
type3 = data.atomType[data.atoms[torsion[2]]]
type4 = data.atomType[data.atoms[torsion[3]]]
match = None
for tordef in self.improper:
types1 = tordef.types1
types2 = tordef.types2
types3 = tordef.types3
types4 = tordef.types4
hasWildcard = (wildcard in (types1, types2, types3, types4))
if match is not None and hasWildcard:
# Prefer specific definitions over ones with wildcards
continue
if type1 in types1:
for (t2, t3, t4) in itertools.permutations(((type2, 1), (type3, 2), (type4, 3))):
if t2[0] in types2 and t3[0] in types3 and t4[0] in types4:
if tordef.ordering == 'default':
if hasWildcard:
# Workaround to be more consistent with AMBER. It uses wildcards to define most of its
# impropers, which leaves the ordering ambiguous. It then follows some bizarre rules
# to pick the order.
a1 = torsion[t2[1]]
a2 = torsion[t3[1]]
e1 = data.atoms[a1].element
e2 = data.atoms[a2].element
if e1 == e2 and a1 > a2:
(a1, a2) = (a2, a1)
elif e1 != elem.carbon and (e2 == elem.carbon or e1.mass < e2.mass):
(a1, a2) = (a2, a1)
match = (a1, a2, torsion[0], torsion[t4[1]], tordef)
else:
# There are no wildcards, so the order is unambiguous.
match = (torsion[0], torsion[t2[1]], torsion[t3[1]], torsion[t4[1]], tordef)
break
elif tordef.ordering == 'amber':
match = _matchAmberImproper((t2, t3, t4), torsion, data, hasWildcard)
break
if match is not None: if match is not None:
(a1, a2, a3, a4, tordef) = match (a1, a2, a3, a4, tordef) = match
force.addTorsion(a1, a2, a3, a4, tordef.paramValues) force.addTorsion(a1, a2, a3, a4, tordef.paramValues)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment