"platforms/cuda/src/CudaIntegrationUtilities.cpp" did not exist on "6e842d8ce9dff25183f89bd7377a6ed93a9a5bff"
Commit 2781f518 authored by peastman's avatar peastman
Browse files

Added scripts for generating force field XML files

parent 89b4a7e4
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>")
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>"
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>')
#=============================================================================================
# 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 "\nResidue %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()
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