Source code for parmed.tinker.system

"""
This module contains the following classes:

   TinkerAnalout - Reads the output from the "analyze" command

"""
from __future__ import print_function, absolute_import, division

from parmed.utils.six.moves import range
from parmed.exceptions import TinkerError
from parmed.tinker.topologyobjects import (AtomList, BondList, AngleList,
      StretchBendList, UreyBradleyList, OutOfPlaneBendList, OutOfPlaneDistList,
      TorsionAngleList, PiTorsionList, TorsionTorsionList, AtomicMultipoleList,
      DipolePolarizabilityList, TorsionTorsionGrid)

[docs]class TinkerAnalout(object): """ Reads the output of "analyze" to determine system parameters """ # Flags paired with the attributes in the pointers atom_inter_flags = {'Atoms in System' : 'natom', 'Pisystem Atoms' : 'norbit', 'Bond Stretches' : 'nbond', 'Conjugated Pi-Bonds' : 'nbpi', 'Angle Bends' : 'nangle', 'Stretch-Bends' : 'nstrbnd', 'Urey-Bradley' : 'nurey', 'Angle-Angles' : 'nangang', 'Out-of-Plane Bends' : 'nopbend', 'Out-of-Plane Distances' : 'nopdist', 'Improper Dihedrals' : 'niprop', 'Improper Torsions' : 'nitors', 'Torsional Angles' : 'ntors', 'Pi-Orbital Torsions' : 'npitors', 'Stretch-Torsions' : 'nstrtor', 'Torsion-Torsions' : 'ntortor', 'Atomic Partial Charges' : 'nion', 'Bond Dipole Moments' : 'ndipole', 'Polarizable Multipoles' : 'npole', 'Number of 1-2 Pairs' : 'pair12', 'Number of 1-3 Pairs' : 'pair13', 'Number of 1-4 Pairs' : 'pair14', 'Number of 1-5 Pairs' : 'pair15', } def __init__(self, fname=None): if fname is not None: self.read(fname)
[docs] def read(self, fname): """ Reads the analout file """ self.pointers = dict(natom=0, norbit=0, nbond=0, nbpi=0, nangle=0, nstrbnd=0, nurey=0, nangang=0, nopbend=0, nopdist=0, niprop=0, nitors=0, ntors=0, npitors=0, nstrtor=0, ntortor=0, nion=0, ndipole=0, npole=0, pair12=0, pair13=0, pair14=0, pair15=0) self.fname = fname f = open(self.fname, 'r') try: line = f.readline() # Look for the TINKER watermark while True: if not line: raise TinkerError('Could not find the TINKER watermark ' 'in %s' % fname) if line.lstrip().startswith('### TINKER'): break line = f.readline() # Get the numbers of all parameters while not line.lstrip().startswith( 'Total Numbers of Atoms and Interactions'): if not line: raise TinkerError('Could not find the atom/ixn count') line = f.readline() # Eat the next line f.readline() line = f.readline() # Get all of the pointers while line.strip(): try: key = TinkerAnalout.atom_inter_flags[line[:27].strip()] except KeyError: raise TinkerError('Unrecognized pointer keyword %s' % key) try: self.pointers[key] = int(line[27:].strip()) except ValueError: raise TinkerError('Could not convert pointer %s to int ' '[%s]' % (key, line.rstrip())) except KeyError: raise Exception('Should not be here -- internal error') line = f.readline() # Check that we read in some pointers s = 0 for key in self.pointers: s += self.pointers[key] if s <= 0: raise TinkerError('All pointers are 0') # Get the atoms in the next section while line.strip() != 'Atom Type Definition Parameters :': if not line: raise TinkerError('Unexpected EOF when looking for atom ' 'definitions') line = f.readline() TinkerAnalout._read_atom_definitions(self, f) # Get all of the sections defined in _functionmap -- see bottom of # this file while True: line = f.readline() try: self._functionmap[line.strip()](self, f) except KeyError: break finally: f.close()
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # These are functions that take an open file and load a section of the file # into the data structures def _read_atom_definitions(self, f): # Make an atom list self.atom_list = AtomList() # Eat 3 lines, then begin f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['natom']): try: atnum = int(line[:6]) self.atom_list.add( line[11:14], line[14:21], line[21:28], line[28:34], line[34:44], line[44:49], line[54:].strip() ) except ValueError: raise TinkerError('Error parsing atomic properties\n\t' '[%s]' % line.rstrip()) line = f.readline() if atnum != i + 1: raise TinkerError('Atom number mismatch [%d vs %d]' % (i + 1, atnum)) def _read_vdw(self, f): """ Reads the van der Waals parameters """ if not hasattr(self, 'atom_list'): raise AttributeError('Atom definitions must be loaded ' 'prior to vdW!') # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['natom']): try: int(line[0:6]) atnum = int(line[9:15]) self.atom_list[i].add_vdw( line[22:32], line[32:42], line[43:53], line[53:63], line[64:74], ) except ValueError: raise TinkerError('Error parsing van der Waals term') line = f.readline() if atnum != i + 1: raise TinkerError('Atom number mismatch in vdW [%d vs %d]' % (i + 1, atnum)) def _read_bonds(self, f): """ Reads the bond stretching terms """ self.bond_list = BondList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['nbond']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 self.bond_list.add(self.atom_list[at1], self.atom_list[at2], line[40:50], line[50:60]) except ValueError: raise TinkerError('Error parsing bonded term') line = f.readline() def _read_angs(self, f): """ Reads the angle stretching terms """ self.angle_list = AngleList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['nangle']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 at3 = int(line[21:27]) - 1 self.angle_list.add(self.atom_list[at1], self.atom_list[at2], self.atom_list[at3], line[40:50], line[50:60], line[60:67], line[69:]) except ValueError: raise TinkerError('Error parsing angle term') line = f.readline() def _read_strbnd(self, f): """ Reads the stretch-bend terms """ self.stretchbend_list = StretchBendList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['nstrbnd']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 at3 = int(line[21:27]) - 1 self.stretchbend_list.add( self.atom_list[at1], self.atom_list[at2], self.atom_list[at3], line[27:40], line[40:50], line[50:60], line[60:70] ) except ValueError: raise TinkerError('Error parsing stretch-bend term') line = f.readline() def _read_ureybrad(self, f): """ Reads the urey-bradley terms """ self.ureybrad_list = UreyBradleyList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['nurey']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 # Support older-style analyze output that had all 3 atoms # involved in the angle. Newer analyze output contains only the # first and 3rd atoms, so that is all we pass into the # UreyBradleyList function try: at3 = int(line[21:27]) - 1 except ValueError: at3 = at2 self.ureybrad_list.add(self.atom_list[at1], self.atom_list[at3], line[34:50], line[50:60]) except ValueError: raise TinkerError('Error parsing Urey-Bradley term') line = f.readline() def _read_opbend(self, f): """ Reads the out-of-plane bending terms """ self.oopbend_list = OutOfPlaneBendList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['nopbend']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 at3 = int(line[21:27]) - 1 at4 = int(line[27:33]) - 1 self.oopbend_list.add(self.atom_list[at1], self.atom_list[at2], self.atom_list[at3], self.atom_list[at4], line[42:52]) except ValueError: raise TinkerError('Error parsing out-of-plane bending term') line = f.readline() def _read_opdist(self, f): """ Read the out-of-plane distance parameters """ self.oopdist_list = OutOfPlaneDistList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['nopdist']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 at3 = int(line[21:27]) - 1 at4 = int(line[27:33]) - 1 self.oopdist_list.add(self.atom_list[at1], self.atom_list[at2], self.atom_list[at3], self.atom_list[at4], line[42:52]) except ValueError: raise TinkerError('Error parsing out-of-plane distance term') line = f.readline() def _read_torang(self, f): """ Read the torsion-angle parameters """ self.torangle_list = TorsionAngleList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['ntors']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 at3 = int(line[21:27]) - 1 at4 = int(line[27:33]) - 1 # Get the rest of the terms (replace / with ' ' so we can do a # simple string split on whitespace) terms = line[33:].replace('/', ' ').split() self.torangle_list.add(self.atom_list[at1], self.atom_list[at2], self.atom_list[at3], self.atom_list[at4], terms) except ValueError: raise TinkerError('Error parsing torsion angle term') line = f.readline() def _read_pitors(self, f): """ Read the Pi-Orbital Torsion parameters """ self.pitors_list = PiTorsionList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['npitors']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 self.pitors_list.add(self.atom_list[at1], self.atom_list[at2], line[40:50]) except ValueError: raise TinkerError('Error parsing pi-torsion term') line = f.readline() def _read_tortors(self, f): """ Read the Torsion-Torsion parameters """ self.tortor_list = TorsionTorsionList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['ntortor']): try: int(line[0:6]) at1 = int(line[9:15]) - 1 at2 = int(line[15:21]) - 1 at3 = int(line[21:27]) - 1 at4 = int(line[27:33]) - 1 at5 = int(line[33:39]) - 1 dim1 = int(line[49:55]) dim2 = int(line[55:61]) self.tortor_list.add(self.atom_list[at1], self.atom_list[at2], self.atom_list[at3], self.atom_list[at4], self.atom_list[at5], dim1, dim2) except ValueError: raise TinkerError('Error parsing torsion-torsion term') line = f.readline() # The CMAP section was adjusted to print out the entire torsion # grid under each tor-tor definition. If this line has 3 words, we # need to eat the next dim1*dim2 lines if len(line.split()) == 3: gridvals = [] for j in range(dim1*dim2): gridvals.append(tuple([float(x) for x in line.split()])) line = f.readline() self.tortor_list[-1].type = TorsionTorsionGrid.new(gridvals) def _read_multipoles(self, f): """ Read the atomic multipoles """ self.multipole_list = AtomicMultipoleList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['npole']): try: int(line[0:6]) at = int(line[9:15]) - 1 # Collect the rest of the arguments, kept as strings frame = [line[16:23], line[23:30], line[30:37]] typestr = line[40:48] moments = [line[50:59]] # Next numbers are on the next line line = f.readline() moments.extend([line[50:59], line[59:68], line[68:77]]) line = f.readline() moments.append(line[50:59]) line = f.readline() moments.extend([line[50:59], line[59:68]]) line = f.readline() moments.extend([line[50:59], line[59:68], line[68:77]]) self.multipole_list.add(self.atom_list[at], frame, typestr, moments) except ValueError: raise TinkerError('Error parsing multipole term') line = f.readline() def _read_dipoles(self, f): """ Read atomic dipole polarizabilities """ self.dipole_list = DipolePolarizabilityList() # Eat the next 3 lines f.readline(); f.readline(); f.readline() line = f.readline() for i in range(self.pointers['npole']): try: int(line[0:6]) at = int(line[9:15]) - 1 self.dipole_list.add(self.atom_list[at], line[25:35], line[40:].split()) except ValueError: raise TinkerError('Error parsing dipole polarizabilities') line = f.readline() def _read_interactions(self, f): """ Reads the number of interactions present in the system """ # Eat the next line (1 only) f.readline() line = f.readline() while line.strip(): try: key = TinkerAnalout.atom_inter_flags[line[1:20]] except KeyError: raise TinkerError('Unrecognized token in interaction count ' '[%s]' % line[1:20].strip()) self.pointers[key] = int(line[21:]) line = f.readline() def _read_12pairs(self, f): # Eat the next line self.pair12_list = set() f.readline() line = f.readline() for i in range(self.pointers['pair12']): at1, at2 = int(line[0:8]) - 1, int(line[8:16]) - 1 self.pair12_list.add( (self.atom_list[at1], self.atom_list[at2]) ) line = f.readline() def _read_13pairs(self, f): # Eat the next line self.pair13_list = set() f.readline() line = f.readline() for i in range(self.pointers['pair13']): at1, at2 = int(line[0:8]) - 1, int(line[8:16]) - 1 self.pair13_list.add( (self.atom_list[at1], self.atom_list[at2]) ) line = f.readline() def _read_14pairs(self, f): # Eat the next line self.pair14_list = set() f.readline() line = f.readline() for i in range(self.pointers['pair14']): at1, at2 = int(line[0:8]) - 1, int(line[8:16]) - 1 self.pair14_list.add( (self.atom_list[at1], self.atom_list[at2]) ) line = f.readline() def _read_15pairs(self, f): # Eat the next line self.pair15_list = set() f.readline() line = f.readline() for i in range(self.pointers['pair15']): at1, at2 = int(line[0:8]) - 1, int(line[8:16]) - 1 self.pair15_list.add( (self.atom_list[at1], self.atom_list[at2]) ) line = f.readline() #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ def __str__(self): return self.fname def __repr__(self): return '<TinkerAnalout; %d atoms>' % self.pointers['natom']
# Add the functionmap onto TinkerAnalout after the class has been built. Only # then will the function references be complete # Function map is a hash with the title string of an analout section # mapping to the function responsible for reading that section and the # key of the pointers flag (see self.pointers below) that declares how # many numbers must be parsed from that section TinkerAnalout._functionmap = { 'Van der Waals Parameters :' : TinkerAnalout._read_vdw, 'Bond Stretching Parameters :' : TinkerAnalout._read_bonds, 'Angle Bending Parameters :' : TinkerAnalout._read_angs, 'Stretch-Bend Parameters :' : TinkerAnalout._read_strbnd, 'Urey-Bradley Parameters :' : TinkerAnalout._read_ureybrad, 'Out-of-Plane Bending Parameters :' : TinkerAnalout._read_opbend, 'Out-of-Plane Distance Parameters :' : TinkerAnalout._read_opdist, 'Torsional Angle Parameters :' : TinkerAnalout._read_torang, 'Pi-Orbital Torsion Parameters :' : TinkerAnalout._read_pitors, 'Torsion-Torsion Parameters :' : TinkerAnalout._read_tortors, 'Atomic Multipole Parameters :' : TinkerAnalout._read_multipoles, 'Dipole Polarizability Parameters :' : TinkerAnalout._read_dipoles, 'List of 1-2 Connected Atomic Interactions :' : TinkerAnalout._read_12pairs, 'List of 1-3 Connected Atomic Interactions :' : TinkerAnalout._read_13pairs, 'List of 1-4 Connected Atomic Interactions :' : TinkerAnalout._read_14pairs, 'List of 1-5 Connected Atomic Interactions :' : TinkerAnalout._read_15pairs, 'Total Number of Pairwise Atomic Interactions :' : TinkerAnalout._read_interactions, }