Source code for pysimm.forcefield.forcefield

# ******************************************************************************
# pysimm.forcefield module
# ******************************************************************************
#
# ******************************************************************************
# License
# ******************************************************************************
# The MIT License (MIT)
#
# Copyright (c) 2016 Michael E. Fortunato, Coray M. Colina
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os
import json
from xml.dom import minidom
from xml.etree import ElementTree as Et
from itertools import permutations, combinations

from pysimm import error_print
from pysimm import warning_print
from pysimm import debug_print
import gasteiger
from pysimm.utils import PysimmError, Item, ItemContainer, compare
from pysimm.system import ParticleType, BondType, AngleType
from pysimm.system import Angle, Dihedral, Improper
from pysimm.system import DihedralType, ImproperType


element_names_by_mass = {1: 'H', 4: 'He', 7: 'Li', 9: 'Be', 11: 'B', 12: 'C',
                         14: 'N', 16: 'O', 19: 'F', 20: 'Ne', 23: 'Na',
                         24: 'Mg', 27: 'Al', 28: 'Si', 31: 'P', 32: 'S',
                         35: 'Cl', 39: 'K', 40: 'Ca', 80: 'Br', 127: 'I'}


[docs]class Forcefield(object): """pysimm.forcefield.Forcefield Base Forcefield class definition. Initialize with force field xml file. Attributes: ff_class: force field class (1 or 2) ff_name: force field name particle_types: :class:`~pysimm.utils.ItemContainer` for particle_types bond_types: :class:`~pysimm.utils.ItemContainer` for bond_types angle_types: :class:`~pysimm.utils.ItemContainer` for angle_types dihedral_types: :class:`~pysimm.utils.ItemContainer` for dihedral_types improper_types: :class:`~pysimm.utils.ItemContainer` for improper_types """ def __init__(self, file_=None, format=None): self.ff_class = 0 self.ff_name = '' self.pair_style = None self.particle_types = ItemContainer() self.bond_style = None self.bond_types = ItemContainer() self.angle_style = None self.angle_types = ItemContainer() self.dihedral_style = None self.dihedral_types = ItemContainer() self.improper_style = None self.improper_types = ItemContainer() if file_: if format == 'json' or file_.split('.')[-1] == 'json': self.from_json(file_) elif format == 'xml' or file_.split('.')[-1] == 'xml': self.from_xml(file_)
[docs] def from_xml(self, file_): tree = Et.parse(file_) root = tree.getroot() ptypes = root.find('ParticleTypes') btypes = root.find('BondTypes') atypes = root.find('AngleTypes') dtypes = root.find('DihedralTypes') itypes = root.find('ImproperTypes') for ptype in ptypes: pt = ParticleType() for k, v in ptype.attrib.items(): try: v = float(v) except ValueError: pass setattr(pt, k, v) pt.tag = pt.name self.particle_types.add(pt) for btype in btypes: bt = BondType() for k, v in btype.attrib.items(): try: v = float(v) except ValueError: pass setattr(bt, k, v) bt.tag = bt.name bt.rname = ','.join(reversed(bt.name.split(','))) self.bond_types.add(bt) for atype in atypes: at = AngleType() for k, v in atype.attrib.items(): try: v = float(v) except ValueError: pass setattr(at, k, v) at.tag = at.name at.rname = ','.join(reversed(at.name.split(','))) self.angle_types.add(at) for dtype in dtypes: dt = DihedralType() for k, v in dtype.attrib.items(): if k != 'd' and k != 'n': try: v = float(v) except ValueError: pass elif k == 'd' or k == 'n': try: v = int(v) except ValueError: pass setattr(dt, k, v) dt.tag = dt.name dt.rname = ','.join(reversed(dt.name.split(','))) self.dihedral_types.add(dt) for itype in itypes: it = ImproperType() for k, v in itype.attrib.items(): try: v = float(v) except ValueError: pass setattr(it, k, v) it.tag = it.name it.rname = ','.join(reversed(it.name.split(','))) self.improper_types.add(it)
[docs] def from_json(self, json_file): with file(json_file) as f: j = json.loads(f.read()) self.ff_name = j.get('ff_name') self.ff_class = j.get('ff_class') self.pair_style = j.get('pair_style') self.bond_style = j.get('bond_style') self.angle_style = j.get('angle_style') self.dihedral_style = j.get('dihedral_style') self.improper_style = j.get('improper_style') for pt in j.get('particle_types'): self.particle_types.add(ParticleType(**pt)) for bt in j.get('bond_types'): self.bond_types.add(BondType(**bt)) for at in j.get('angle_types'): self.angle_types.add(AngleType(**at)) for dt in j.get('dihedral_types'): self.dihedral_types.add(DihedralType(**dt)) for it in j.get('improper_types'): self.improper_types.add(ImproperType(**it))
[docs] def write_json(self, out): f = {} f['ff_name'] = self.ff_name f['ff_class'] = self.ff_class f['pair_style'] = self.pair_style f['bond_style'] = self.bond_style f['angle_style'] = self.angle_style f['dihedral_style'] = self.dihedral_style f['improper_style'] = self.improper_style f['particle_types'] = [vars(pt) for pt in self.particle_types] f['bond_types'] = [vars(bt) for bt in self.bond_types] f['angle_types'] = [vars(at) for at in self.angle_types] f['dihedral_types'] = [vars(dt) for dt in self.dihedral_types] f['improper_types'] = [vars(it) for it in self.improper_types] with file(out, 'w') as _file: _file.write(json.dumps(f, indent=4))
[docs] def write_xml(self, out): """pysimm.forcefield.Forcefield.write Write Forcefield object to xml format. Args: out: file name to write Returns: None """ ff_elem = Et.Element('Forcefield') ff_elem.set('name', self.ff_name) ff_elem.set('class', self.ff_class) ptypes = Et.SubElement(ff_elem, 'ParticleTypes') for pt in self.particle_types: ptype = Et.SubElement(ptypes, 'Type') for k, v in vars(pt).items(): ptype.set(k, str(v)) btypes = Et.SubElement(ff_elem, 'BondTypes') for bt in self.bond_types: btype = Et.SubElement(btypes, 'Type') for k, v in vars(bt).items(): btype.set(k, str(v)) atypes = Et.SubElement(ff_elem, 'AngleTypes') for at in self.angle_types: atype = Et.SubElement(atypes, 'Type') for k, v in vars(at).items(): atype.set(k, str(v)) dtypes = Et.SubElement(ff_elem, 'DihedralTypes') for dt in self.dihedral_types: dtype = Et.SubElement(dtypes, 'Type') for k, v in vars(dt).items(): dtype.set(k, str(v)) itypes = Et.SubElement(ff_elem, 'ImproperTypes') for it in self.improper_types: itype = Et.SubElement(itypes, 'Type') for k, v in vars(it).items(): itype.set(k, str(v)) with open(out, 'w') as f: f.write( minidom.parseString(Et.tostring(ff_elem, 'utf-8')).toprettyxml( indent=" "))