Commit 004db14a authored by Rafal P. Wiewiora's avatar Rafal P. Wiewiora
Browse files

read all ffxmls together by section, rather than all sections in one file first

parent d2725cd3
...@@ -120,88 +120,99 @@ class ForceField(object): ...@@ -120,88 +120,99 @@ class ForceField(object):
self._forces = [] self._forces = []
self._scripts = [] self._scripts = []
self._templateGenerators = [] self._templateGenerators = []
for file in files: self.loadFile(files)
self.loadFile(file)
def loadFile(self, file): def loadFile(self, files):
"""Load an XML file and add the definitions from it to this ForceField. """Load an XML file and add the definitions from it to this ForceField.
Parameters Parameters
---------- ----------
file : string or file files : string or file or tuple
An XML file containing force field definitions. It may be either an An XML file or tuple of XML files containing force field definitions.
absolute file path, a path relative to the current working Each entry may be either an absolute file path, a path relative to the current working
directory, a path relative to this module's data subdirectory (for directory, a path relative to this module's data subdirectory (for
built in force fields), or an open file-like object with a read() built in force fields), or an open file-like object with a read()
method from which the forcefield XML data can be loaded. method from which the forcefield XML data can be loaded.
""" """
try:
# this handles either filenames or open file-like objects
tree = etree.parse(file)
except IOError:
tree = etree.parse(os.path.join(os.path.dirname(__file__), 'data', file))
except Exception as e:
# Fail with an error message about which file could not be read.
# TODO: Also handle case where fallback to 'data' directory encounters problems,
# but this is much less worrisome because we control those files.
msg = str(e) + '\n'
if hasattr(file, 'name'):
filename = file.name
else:
filename = str(file)
msg += "ForceField.loadFile() encountered an error reading file '%s'\n" % filename
raise Exception(msg)
root = tree.getroot() if not isinstance(files, tuple):
files = (files,)
trees = []
for file in files:
try:
# this handles either filenames or open file-like objects
tree = etree.parse(file)
except IOError:
tree = etree.parse(os.path.join(os.path.dirname(__file__), 'data', file))
except Exception as e:
# Fail with an error message about which file could not be read.
# TODO: Also handle case where fallback to 'data' directory encounters problems,
# but this is much less worrisome because we control those files.
msg = str(e) + '\n'
if hasattr(file, 'name'):
filename = file.name
else:
filename = str(file)
msg += "ForceField.loadFile() encountered an error reading file '%s'\n" % filename
raise Exception(msg)
trees.append(tree)
# Load the atom types. # Load the atom types.
if tree.getroot().find('AtomTypes') is not None: for tree in trees:
for type in tree.getroot().find('AtomTypes').findall('Type'): if tree.getroot().find('AtomTypes') is not None:
self.registerAtomType(type.attrib) for type in tree.getroot().find('AtomTypes').findall('Type'):
self.registerAtomType(type.attrib)
# Load the residue templates. # Load the residue templates.
if tree.getroot().find('Residues') is not None: for tree in trees:
for residue in root.find('Residues').findall('Residue'): if tree.getroot().find('Residues') is not None:
resName = residue.attrib['name'] for residue in tree.getroot().find('Residues').findall('Residue'):
template = ForceField._TemplateData(resName) resName = residue.attrib['name']
atomIndices = {} template = ForceField._TemplateData(resName)
for atom in residue.findall('Atom'): atomIndices = {}
params = {} for atom in residue.findall('Atom'):
for key in atom.attrib: params = {}
if key not in ('name', 'type'): for key in atom.attrib:
params[key] = _convertParameterToNumber(atom.attrib[key]) if key not in ('name', 'type'):
atomName = atom.attrib['name'] params[key] = _convertParameterToNumber(atom.attrib[key])
if atomName in atomIndices: atomName = atom.attrib['name']
raise ValueError('Residue '+resName+' contains multiple atoms named '+atomName) if atomName in atomIndices:
atomIndices[atomName] = len(template.atoms) raise ValueError('Residue '+resName+' contains multiple atoms named '+atomName)
typeName = atom.attrib['type'] atomIndices[atomName] = len(template.atoms)
template.atoms.append(ForceField._TemplateAtomData(atomName, typeName, self._atomTypes[typeName].element, params)) typeName = atom.attrib['type']
for site in residue.findall('VirtualSite'): template.atoms.append(ForceField._TemplateAtomData(atomName, typeName, self._atomTypes[typeName].element, params))
template.virtualSites.append(ForceField._VirtualSiteData(site, atomIndices)) for site in residue.findall('VirtualSite'):
for bond in residue.findall('Bond'): template.virtualSites.append(ForceField._VirtualSiteData(site, atomIndices))
if 'atomName1' in bond.attrib: for bond in residue.findall('Bond'):
template.addBondByName(bond.attrib['atomName1'], bond.attrib['atomName2']) if 'atomName1' in bond.attrib:
else: template.addBondByName(bond.attrib['atomName1'], bond.attrib['atomName2'])
template.addBond(int(bond.attrib['from']), int(bond.attrib['to'])) else:
for bond in residue.findall('ExternalBond'): template.addBond(int(bond.attrib['from']), int(bond.attrib['to']))
if 'atomName' in bond.attrib: for bond in residue.findall('ExternalBond'):
template.addExternalBondByName(bond.attrib['atomName']) if 'atomName' in bond.attrib:
else: template.addExternalBondByName(bond.attrib['atomName'])
template.addExternalBond(int(bond.attrib['from'])) else:
self.registerResidueTemplate(template) template.addExternalBond(int(bond.attrib['from']))
self.registerResidueTemplate(template)
# Load force definitions # Load force definitions
for child in root: for tree in trees:
if child.tag in parsers: for child in tree.getroot():
parsers[child.tag](child, self) if child.tag in parsers:
parsers[child.tag](child, self)
# Load scripts # Load scripts
for node in tree.getroot().findall('Script'): for tree in trees:
self.registerScript(node.text) for node in tree.getroot().findall('Script'):
self.registerScript(node.text)
def getGenerators(self): def getGenerators(self):
"""Get the list of all registered generators.""" """Get the list of all registered generators."""
......
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