Beispiel #1
0
    def report(self, simulation, state):
        """
        Generate a report.

        Parameters:
            - simulation (Simulation) The Simulation to generate a report for
            - state (State) The current state of the simulation
        """
        from parmed.amber.asciicrd import VELSCALE
        global VELUNIT, FRCUNIT
        if self.crds:
            crds = state.getPositions().value_in_unit(u.angstrom)
        elif self.vels: # crds/vels/frcs are exclusive, elif works
            vels = state.getVelocities().value_in_unit(VELUNIT)
        elif self.frcs:
            frcs = state.getForces().value_in_unit(FRCUNIT)
        if self._out is None:
            # This must be the first frame, so set up the trajectory now
            if self.crds:
                self.atom = len(crds)
            elif self.vels:
                self.atom = len(vels)
            elif self.frcs:
                self.atom = len(frcs)
            self.uses_pbc = simulation.topology.getUnitCellDimensions() is not None
            self._out = AmberMdcrd(self.fname, self.atom, self.uses_pbc,
                    title="ParmEd-created trajectory using OpenMM", mode='w')

        # Add the coordinates, velocities, and/or forces as needed
        if self.crds:
            flatcrd = [0 for i in range(self.atom*3)]
            for i in range(self.atom):
                i3 = i*3
                flatcrd[i3], flatcrd[i3+1], flatcrd[i3+2] = crds[i]
            self._out.add_coordinates(flatcrd)
        if self.vels:
            # Divide by the scaling factor (works if vels is a list of Vec3's)
            # This is necessary since AmberMdcrd does not scale before writing
            # (since it expects coordinates)
            vels = [v / VELSCALE for v in vels]
            flatvel = [0 for i in range(self.atom*3)]
            for i in range(self.atom):
                i3 = i*3
                flatvel[i3], flatvel[i3+1], flatvel[i3+2] = vels[i]
            self._out.add_coordinates(flatvel)
        if self.frcs:
            flatfrc = [0 for i in range(self.atom*3)]
            for i in range(self.atom):
                i3 = i*3
                flatfrc[i3], flatfrc[i3+1], flatfrc[i3+2] = frcs[i]
            self._out.add_coordinates(flatfrc)
        # Now it's time to add the box lengths
        if self.uses_pbc:
            boxvecs = state.getPeriodicBoxVectors()
            lengths, angles = box_vectors_to_lengths_and_angles(*boxvecs)
            self._out.add_box(lengths.value_in_unit(u.angstroms))
Beispiel #2
0
    def report(self, simulation, state):
        """Generate a report.
        Parameters
        ----------
        simulation : :class:`app.Simulation`
            The Simulation to generate a report for
        state : :class:`mm.State`
            The current state of the simulation
        """
        global VELUNIT, FRCUNIT
        if self.crds:
            crds = state.getPositions().value_in_unit(u.angstrom)
        if self.vels:
            vels = state.getVelocities().value_in_unit(VELUNIT)
        if self.frcs:
            frcs = state.getForces().value_in_unit(FRCUNIT)
        if self.protocolWork:
            protocolWork = simulation.integrator.get_protocol_work(dimensionless=True)
        if self.alchemicalLambda:
            alchemicalLambda = simulation.integrator.getGlobalVariableByName('lambda')
        if self._out is None:
            # This must be the first frame, so set up the trajectory now
            if self.crds:
                atom = len(crds)
            elif self.vels:
                atom = len(vels)
            elif self.frcs:
                atom = len(frcs)
            self.uses_pbc = simulation.topology.getUnitCellDimensions() is not None
            self._out = NetCDF4Traj.open_new(
                    self.fname, atom, self.uses_pbc, self.crds, self.vels,
                    self.frcs, title="ParmEd-created trajectory using OpenMM",
                    protocolWork=self.protocolWork, alchemicalLambda=self.alchemicalLambda,
            )

        if self.uses_pbc:
            vecs = state.getPeriodicBoxVectors()
            lengths, angles = box_vectors_to_lengths_and_angles(*vecs)
            self._out.add_cell_lengths_angles(lengths.value_in_unit(u.angstrom),
                                              angles.value_in_unit(u.degree))

        # Add the coordinates, velocities, and/or forces as needed
        if self.crds:
            self._out.add_coordinates(crds)
        if self.vels:
            # The velocities get scaled right before writing
            self._out.add_velocities(vels)
        if self.frcs:
            self._out.add_forces(frcs)
        if self.protocolWork:
            self._out.add_protocolWork(protocolWork)
        if self.alchemicalLambda:
            self._out.add_alchemicalLambda(alchemicalLambda)
        # Now it's time to add the time.
        self._out.add_time(state.getTime().value_in_unit(u.picosecond))
    def testBoxLengthsVectors(self):
        """ Test converting box lengths/angles to vectors and back again """
        a, b, c = geo.box_lengths_and_angles_to_vectors(1, 1, 1, 90, 90, 90)

        self.assertEqualVectors(a, [1.0, 0.0, 0.0] * u.angstroms)
        self.assertEqualVectors(b, [0.0, 1.0, 0.0] * u.angstroms)
        self.assertEqualVectors(c, [0.0, 0.0, 1.0] * u.angstroms)

        ang = 109.475
        rad = ang * math.pi / 180
        a,b,c = geo.box_lengths_and_angles_to_vectors(50, 50, 50, ang, ang, ang)
        leng, ang = geo.box_vectors_to_lengths_and_angles(a, b, c)
        self.assertEqualVectors(leng, (50, 50, 50))
        self.assertEqualVectors(ang, (rad, rad, rad))
Beispiel #4
0
    def report(self, sim, state):
        """Generate a report.

        Parameters
        ----------
        sim : :class:`app.Simulation`
            The Simulation to generate a report for
        state : :class:`mm.State`
            The current state of the simulation
        """
        global VELUNIT
        crds = state.getPositions().value_in_unit(u.angstrom)
        if self.rst7 is None:
            self.uses_pbc = sim.topology.getUnitCellDimensions() is not None
            self.atom = len(crds)
            # First time written
            self.rst7 = Rst7(natom=self.atom,
                             title='Restart file written by ParmEd with OpenMM')
        self.rst7.time = state.getTime().value_in_unit(u.picosecond)
        flatcrd = [0.0 for i in range(self.atom*3)]
        for i in range(self.atom):
            i3 = i*3
            flatcrd[i3], flatcrd[i3+1], flatcrd[i3+2] = crds[i]
        self.rst7.coordinates = flatcrd

        if self.write_velocities:
            vels = state.getVelocities().value_in_unit(VELUNIT)
            flatvel = [0.0 for i in range(self.atom*3)]
            for i in range(self.atom):
                i3 = i*3
                flatvel[i3], flatvel[i3+1], flatvel[i3+2] = vels[i]
            self.rst7.vels = flatvel

        if self.uses_pbc:
            boxvecs = state.getPeriodicBoxVectors()
            lengths, angles = box_vectors_to_lengths_and_angles(*boxvecs)
            lengths = lengths.value_in_unit(u.angstrom)
            angles = angles.value_in_unit(u.degree)
            self.rst7.box = [lengths[0], lengths[1], lengths[2],
                             angles[0], angles[1], angles[2]]

        if self.write_multiple:
            fname = self.fname + '.%d' % sim.currentStep
        else:
            fname = self.fname

        self.rst7.write(fname, self.netcdf)
Beispiel #5
0
    def report(self, simulation, state):
        """Generate a report.

        Parameters
        ----------
        simulation : :class:`app.Simulation`
            The Simulation to generate a report for
        state : :class:`mm.State`
            The current state of the simulation
        """
        global VELUNIT, FRCUNIT
        if self.crds:
            crds = state.getPositions().value_in_unit(u.angstrom)
        if self.vels:
            vels = state.getVelocities().value_in_unit(VELUNIT)
        if self.frcs:
            frcs = state.getForces().value_in_unit(FRCUNIT)
        if self._out is None:
            # This must be the first frame, so set up the trajectory now
            if self.crds:
                atom = len(crds)
            elif self.vels:
                atom = len(vels)
            elif self.frcs:
                atom = len(frcs)
            self.uses_pbc = simulation.topology.getUnitCellDimensions() is not None
            self._out = NetCDFTraj.open_new(
                    self.fname, atom, self.uses_pbc, self.crds, self.vels,
                    self.frcs, title="ParmEd-created trajectory using OpenMM"
            )
        if self.uses_pbc:
            vecs = state.getPeriodicBoxVectors()
            lengths, angles = box_vectors_to_lengths_and_angles(*vecs)
            self._out.add_cell_lengths_angles(lengths.value_in_unit(u.angstrom),
                                              angles.value_in_unit(u.degree))

        # Add the coordinates, velocities, and/or forces as needed
        if self.crds:
            self._out.add_coordinates(crds)
        if self.vels:
            # The velocities get scaled right before writing
            self._out.add_velocities(vels)
        if self.frcs:
            self._out.add_forces(frcs)
        # Now it's time to add the time.
        self._out.add_time(state.getTime().value_in_unit(u.picosecond))
Beispiel #6
0
 def __init__(self, state):
     self.coordinates = self._get_data(state, 'getPositions',
                             u.angstrom, (1, -1, 3), asNumpy=True)
     self.velocities = self._get_data(state, 'getVelocities',
                             u.angstrom/u.picosecond, (1, -1, 3),
                             asNumpy=True)
     self.forces = self._get_data(state, 'getForces',
                             u.kilocalorie_per_mole/u.angstrom,
                             (1, -1, 3), asNumpy=True)
     self.energy = self._get_data(state, 'getPotentialEnergy',
                             u.kilocalorie_per_mole)
     self.time = self._get_data(state, 'getTime', u.picosecond)
     box = self._get_data(state, 'getPeriodicBoxVectors', u.angstroms,
                          (3, 3), asNumpy=True)
     if box is not None:
         leng, ang = box_vectors_to_lengths_and_angles(*box)
         leng = leng.value_in_unit(u.angstrom)
         ang = ang.value_in_unit(u.degree)
         self.box = np.array(list(leng) + list(ang))
     else:
         self.box = None
Beispiel #7
0
 def __init__(self, state):
     self.coordinates = self._get_data(state, 'getPositions',
                             u.angstrom, (1, -1, 3), asNumpy=True)
     self.velocities = self._get_data(state, 'getVelocities',
                             u.angstrom/u.picosecond, (1, -1, 3),
                             asNumpy=True)
     self.forces = self._get_data(state, 'getForces',
                             u.kilocalorie_per_mole/u.angstrom,
                             (1, -1, 3), asNumpy=True)
     self.energy = self._get_data(state, 'getPotentialEnergy',
                             u.kilocalorie_per_mole)
     self.time = self._get_data(state, 'getTime', u.picosecond)
     box = self._get_data(state, 'getPeriodicBoxVectors', u.angstroms,
                          (3, 3), asNumpy=True)
     if box is not None:
         leng, ang = box_vectors_to_lengths_and_angles(*box)
         leng = leng.value_in_unit(u.angstrom)
         ang = ang.value_in_unit(u.degree)
         self.box = np.array(list(leng) + list(ang))
     else:
         self.box = None
Beispiel #8
0
    def parse(filename):
        """ Parses a Gromacs GRO file

        Parameters
        ----------
        filename : str or file-like
            Name of the file or the GRO file object

        Returns
        -------
        struct : :class:`Structure`
            The Structure instance instantiated with *just* residues and atoms
            populated (with coordinates)
        """
        struct = Structure()
        if isinstance(filename, string_types):
            fileobj = genopen(filename, 'r')
            own_handle = True
        else:
            fileobj = filename
            own_handle = False
        try:
            # Ignore the title line
            fileobj.readline()
            try:
                natom = int(fileobj.readline().strip())
            except ValueError:
                raise GromacsError('Could not parse %s as GRO file' % filename)
            digits = None
            for i, line in enumerate(fileobj):
                if i == natom: break
                try:
                    resnum = int(line[:5])
                    resname = line[5:10].strip()
                    atomname = line[10:15].strip()
                    elem = element_by_name(atomname)
                    atomic_number = AtomicNum[elem]
                    mass = Mass[elem]
                    atnum = int(line[15:20])
                    if atomic_number == 0:
                        atom = ExtraPoint(name=atomname, number=atnum)
                    else:
                        atom = Atom(atomic_number=atomic_number, name=atomname,
                                    number=atnum, mass=mass)
                    if digits is None:
                        pdeci = line.index('.', 20)
                        ndeci = line.index('.', pdeci+1)
                        digits = ndeci - pdeci
                    atom.xx, atom.xy, atom.xz = (
                            float(line[20+i*digits:20+(i+1)*digits])*10
                                for i in range(3)
                    )
                    i = 4
                    wbeg = (pdeci-4)+(5+ndeci)*(i-1)
                    wend = (pdeci-4)+(5+ndeci)*i
                    if line[wbeg:wend].strip():
                        atom.vx, atom.vy, atom.vz = (
                                float(line[(pdeci-3)+(6+ndeci)*i:
                                           (pdeci-3)+(6+ndeci)*(i+1)])*10
                                for i in range(3, 6)
                        )
                except (ValueError, IndexError):
                    raise GromacsError('Could not parse the atom record of '
                                       'GRO file %s' % filename)
                struct.add_atom(atom, resname, resnum)
            # Get the box from the last line if it's present
            if line.strip():
                try:
                    box = [float(x) for x in line.split()]
                except ValueError:
                    raise GromacsError('Could not understand box line of GRO '
                                       'file %s' % filename)
                if len(box) == 3:
                    struct.box = [box[0]*10, box[1]*10, box[2]*10,
                                  90.0, 90.0, 90.0]
                elif len(box) == 9:
                    # Assume we have vectors
                    leng, ang = box_vectors_to_lengths_and_angles(
                                [box[0], box[3], box[4]]*u.nanometers,
                                [box[5], box[1], box[6]]*u.nanometers,
                                [box[7], box[8], box[2]]*u.nanometers)
                    a, b, c = leng.value_in_unit(u.angstroms)
                    alpha, beta, gamma = ang.value_in_unit(u.degrees)
                    struct.box = [a, b, c, alpha, beta, gamma]
        finally:
            if own_handle:
                fileobj.close()

        return struct
Beispiel #9
0
def load_topology(topology, system=None):
    """
    Creates a :class:`parmed.structure.Structure` instance from an OpenMM
    Topology, optionally filling in parameters from a System

    Parameters
    ----------
    topology : :class:`simtk.openmm.app.Topology`
        The Topology instance with the list of atoms and bonds for this system
    system : :class:`simtk.openmm.System` or str, optional
        If provided, parameters from this System will be applied to the
        Structure. If a string is given, it will be interpreted as the file name
        of an XML-serialized System, and it will be deserialized into a System
        before used to supply parameters

    Returns
    -------
    struct : :class:`Structure <parmed.structure.Structure>`
        The structure from the provided topology

    Raises
    ------
    OpenMMWarning if parameters are found that cannot be interpreted or
    processed by ParmEd

    TypeError if there are any mismatches between the provided topology and
    system (e.g., they have different numbers of atoms)

    IOError if system is a string and it is not an existing file

    Notes
    -----
    Due to its flexibility with CustomForces, it is entirely possible that the
    functional form of the potential will be unknown to ParmEd. This function
    will try to use the energy expression to identify supported potential types
    that are implemented as CustomForce objects. In particular, quadratic
    improper torsions, when recognized, will be extracted.

    Other CustomForces, including the CustomNonbondedForce used to implement
    NBFIX (off-diagonal L-J modifications) and the 12-6-4 potential, will not be
    processed and will result in an unknown functional form
    """
    struct = Structure()
    atommap = dict()
    for c in topology.chains():
        chain = c.id
        for r in c.residues():
            residue = r.name
            resid = r.index
            for a in r.atoms():
                if a.element is None:
                    atom = ExtraPoint(name=a.name)
                else:
                    atom = Atom(atomic_number=a.element.atomic_number,
                                name=a.name, mass=a.element.mass)
                struct.add_atom(atom, residue, resid, chain)
                atommap[a] = atom
    for a1, a2 in topology.bonds():
        struct.bonds.append(Bond(atommap[a1], atommap[a2]))

    vectors = topology.getPeriodicBoxVectors()
    if vectors is not None:
        leng, ang = box_vectors_to_lengths_and_angles(*vectors)
        leng = leng.value_in_unit(u.angstroms)
        ang = ang.value_in_unit(u.degrees)
        struct.box = [leng[0], leng[1], leng[2], ang[0], ang[1], ang[2]]

    if struct.box is not None:
        struct.box = create_array(struct.box)

    if system is None:
        return struct

    if isinstance(system, string_types):
        with open(system, 'r') as f:
            system = mm.XmlSerializer.deserialize(f.read())

    # We have a system, try to extract parameters from it
    if len(struct.atoms) != system.getNumParticles():
        raise TypeError('Topology and System have different numbers of atoms '
                '(%d vs. %d)' % (len(struct.atoms), system.getNumParticles()))

    processed_forces = set()
    ignored_forces = (mm.CMMotionRemover, mm.AndersenThermostat,
                      mm.MonteCarloBarostat, mm.MonteCarloAnisotropicBarostat,
                      mm.MonteCarloMembraneBarostat, mm.CustomExternalForce,
                      mm.GBSAOBCForce, mm.CustomGBForce)

    if system.usesPeriodicBoundaryConditions():
        vectors = system.getDefaultPeriodicBoxVectors()
        leng, ang = box_vectors_to_lengths_and_angles(*vectors)
        leng = leng.value_in_unit(u.angstroms)
        ang = ang.value_in_unit(u.degrees)
        struct.box = create_array(
                [leng[0], leng[1], leng[2], ang[0], ang[1], ang[2]]
        )
    else:
        struct.box = None

    for force in system.getForces():
        if isinstance(force, mm.HarmonicBondForce):
            if mm.HarmonicBondForce in processed_forces:
                # Try to process this HarmonicBondForce as a Urey-Bradley term
                _process_urey_bradley(struct, force)
            else:
                _process_bond(struct, force)
        elif isinstance(force, mm.HarmonicAngleForce):
            _process_angle(struct, force)
        elif isinstance(force, mm.PeriodicTorsionForce):
            _process_dihedral(struct, force)
        elif isinstance(force, mm.RBTorsionForce):
            _process_rbtorsion(struct, force)
        elif isinstance(force, mm.CustomTorsionForce):
            if not _process_improper(struct, force):
                struct.unknown_functional = True
                warnings.warn('Unknown functional form of CustomTorsionForce',
                              OpenMMWarning)
        elif isinstance(force, mm.CMAPTorsionForce):
            _process_cmap(struct, force)
        elif isinstance(force, mm.NonbondedForce):
            _process_nonbonded(struct, force)
        elif isinstance(force, ignored_forces):
            continue
        else:
            struct.unknown_functional = True
            warnings.warn('Unsupported Force type %s' % type(force).__name__,
                          OpenMMWarning)
        processed_forces.add(type(force))

    return struct
Beispiel #10
0
    def parse(filename, skip_bonds=False):
        """ Parses a Gromacs GRO file

        Parameters
        ----------
        filename : str or file-like
            Name of the file or the GRO file object
        skip_bonds : bool, optional
            If True, skip trying to assign bonds. This can save substantial time
            when parsing large files with non-standard residue names. However,
            no bonds are assigned. This is OK if, for instance, the GRO file is
            being parsed simply for its coordinates. This will also reduce the
            accuracy of assigned atomic numbers for typical ions. Default is
            False.

        Returns
        -------
        struct : :class:`Structure`
            The Structure instance instantiated with *just* residues and atoms
            populated (with coordinates)
        """
        struct = Structure()
        if isinstance(filename, string_types):
            fileobj = genopen(filename, 'r')
            own_handle = True
        else:
            fileobj = filename
            own_handle = False
        try:
            # Ignore the title line
            fileobj.readline()
            try:
                natom = int(fileobj.readline().strip())
            except ValueError:
                raise GromacsError('Could not parse %s as GRO file' % filename)
            line_parser = _AtomLineParser()
            for i, line in enumerate(fileobj):
                if i == natom: break
                try:
                    atom, resname, resnum = line_parser.read(line)
                except (ValueError, IndexError):
                    raise GromacsError('Could not parse the atom record of '
                                       'GRO file %s' % filename)
                struct.add_atom(atom, resname, resnum)
            else:
                # If no box exists, the break did not hit, so line still
                # contains the last atom (which cannot be interpreted as a box).
                # This wipes out line (IFF fileobj reached the line)
                line = fileobj.readline()
                if i+1 != natom:
                    raise GromacsError('Truncated GRO file. Found %d of %d '
                                       'atoms' % (i+1, natom))
            # Get the box from the last line if it's present
            if line.strip():
                try:
                    box = [float(x) for x in line.split()]
                except ValueError:
                    raise GromacsError('Could not understand box line of GRO '
                                       'file %s' % filename)
                if len(box) == 3:
                    struct.box = [box[0]*10, box[1]*10, box[2]*10,
                                  90.0, 90.0, 90.0]
                elif len(box) == 9:
                    # Assume we have vectors
                    leng, ang = box_vectors_to_lengths_and_angles(
                                [box[0], box[3], box[4]]*u.nanometers,
                                [box[5], box[1], box[6]]*u.nanometers,
                                [box[7], box[8], box[2]]*u.nanometers)
                    a, b, c = leng.value_in_unit(u.angstroms)
                    alpha, beta, gamma = ang.value_in_unit(u.degrees)
                    struct.box = [a, b, c, alpha, beta, gamma]
        finally:
            if own_handle:
                fileobj.close()

        # Assign bonds (and improved element guesses)
        if not skip_bonds:
            struct.assign_bonds()

        return struct
Beispiel #11
0
def load_topology(topology, system=None, xyz=None, box=None):
    """
    Creates a :class:`parmed.structure.Structure` instance from an OpenMM
    Topology, optionally filling in parameters from a System

    Parameters
    ----------
    topology : :class:`simtk.openmm.app.Topology`
        The Topology instance with the list of atoms and bonds for this system
    system : :class:`simtk.openmm.System` or str, optional
        If provided, parameters from this System will be applied to the
        Structure. If a string is given, it will be interpreted as the file name
        of an XML-serialized System, and it will be deserialized into a System
        before used to supply parameters
    xyz : str or array of float
        Name of a file containing coordinate information or an array of
        coordinates. If file has unit cell information, it also uses that
        information unless ``box`` (below) is also specified
    box : array of 6 floats
        Unit cell dimensions

    Returns
    -------
    struct : :class:`Structure <parmed.structure.Structure>`
        The structure from the provided topology

    Raises
    ------
    OpenMMWarning if parameters are found that cannot be interpreted or
    processed by ParmEd

    TypeError if there are any mismatches between the provided topology and
    system (e.g., they have different numbers of atoms)

    IOError if system is a string and it is not an existing file

    Notes
    -----
    Due to its flexibility with CustomForces, it is entirely possible that the
    functional form of the potential will be unknown to ParmEd. This function
    will try to use the energy expression to identify supported potential types
    that are implemented as CustomForce objects. In particular, quadratic
    improper torsions, when recognized, will be extracted.

    Other CustomForces, including the CustomNonbondedForce used to implement
    NBFIX (off-diagonal L-J modifications) and the 12-6-4 potential, will not be
    processed and will result in an unknown functional form
    """
    import simtk.openmm as mm
    struct = Structure()
    atommap = dict()
    for c in topology.chains():
        chain = c.id
        for r in c.residues():
            residue = r.name
            resid = r.index
            for a in r.atoms():
                if a.element is None:
                    atom = ExtraPoint(name=a.name)
                else:
                    atom = Atom(atomic_number=a.element.atomic_number,
                                name=a.name,
                                mass=a.element.mass)
                struct.add_atom(atom, residue, resid, chain)
                atommap[a] = atom
    for a1, a2 in topology.bonds():
        struct.bonds.append(Bond(atommap[a1], atommap[a2]))

    vectors = topology.getPeriodicBoxVectors()
    if vectors is not None:
        leng, ang = box_vectors_to_lengths_and_angles(*vectors)
        leng = leng.value_in_unit(u.angstroms)
        ang = ang.value_in_unit(u.degrees)
        struct.box = [leng[0], leng[1], leng[2], ang[0], ang[1], ang[2]]

    loaded_box = False

    if xyz is not None:
        if isinstance(xyz, string_types):
            xyz = load_file(xyz, skip_bonds=True)
            struct.coordinates = xyz.coordinates
            if struct.box is not None:
                if xyz.box is not None:
                    loaded_box = True
                    struct.box = xyz.box
        else:
            struct.coordinates = xyz

    if box is not None:
        loaded_box = True
        struct.box = box

    if struct.box is not None:
        struct.box = np.asarray(struct.box)

    if system is None:
        return struct

    if isinstance(system, string_types):
        system = load_file(system)

    if not isinstance(system, mm.System):
        raise TypeError('system must be an OpenMM System object or serialized '
                        'XML of an OpenMM System object')

    # We have a system, try to extract parameters from it
    if len(struct.atoms) != system.getNumParticles():
        raise TypeError('Topology and System have different numbers of atoms '
                        '(%d vs. %d)' %
                        (len(struct.atoms), system.getNumParticles()))

    processed_forces = set()
    ignored_forces = (mm.CMMotionRemover, mm.AndersenThermostat,
                      mm.MonteCarloBarostat, mm.MonteCarloAnisotropicBarostat,
                      mm.MonteCarloMembraneBarostat, mm.CustomExternalForce,
                      mm.GBSAOBCForce, mm.CustomGBForce)

    if system.usesPeriodicBoundaryConditions():
        if not loaded_box:
            vectors = system.getDefaultPeriodicBoxVectors()
            leng, ang = box_vectors_to_lengths_and_angles(*vectors)
            leng = leng.value_in_unit(u.angstroms)
            ang = ang.value_in_unit(u.degrees)
            struct.box = np.asarray(
                [leng[0], leng[1], leng[2], ang[0], ang[1], ang[2]])
    else:
        struct.box = None

    for force in system.getForces():
        if isinstance(force, mm.HarmonicBondForce):
            if mm.HarmonicBondForce in processed_forces:
                # Try to process this HarmonicBondForce as a Urey-Bradley term
                _process_urey_bradley(struct, force)
            else:
                _process_bond(struct, force)
        elif isinstance(force, mm.HarmonicAngleForce):
            _process_angle(struct, force)
        elif isinstance(force, mm.PeriodicTorsionForce):
            _process_dihedral(struct, force)
        elif isinstance(force, mm.RBTorsionForce):
            _process_rbtorsion(struct, force)
        elif isinstance(force, mm.CustomTorsionForce):
            if not _process_improper(struct, force):
                struct.unknown_functional = True
                warnings.warn('Unknown functional form of CustomTorsionForce',
                              OpenMMWarning)
        elif isinstance(force, mm.CMAPTorsionForce):
            _process_cmap(struct, force)
        elif isinstance(force, mm.NonbondedForce):
            _process_nonbonded(struct, force)
        elif isinstance(force, ignored_forces):
            continue
        else:
            struct.unknown_functional = True
            warnings.warn('Unsupported Force type %s' % type(force).__name__,
                          OpenMMWarning)
        processed_forces.add(type(force))

    return struct
Beispiel #12
0
    def parse(filename):
        """ Parses a Gromacs GRO file

        Parameters
        ----------
        filename : str or file-like
            Name of the file or the GRO file object

        Returns
        -------
        struct : :class:`Structure`
            The Structure instance instantiated with *just* residues and atoms
            populated (with coordinates)
        """
        struct = Structure()
        if isinstance(filename, string_types):
            fileobj = genopen(filename, 'r')
            own_handle = True
        else:
            fileobj = filename
            own_handle = False
        try:
            # Ignore the title line
            fileobj.readline()
            try:
                natom = int(fileobj.readline().strip())
            except ValueError:
                raise GromacsError('Could not parse %s as GRO file' % filename)
            digits = None
            line_parser = _AtomLineParser()
            for i, line in enumerate(fileobj):
                if i == natom: break
                try:
                    atom, resname, resnum = line_parser.read(line)
                except (ValueError, IndexError):
                    raise GromacsError('Could not parse the atom record of '
                                       'GRO file %s' % filename)
                struct.add_atom(atom, resname, resnum)
            else:
                # If no box exists, the break did not hit, so line still
                # contains the last atom (which cannot be interpreted as a box).
                # This wipes out line (IFF fileobj reached the line)
                line = fileobj.readline()
                if i+1 != natom:
                    raise GromacsError('Truncated GRO file. Found %d of %d '
                                       'atoms' % (i+1, natom))
            # Get the box from the last line if it's present
            if line.strip():
                try:
                    box = [float(x) for x in line.split()]
                except ValueError:
                    raise GromacsError('Could not understand box line of GRO '
                                       'file %s' % filename)
                if len(box) == 3:
                    struct.box = [box[0]*10, box[1]*10, box[2]*10,
                                  90.0, 90.0, 90.0]
                elif len(box) == 9:
                    # Assume we have vectors
                    leng, ang = box_vectors_to_lengths_and_angles(
                                [box[0], box[3], box[4]]*u.nanometers,
                                [box[5], box[1], box[6]]*u.nanometers,
                                [box[7], box[8], box[2]]*u.nanometers)
                    a, b, c = leng.value_in_unit(u.angstroms)
                    alpha, beta, gamma = ang.value_in_unit(u.degrees)
                    struct.box = [a, b, c, alpha, beta, gamma]
        finally:
            if own_handle:
                fileobj.close()

        return struct