Пример #1
0
    def _parse(self, fname):

        with closing(io.genopen(fname, 'r')) as crdfile:
            readingHeader = True
            while readingHeader:
                line = crdfile.readline()
                if not len(line):
                    raise CharmmError('Premature end of file')
                line = line.strip()
                words = line.split()
                if len(line) != 0:
                    if words[0] == 'ENERGIES' or words[0] == '!ENERGIES':
                        readingHeader = False
                    else:
                        self.header.append(line.strip())
                else:
                    self.header.append(line.strip())

            for row in range(len(self.header)):
                if len(self.header[row].strip()) != 0:
                    line = self.header[row].strip().split()
                    if line[0][0:5] == 'NATOM' or line[0][0:6] == '!NATOM':
                        try:
                            line = self.header[row + 1].strip().split()
                            self.natom = int(line[0])
                            self.npriv = int(line[1])  # num. previous steps
                            self.nstep = int(line[2])  # num. steps in file
                            self.nsavc = int(line[3])  # coord save frequency
                            self.nsavv = int(line[4])  # velocities "
                            self.jhstrt = int(line[5])  # Num total steps?
                            break
                        except (ValueError, IndexError):
                            raise CharmmError('Problem parsing CHARMM restart')

            self.scan(crdfile, '!XOLD')
            self._get_formatted_crds(crdfile, self.coordsold)
            self.coordsold = np.array(self.coordsold).reshape(
                (-1, self.natom, 3))

            self.scan(crdfile, '!VX')
            self._get_formatted_crds(crdfile, self.vels)
            self.vels = np.array(self.vels).reshape((-1, self.natom, 3))
            # Convert velocities to angstroms/ps
            self.vels *= ONE_TIMESCALE

            self.scan(crdfile, '!X')
            self._get_formatted_crds(crdfile, self.coords)
            self.coords = np.array(self.coords).reshape((-1, self.natom, 3))
Пример #2
0
    def _parse_psf_section(psf):
        """
        This method parses a section of the PSF file

        Parameters
        ----------
        psf : file
            Open file that is pointing to the first line of the section that is
            to be parsed

        Returns
        -------
        title : str
            The label of the PSF section we are parsing
        pointers : (int/tuple of ints)
            If one pointer is set, pointers is simply the integer that is value
            of that pointer. Otherwise it is a tuple with every pointer value
            defined in the first line
        data : list
            A list of all data in the parsed section converted to integers
        """
        conv = CharmmPsfFile._convert
        line = psf.readline()
        while not line.strip():
            if not line:
                raise _FileEOF('Unexpected EOF in PSF file')
            else:
                line = psf.readline()
        if '!' in line:
            words = line[:line.index('!')].split()
            title = line[line.index('!') + 1:].strip().upper()
            # Strip out description
            if ':' in title:
                title = title[:title.index(':')]
        else:
            raise CharmmError(
                'Could not determine section title')  # pragma: no cover
        if len(words) == 1:
            pointers = conv(words[0], int, 'pointer')
        else:
            pointers = tuple([conv(w, int, 'pointer') for w in words])
        line = psf.readline().strip()
        if not line and title.startswith('NNB'):
            # This will correctly handle the NNB section (which has a spurious
            # blank line) as well as any sections that have 0 members.
            line = psf.readline().strip()
        data = []
        if title == 'NATOM' or title == 'NTITLE':
            # Store these two sections as strings (ATOM section we will parse
            # later). The rest of the sections are integer pointers
            while line:
                data.append(line)
                line = psf.readline().strip()
        else:
            while line:
                words = line.split()
                data.extend([conv(w, int, 'PSF data') for w in words])
                line = psf.readline().strip()
        return title, pointers, data
Пример #3
0
    def _get_formatted_crds(self, crdfile, crds):
        for row in range(self.natom):
            line = crdfile.readline()

            if not line:
                raise CharmmError('Premature end of file')

            if len(line) < 3 * CHARMLEN:
                raise CharmmError("Less than 3 coordinates present in "
                                  "coordinate row or coords may be "
                                  "truncated.")

            line = line.replace('D', 'E')  # CHARMM uses 'D' for exponentials

            # CHARMM uses fixed format (len = CHARMLEN = 22) for crds in .rst's
            crds.append(float(line[0:CHARMLEN]))
            crds.append(float(line[CHARMLEN:2 * CHARMLEN]))
            crds.append(float(line[2 * CHARMLEN:3 * CHARMLEN]))
Пример #4
0
    def scan(self, handle, str, r=0):  # read lines in file till 'str' is found
        scanning = True

        if (r): handle.seek(0)

        while scanning:
            line = handle.readline()
            if not line:
                raise CharmmError('Premature end of file')

            if len(line.strip()) != 0:
                if line.strip().split()[0][0:len(str)] == str:
                    scanning = False
Пример #5
0
    def _convert(string, type, message):
        """
        Converts a string to a specific type, making sure to raise
        CharmmError with the given message in the event of a failure.

        Parameters
        ----------
        string : str
            Input string to process
        type : type
            Type of data to convert to (e.g., ``int``)
        message : str
            Error message to put in exception if failed
        """
        try:
            return type(string)
        except ValueError:
            raise CharmmError('Could not convert %s [%s]' % (message, string))
Пример #6
0
    def _parse(self, fname):

        with closing(io.genopen(fname, 'r')) as crdfile:
            line = crdfile.readline().strip()

            while len(line) == 0:  # Skip whitespace, as a precaution
                line = crdfile.readline().strip()

            intitle = True
            while intitle:
                self.title.append(line)
                line = crdfile.readline().strip()
                if len(line) == 0:
                    intitle = False
                elif line[0] != '*':
                    intitle = False
                else:
                    intitle = True

            while len(line) == 0:  # Skip whitespace
                line = crdfile.readline().strip()

            try:
                self.natom = int(line.split()[0])
                for row in range(self.natom):
                    line = crdfile.readline().split()
                    self.atomno.append(int(line[0]))
                    self.resno.append(int(line[1]))
                    self.resname.append(line[2])
                    self.atname.append(line[3])
                    self.coords.append(float(line[4]))
                    self.coords.append(float(line[5]))
                    self.coords.append(float(line[6]))
                    self.segid.append(line[7])
                    self.resid.append(int(line[8]))
                    self.weighting.append(float(line[9]))

                assert 3 * self.natom == len(self.coords), '# atom mismatch'
            except (ValueError, IndexError):
                raise CharmmError('Error parsing CHARMM coordinate file')
            self.coords = np.array(self.coords).reshape((-1, self.natom, 3))
Пример #7
0
 def newfunc(*args, **kwargs):
     """ Catch the index error """
     try:
         return func(*args, **kwargs)
     except IndexError as e:
         raise CharmmError('Array is too short: %s' % e)
Пример #8
0
 def __init__(self, psf_name=None):
     """
     Opens and parses a PSF file, then instantiates a CharmmPsfFile
     instance from the data.
     """
     global _resre
     Structure.__init__(self)
     # Bail out if we don't have a filename
     if psf_name is None:
         return
     conv = CharmmPsfFile._convert
     # Open the PSF and read the first line. It must start with "PSF"
     with closing(genopen(psf_name, 'r')) as psf:
         self.name = psf_name
         line = psf.readline()
         if not line.startswith('PSF'):
             raise CharmmError('Unrecognized PSF file. First line is %s' %
                               line.strip())
         # Store the flags
         psf_flags = line.split()[1:]
         # Now get all of the sections and store them in a dict
         psf.readline()
         # Now get all of the sections
         psfsections = _ZeroDict()
         while True:
             try:
                 sec, ptr, data = CharmmPsfFile._parse_psf_section(psf)
             except _FileEOF:
                 break
             psfsections[sec] = (ptr, data)
         # store the title
         self.title = psfsections['NTITLE'][1]
         # Next is the number of atoms
         natom = conv(psfsections['NATOM'][0], int, 'natom')
         # Parse all of the atoms
         for i in range(natom):
             words = psfsections['NATOM'][1][i].split()
             atid = int(words[0])
             if atid != i + 1:
                 raise CharmmError('Nonsequential atoms detected!')
             segid = words[1]
             rematch = _resre.match(words[2])
             if not rematch:
                 raise CharmmError('Could not interpret residue number %s'
                                   %  # pragma: no cover
                                   words[2])
             resid, inscode = rematch.groups()
             resid = conv(resid, int, 'residue number')
             resname = words[3]
             name = words[4]
             attype = words[5]
             # Try to convert the atom type to an integer a la CHARMM
             try:
                 attype = int(attype)
             except ValueError:
                 pass
             charge = conv(words[6], float, 'partial charge')
             mass = conv(words[7], float, 'atomic mass')
             props = words[8:]
             atom = Atom(name=name, type=attype, charge=charge, mass=mass)
             atom.props = props
             self.add_atom(atom,
                           resname,
                           resid,
                           chain=segid,
                           inscode=inscode,
                           segid=segid)
         # Now get the number of bonds
         nbond = conv(psfsections['NBOND'][0], int, 'number of bonds')
         if len(psfsections['NBOND'][1]) != nbond * 2:
             raise CharmmError(
                 'Got %d indexes for %d bonds' %  # pragma: no cover
                 (len(psfsections['NBOND'][1]), nbond))
         it = iter(psfsections['NBOND'][1])
         for i, j in zip(it, it):
             self.bonds.append(Bond(self.atoms[i - 1], self.atoms[j - 1]))
         # Now get the number of angles and the angle list
         ntheta = conv(psfsections['NTHETA'][0], int, 'number of angles')
         if len(psfsections['NTHETA'][1]) != ntheta * 3:
             raise CharmmError(
                 'Got %d indexes for %d angles' %  # pragma: no cover
                 (len(psfsections['NTHETA'][1]), ntheta))
         it = iter(psfsections['NTHETA'][1])
         for i, j, k in zip(it, it, it):
             self.angles.append(
                 Angle(self.atoms[i - 1], self.atoms[j - 1],
                       self.atoms[k - 1]))
             self.angles[-1].funct = 5  # urey-bradley
         # Now get the number of torsions and the torsion list
         nphi = conv(psfsections['NPHI'][0], int, 'number of torsions')
         if len(psfsections['NPHI'][1]) != nphi * 4:
             raise CharmmError(
                 'Got %d indexes for %d torsions' %  # pragma: no cover
                 (len(psfsections['NPHI']), nphi))
         it = iter(psfsections['NPHI'][1])
         for i, j, k, l in zip(it, it, it, it):
             self.dihedrals.append(
                 Dihedral(self.atoms[i - 1], self.atoms[j - 1],
                          self.atoms[k - 1], self.atoms[l - 1]))
         self.dihedrals.split = False
         # Now get the number of improper torsions
         nimphi = conv(psfsections['NIMPHI'][0], int, 'number of impropers')
         if len(psfsections['NIMPHI'][1]) != nimphi * 4:
             raise CharmmError(
                 'Got %d indexes for %d impropers' %  # pragma: no cover
                 (len(psfsections['NIMPHI'][1]), nimphi))
         it = iter(psfsections['NIMPHI'][1])
         for i, j, k, l in zip(it, it, it, it):
             self.impropers.append(
                 Improper(self.atoms[i - 1], self.atoms[j - 1],
                          self.atoms[k - 1], self.atoms[l - 1]))
         # Now handle the donors (what is this used for??)
         ndon = conv(psfsections['NDON'][0], int, 'number of donors')
         if len(psfsections['NDON'][1]) != ndon * 2:
             raise CharmmError(
                 'Got %d indexes for %d donors' %  # pragma: no cover
                 (len(psfsections['NDON'][1]), ndon))
         it = iter(psfsections['NDON'][1])
         for i, j in zip(it, it):
             self.donors.append(
                 AcceptorDonor(self.atoms[i - 1], self.atoms[j - 1]))
         # Now handle the acceptors (what is this used for??)
         nacc = conv(psfsections['NACC'][0], int, 'number of acceptors')
         if len(psfsections['NACC'][1]) != nacc * 2:
             raise CharmmError(
                 'Got %d indexes for %d acceptors' %  # pragma: no cover
                 (len(psfsections['NACC'][1]), nacc))
         it = iter(psfsections['NACC'][1])
         for i, j in zip(it, it):
             self.acceptors.append(
                 AcceptorDonor(self.atoms[i - 1], self.atoms[j - 1]))
         # Now get the group sections
         try:
             ngrp, nst2 = psfsections['NGRP NST2'][0]
         except ValueError:  # pragma: no cover
             raise CharmmError(
                 'Could not unpack GROUP pointers')  # pragma: no cover
         tmp = psfsections['NGRP NST2'][1]
         self.groups.nst2 = nst2
         # Now handle the groups
         if len(psfsections['NGRP NST2'][1]) != ngrp * 3:
             raise CharmmError(
                 'Got %d indexes for %d groups' %  # pragma: no cover
                 (len(tmp), ngrp))
         it = iter(psfsections['NGRP NST2'][1])
         for i, j, k in zip(it, it, it):
             self.groups.append(Group(self.atoms[i], j, k))
         # Assign all of the atoms to molecules recursively
         tmp = psfsections['MOLNT'][1]
         set_molecules(self.atoms)
         molecule_list = [a.marked for a in self.atoms]
         if len(tmp) == len(self.atoms):
             if molecule_list != tmp:
                 warnings.warn(
                     'Detected PSF molecule section that is WRONG. '
                     'Resetting molecularity.', CharmmWarning)
             # We have a CHARMM PSF file; now do NUMLP/NUMLPH sections
             numlp, numlph = psfsections['NUMLP NUMLPH'][0]
             if numlp != 0 or numlph != 0:
                 raise NotImplementedError(
                     'Cannot currently handle PSFs with '
                     'lone pairs defined in the NUMLP/'
                     'NUMLPH section.')
         # Now do the CMAPs
         ncrterm = conv(psfsections['NCRTERM'][0], int,
                        'Number of cross-terms')
         if len(psfsections['NCRTERM'][1]) != ncrterm * 8:
             raise CharmmError('Got %d CMAP indexes for %d cmap terms'
                               %  # pragma: no cover
                               (len(psfsections['NCRTERM']), ncrterm))
         it = iter(psfsections['NCRTERM'][1])
         for i, j, k, l, m, n, o, p in zip(it, it, it, it, it, it, it, it):
             self.cmaps.append(
                 Cmap.extended(self.atoms[i - 1], self.atoms[j - 1],
                               self.atoms[k - 1], self.atoms[l - 1],
                               self.atoms[m - 1], self.atoms[n - 1],
                               self.atoms[o - 1], self.atoms[p - 1]))
         self.unchange()
         self.flags = psf_flags