Beispiel #1
0
def _topology_from_residue(res):
    """Converts a openmm.app.Topology.Residue to openmm.app.Topology.

    Parameters
    ----------
    res : openmm.app.Topology.Residue
        An individual residue in an openmm.app.Topology

    Returns
    -------
    topology : openmm.app.Topology
        The generated topology

    """
    topology = app.Topology()
    chain = topology.addChain()
    new_res = topology.addResidue(res.name, chain)

    atoms = dict()  # { omm.Atom in res : omm.Atom in *new* topology }

    for res_atom in res.atoms():
        topology_atom = topology.addAtom(name=res_atom.name,
                         element=res_atom.element,
                         residue=new_res)
        atoms[res_atom] = topology_atom
        topology_atom.bond_partners = []

    for bond in res.bonds():
        atom1 = atoms[bond.atom1]
        atom2 = atoms[bond.atom2]
        topology.addBond(atom1, atom2)
        atom1.bond_partners.append(atom2)
        atom2.bond_partners.append(atom1)

    return topology
Beispiel #2
0
def build_water_system(box_width):
    ff = app.ForceField('tip3p.xml')

    # Create empty topology and coordinates.
    top = app.Topology()
    pos = unit.Quantity((), unit.angstroms)
    m = app.Modeller(top, pos)

    boxSize = Vec3(box_width, box_width, box_width)*unit.nanometers
    m.addSolvent(ff, boxSize=boxSize, model='tip3p')

    system = ff.createSystem(
        m.getTopology(),
        nonbondedMethod=app.NoCutoff,
        constraints=None,
        rigidWater=False
    )

    positions = m.getPositions()
    positions = unit.Quantity(np.array(positions / positions.unit), positions.unit)

    assert m.getTopology().getNumAtoms() == positions.shape[0]

    # TODO: minimize the water box (BFGS or scipy.optimize)
    return system, positions, np.eye(3)*box_width, m.getTopology()
def _build_new_topology(current_receptor_topology, oemol_proposed):
    """
    Construct a new topology
    Parameters
    ----------
    oemol_proposed : oechem.OEMol object
        the proposed OEMol object
    current_receptor_topology : app.Topology object
        The current topology without the small molecule

    Returns
    -------
    new_topology : app.Topology object
        A topology with the receptor and the proposed oemol
    mol_start_index : int
        The first index of the small molecule
    """
    oemol_proposed.SetTitle("MOL")
    mol_topology = forcefield_generators.generateTopologyFromOEMol(
        oemol_proposed)
    new_topology = app.Topology()
    append_topology(new_topology, current_receptor_topology)
    append_topology(new_topology, mol_topology)
    # Copy periodic box vectors.
    if current_receptor_topology._periodicBoxVectors != None:
        new_topology._periodicBoxVectors = copy.deepcopy(
            current_receptor_topology._periodicBoxVectors)

    return new_topology
Beispiel #4
0
def _topology_from_parmed(structure, non_element_types):
    """Convert a ParmEd Structure to an OpenMM Topology. """

    topology = app.Topology()
    chain = topology.addChain()
    residue = topology.addResidue(structure.title, chain)
    atoms = dict()  # pmd.Atom: omm.Atom

    for pmd_atom in structure.atoms:
        name = pmd_atom.name
        if pmd_atom.element in non_element_types:
            element = non_element_types[pmd_atom.element]
        else:
            if (isinstance(pmd_atom.atomic_number, int) and
                    pmd_atom.atomic_number != 0):
                element = elem.Element.getByAtomicNumber(pmd_atom.atomic_number)
            else:
                element = elem.Element.getBySymbol(pmd_atom.name)

        omm_atom = topology.addAtom(name, element, residue)
        atoms[pmd_atom] = omm_atom
        omm_atom.bond_partners = []

    for bond in structure.bonds:
        atom1 = atoms[bond.atom1]
        atom2 = atoms[bond.atom2]
        topology.addBond(atom1, atom2)
        atom1.bond_partners.append(atom2)
        atom2.bond_partners.append(atom1)
    if structure.box_vectors and np.any([x._value for x in structure.box_vectors]):
        topology.setPeriodicBoxVectors(structure.box_vectors)

    positions = structure.positions
    return topology, positions
def mol_to_topology(mol):
    """ Create an openmm topology object from an MDT molecule

    Args:
        mol (moldesign.Molecule): molecule to copy topology from

    Returns:
        simtk.openmm.app.Topology: topology of the molecule
    """
    from simtk.openmm import app

    top = app.Topology()
    chainmap = {chain: top.addChain(chain.name) for chain in mol.chains}
    resmap = {
        res: top.addResidue(res.resname, chainmap[res.chain],
                            str(res.pdbindex))
        for res in mol.residues
    }
    atommap = {
        atom: top.addAtom(atom.name,
                          app.Element.getBySymbol(atom.element),
                          resmap[atom.residue],
                          id=str(atom.pdbindex))
        for atom in mol.atoms
    }
    for bond in mol.bonds:
        top.addBond(atommap[bond.a1], atommap[bond.a2])

    return top
Beispiel #6
0
def convert_spce_to_cs(file, saveas="newpdb.pdb"):
    """Extract and rename oxygens from all-atom water structure"""

    import os
    import numpy as np

    import simtk.unit as unit
    import simtk.openmm as omm
    import simtk.openmm.app as app
    file = "equil_spc.pdb"
    saveas = "justO_spc.pdb"
    app.element.solvent = app.element.Element(201, "Solvent", "Sv",
                                              18 * unit.amu)

    pdb = app.PDBFile(file)
    O_idxs = np.array(
        [atm.index for atm in pdb.topology.atoms() if atm.name == "O"])

    xyz = np.array(pdb.positions / unit.angstrom)[O_idxs]
    positions = unit.Quantity(xyz, unit.angstrom)

    n_slv = len(O_idxs)

    topology = app.Topology()
    chain = topology.addChain()
    for i in range(n_slv):
        res = topology.addResidue("SLV", chain)
        topology.addAtom("CS", app.element.get_by_symbol("Sv"), res)

    box_edge = 5.96256971 * unit.nanometer
    topology.setUnitCellDimensions(box_edge * omm.Vec3(1, 1, 1))

    with open(saveas, "w") as fout:
        pdb.writeFile(topology, positions, file=fout)
Beispiel #7
0
    def to_omm_topology(self):
        '''
        Generate OpenMM topology from this topology

        Returns
        -------
        omm_topology : mm.app.Topology
        '''
        try:
            from simtk.openmm import app as omm_app
            from simtk.openmm.app.element import Element as omm_Element
        except ImportError:
            raise Exception('cannot import openmm')

        omm_top = omm_app.Topology()
        omm_chain = omm_top.addChain()
        for mol in self._molecules:
            omm_residue = omm_top.addResidue(mol.name, omm_chain)
            for atom in mol.atoms:
                try:
                    omm_element = omm_Element.getBySymbol(atom.symbol)
                except:
                    omm_element = None
                omm_top.addAtom(atom.name, omm_element, omm_residue)

        if self.cell.volume != 0:
            omm_top.setPeriodicBoxVectors(self.cell.vectors)
        omm_atoms = list(omm_top.atoms())
        for bond in self.bonds:
            omm_top.addBond(omm_atoms[bond.atom1.id], omm_atoms[bond.atom2.id])

        return omm_top
def _create_torsion_sim(periodicity: int = 2,
                        phase=0 * omm_angle_unit,
                        k=10.0 * omm_energy_unit) -> app.Simulation:
    """Create a 4-particle OpenMM Simulation containing only a PeriodicTorsionForce"""
    system = mm.System()

    # add 4 particles of unit mass
    for _ in range(4):
        system.addParticle(1)

    # add torsion force to system
    force = mm.PeriodicTorsionForce()
    force.addTorsion(0, 1, 2, 3, periodicity, phase, k)
    system.addForce(force)

    # create openmm Simulation, which requires a Topology and Integrator
    topology = app.Topology()
    chain = topology.addChain()
    residue = topology.addResidue("torsion", chain)
    for name in ["a", "b", "c", "d"]:
        topology.addAtom(name, "C", residue)
    integrator = mm.VerletIntegrator(1.0)
    sim = app.Simulation(topology, system, integrator)

    return sim
Beispiel #9
0
 def create_omm_topology(self):
     topology = app.Topology()
     for molecule_name, number_of_molecule_copies in self.molecules:
         for _ in range(number_of_molecule_copies):
             self.add_moltype_to_omm_topology(
                 self.molecule_types[molecule_name],
                 topology,
             )
     return topology
Beispiel #10
0
def write_solvent_pdb(sigma_slv,
                      packing_fraction,
                      box_edge,
                      starting_pdb,
                      dummypdb="dum.pdb"):
    """Create solvent in box"""

    # generate solvent
    n_slv = int(round(packing_fraction * ((box_edge / sigma_slv)**3)))
    xyz_slv = np.random.uniform(high=box_edge / unit.angstroms,
                                size=[n_slv, 3])
    overlap_radius = sigma_slv / unit.angstrom

    box_ang = box_edge / unit.angstrom

    new_xyz_slv = []
    for i in range(len(xyz_slv)):
        not_overlapping = True
        if i < (len(xyz_slv) - 1):
            for n in range(i + 1, len(xyz_slv)):
                sep = periodic_distance(xyz_slv[i], xyz_slv[n], box_ang)
                if sep < overlap_radius:
                    # remove solvent that is overlapping itself
                    not_overlapping = False
                    break
        if not_overlapping:
            new_xyz_slv.append(xyz_slv[i])
    xyz_slv = np.array(new_xyz_slv)
    n_slv = len(xyz_slv)

    # create topology
    topology = app.Topology()
    chain = topology.addChain()
    for i in range(n_slv):
        res = topology.addResidue("SLV", chain)
        topology.addAtom("SV", app.element.get_by_symbol("Sv"), res)

    positions = unit.Quantity(xyz_slv, unit.angstrom)

    topology.setUnitCellDimensions(
        (box_edge / unit.nanometer) * omm.Vec3(1, 1, 1))

    pdb = app.PDBFile(dummypdb)
    with open(starting_pdb, "w") as fout:
        pdb.writeFile(topology, positions, file=fout)
Beispiel #11
0
    def chimera_molecule_to_openmm_topology(*molecules):
        """
        Convert a Chimera Molecule object to OpenMM structure,
        providing topology and coordinates.

        Parameters
        ----------
        molecule : chimera.Molecule

        Returns
        -------
        topology : simtk.openmm.app.topology.Topology
        coordinates : simtk.unit.Quantity

        """
        # Create topology

        atoms, residues, chains = {}, {}, {}
        topology = openmm_app.Topology()
        for i, mol in enumerate(molecules):
            for a in mol.atoms:
                chain_id = (i, a.residue.id.chainId)
                try:
                    chain = chains[chain_id]
                except KeyError:
                    chain = chains[chain_id] = topology.addChain()

                r = a.residue
                try:
                    residue = residues[r]
                except KeyError:
                    residue = residues[r] = topology.addResidue(r.type, chain)
                name = a.name
                element = openmm_app.Element.getByAtomicNumber(
                    a.element.number)
                serial = a.serialNumber
                atoms[a] = topology.addAtom(name, element, residue, serial)

            for b in mol.bonds:
                topology.addBond(atoms[b.atoms[0]], atoms[b.atoms[1]])

        return topology
Beispiel #12
0
def save_coords(saveas, xyz_ply, box_edge_nm):
    # create polymer topology
    topology = app.Topology()
    chain = topology.addChain()

    for i in range(len(xyz_ply)):
        res = topology.addResidue("PLY", chain)
        atm = topology.addAtom("PL", app.element.get_by_symbol("Pl"), res)
        if i == 0:
            prev_atm = atm
        else:
            topology.addBond(prev_atm, atm)
            prev_atm = atm

    positions = unit.Quantity(xyz_ply, unit.nanometer)

    topology.setUnitCellDimensions(box_edge_nm * omm.Vec3(1, 1, 1))

    pdb = app.PDBFile("dum.pdb")
    with open(saveas, "w") as fout:
        pdb.writeFile(topology, positions, file=fout)
Beispiel #13
0
def test_mutate_from_every_amino_to_every_other():
    """
    Make sure mutations are successful between every possible pair of before-and-after residues
    Mutate Ecoli F-ATPase alpha subunit to all 20 amino acids (test going FROM all possibilities)
    Mutate each residue to all 19 alternatives
    """
    import perses.rjmc.topology_proposal as topology_proposal

    aminos = [
        'ALA', 'ARG', 'ASN', 'ASP', 'CYS', 'GLN', 'GLU', 'GLY', 'HIS', 'ILE',
        'LEU', 'LYS', 'MET', 'PHE', 'PRO', 'SER', 'THR', 'TRP', 'TYR', 'VAL'
    ]

    failed_mutants = 0

    pdbid = "2A7U"
    topology, positions = load_pdbid_to_openmm(pdbid)
    modeller = app.Modeller(topology, positions)
    for chain in modeller.topology.chains():
        pass

    modeller.delete([chain])

    ff_filename = "amber99sbildn.xml"
    max_point_mutants = 1

    ff = app.ForceField(ff_filename)
    system = ff.createSystem(modeller.topology)
    chain_id = 'A'

    metadata = dict()

    system_generator = topology_proposal.SystemGenerator([ff_filename])

    pm_top_engine = topology_proposal.PointMutationEngine(
        modeller.topology,
        system_generator,
        chain_id,
        proposal_metadata=metadata,
        max_point_mutants=max_point_mutants,
        always_change=True)

    current_system = system
    current_topology = modeller.topology
    current_positions = modeller.positions

    pm_top_engine._allowed_mutations = list()
    for k, proposed_amino in enumerate(aminos):
        pm_top_engine._allowed_mutations.append((str(k + 2), proposed_amino))
    pm_top_proposal = pm_top_engine.propose(current_system, current_topology)
    current_system = pm_top_proposal.new_system
    current_topology = pm_top_proposal.new_topology

    for chain in current_topology.chains():
        if chain.id == chain_id:
            # num_residues : int
            num_residues = len(chain._residues)
            break
    new_sequence = list()
    for residue in current_topology.residues():
        if residue.index == 0:
            continue
        if residue.index == (num_residues - 1):
            continue
        if residue.name in ['HID', 'HIE']:
            residue.name = 'HIS'
        new_sequence.append(residue.name)
    for i in range(len(aminos)):
        assert new_sequence[i] == aminos[i]

    pm_top_engine = topology_proposal.PointMutationEngine(
        current_topology,
        system_generator,
        chain_id,
        proposal_metadata=metadata,
        max_point_mutants=max_point_mutants)

    from perses.rjmc.topology_proposal import append_topology
    old_topology = app.Topology()
    append_topology(old_topology, current_topology)
    new_topology = app.Topology()
    append_topology(new_topology, current_topology)

    old_chemical_state_key = pm_top_engine.compute_state_key(old_topology)

    for chain in new_topology.chains():
        if chain.id == chain_id:
            # num_residues : int
            num_residues = len(chain._residues)
            break
    for proposed_location in range(1, num_residues - 1):
        print('Making mutations at residue %s' % proposed_location)
        original_residue_name = chain._residues[proposed_location].name
        matching_amino_found = 0
        for proposed_amino in aminos:
            pm_top_engine._allowed_mutations = [(str(proposed_location + 1),
                                                 proposed_amino)]
            new_topology = app.Topology()
            append_topology(new_topology, current_topology)
            old_system = current_system
            old_topology_natoms = sum([1 for atom in old_topology.atoms()])
            old_system_natoms = old_system.getNumParticles()
            if old_topology_natoms != old_system_natoms:
                msg = 'PolymerProposalEngine: old_topology has %d atoms, while old_system has %d atoms' % (
                    old_topology_natoms, old_system_natoms)
                raise Exception(msg)
            metadata = dict()

            for atom in new_topology.atoms():
                atom.old_index = atom.index

            index_to_new_residues, metadata = pm_top_engine._choose_mutant(
                new_topology, metadata)
            if len(index_to_new_residues) == 0:
                matching_amino_found += 1
                continue
            print('Mutating %s to %s' %
                  (original_residue_name, proposed_amino))

            residue_map = pm_top_engine._generate_residue_map(
                new_topology, index_to_new_residues)
            for res_pair in residue_map:
                residue = res_pair[0]
                name = res_pair[1]
                assert residue.index in index_to_new_residues.keys()
                assert index_to_new_residues[residue.index] == name
                assert residue.name + '-' + str(
                    residue.id) + '-' + name in metadata['mutations']

            new_topology, missing_atoms = pm_top_engine._delete_excess_atoms(
                new_topology, residue_map)
            new_topology = pm_top_engine._add_new_atoms(
                new_topology, missing_atoms, residue_map)
            for res_pair in residue_map:
                residue = res_pair[0]
                name = res_pair[1]
                assert residue.name == name

            atom_map = pm_top_engine._construct_atom_map(
                residue_map, old_topology, index_to_new_residues, new_topology)
            templates = pm_top_engine._ff.getMatchingTemplates(new_topology)
            assert [
                templates[index].name == residue.name
                for index, (residue, name) in enumerate(residue_map)
            ]

            new_chemical_state_key = pm_top_engine.compute_state_key(
                new_topology)
            new_system = pm_top_engine._system_generator.build_system(
                new_topology)
            pm_top_proposal = topology_proposal.TopologyProposal(
                new_topology=new_topology,
                new_system=new_system,
                old_topology=old_topology,
                old_system=old_system,
                old_chemical_state_key=old_chemical_state_key,
                new_chemical_state_key=new_chemical_state_key,
                logp_proposal=0.0,
                new_to_old_atom_map=atom_map)

        assert matching_amino_found == 1
Beispiel #14
0
def hydrate(system, opt):
    """
    This function solvates the system by using PDBFixer

    Parameters:
    -----------
    system: OEMol molecule
        The system to solvate
    opt: python dictionary
        The parameters used to solvate the system

    Return:
    -------
    oe_mol: OEMol
        The solvated system
    """
    def BoundingBox(molecule):
        """
        This function calculates the Bounding Box of the passed
        molecule

        molecule: OEMol

        return: bb (numpy array)
            the calculated bounding box is returned as numpy array:
            [(xmin,ymin,zmin), (xmax,ymax,zmax)]
        """
        coords = [v for k, v in molecule.GetCoords().items()]
        np_coords = np.array(coords)
        min_coord = np_coords.min(axis=0)
        max_coord = np_coords.max(axis=0)
        bb = np.array([min_coord, max_coord])
        return bb

    # Create a system copy
    sol_system = system.CreateCopy()

    # Calculate system BoundingBox (Angstrom units)
    BB = BoundingBox(sol_system)

    # Estimation of the box cube length in A
    box_edge = 2.0 * opt['solvent_padding'] + np.max(BB[1] - BB[0])

    # BB center
    xc = (BB[0][0]+BB[1][0])/2.
    yc = (BB[0][1]+BB[1][1])/2.
    zc = (BB[0][2]+BB[1][2])/2.

    delta = np.array([box_edge/2., box_edge/2., box_edge/2.]) - np.array([xc, yc, zc])

    sys_coord_dic = {k: (v+delta) for k, v in sol_system.GetCoords().items()}

    sol_system.SetCoords(sys_coord_dic)

    # Load a fake system to initialize PDBfixer
    filename = resource_filename('pdbfixer', 'tests/data/test.pdb')
    fixer = PDBFixer(filename=filename)

    # Convert between OE and OpenMM topology
    omm_top, omm_pos = oeommutils.oemol_to_openmmTop(sol_system)

    chain_names = []

    for chain in omm_top.chains():
        chain_names.append(chain.id)

    # Set the correct topology to the fake system
    fixer.topology = omm_top
    fixer.positions = omm_pos

    # Solvate the system
    fixer.addSolvent(padding=unit.Quantity(opt['solvent_padding'], unit.angstroms),
                     ionicStrength=unit.Quantity(opt['salt_concentration'], unit.millimolar))

    # The OpenMM topology produced by the solvation fixer has missing bond
    # orders and aromaticity. The following section is creating a new openmm
    # topology made of just water molecules and ions. The new topology is then
    # converted in an OEMol and added to the passed molecule to produce the
    # solvated system

    wat_ion_top = app.Topology()

    # Atom dictionary between the the PDBfixer topology and the water_ion topology
    fixer_atom_to_wat_ion_atom = {}

    for chain in fixer.topology.chains():
        if chain.id not in chain_names:
            n_chain = wat_ion_top.addChain(chain.id)
            for res in chain.residues():
                n_res = wat_ion_top.addResidue(res.name, n_chain)
                for at in res.atoms():
                    n_at = wat_ion_top.addAtom(at.name, at.element, n_res)
                    fixer_atom_to_wat_ion_atom[at] = n_at

    for bond in fixer.topology.bonds():
        at0 = bond[0]
        at1 = bond[1]
        try:
            wat_ion_top.addBond(fixer_atom_to_wat_ion_atom[at0],
                                fixer_atom_to_wat_ion_atom[at1], type=None, order=1)
        except:
            pass

    wat_ion_pos = fixer.positions[len(omm_pos):]

    oe_mol = oeommutils.openmmTop_to_oemol(wat_ion_top, wat_ion_pos)

    # Setting the box vectors
    omm_box_vectors = fixer.topology.getPeriodicBoxVectors()
    box_vectors = utils.PackageOEMol.encodePyObj(omm_box_vectors)
    oe_mol.SetData(oechem.OEGetTag('box_vectors'), box_vectors)

    oechem.OEAddMols(oe_mol, sol_system)

    return oe_mol
    def __init__(self,
                 n_particles=1,
                 mass=100 * unit.amu,
                 Eo=3.0 * unit.kilocalories_per_mole,
                 a=0.5 * unit.nanometers,
                 b=0.5 * unit.kilocalories_per_mole,
                 k=1.0 * unit.kilocalories_per_mole / unit.angstroms**2,
                 coordinates=None):
        """Creating a new instance of DoubleWell

        A new test system is returned with the openmm system of particles in an external double
        well potential.

        Parameters
        ----------

        n_particles: int
            Number of particles in the system
        mass: unit.Quantity
            Mass of the particles (in units of mass).
        Eo: unit.Quantity
            Parameter of the external potential with units of energy.
        a: unit.Quantity
            Parameter of the external potential with units of length.
        b: unit.Quantity
            Parameter of the external potential with units of energy.
        k: unit.Quantity
            Parameter of the external potential with units of energy/length^2.

        Examples
        --------

        >>> from uibcdf_test_systems import DoubleWell
        >>> from simtk import unit
        >>> double_well = DoubleWell(n_particles = 1, mass = 64 * unit.amu, Eo=4.0 * unit.kilocalories_per_mole, a=1.0 * unit.nanometers, b=0.0 * unit.kilocalories_per_mole, k=1.0 * unit.kilocalories_per_mole/unit.angstroms**2))

        Notes
        -----

        See `corresponding documentation in the user guide regarding this class
        <../../systems/double_well_potential.html>`_.

        """

        super().__init__()

        # Parameters

        self.parameters = {}
        self.parameters['n_particles'] = n_particles
        self.parameters['mass'] = mass
        self.parameters['Eo'] = Eo
        self.parameters['a'] = a
        self.parameters['b'] = b
        self.parameters['k'] = k

        # OpenMM topology

        self.topology = app.Topology()

        try:
            dummy_element = app.element.get_by_symbol('DUM')
        except:
            dummy_element = app.Element(0, 'DUM', 'DUM', 0.0 * unit.amu)

        dummy_element.mass._value = mass.value_in_unit(unit.amu)

        chain = self.topology.addChain('A')
        for _ in range(n_particles):
            residue = self.topology.addResidue('DUM', chain)
            atom = self.topology.addAtom(name='DUM',
                                         element=dummy_element,
                                         residue=residue)

        # OpenMM system

        self.system = mm.System()

        for _ in range(n_particles):
            self.system.addParticle(dummy_element.mass)

        A = Eo / (a**4)
        B = -2.0 * Eo / (a**2)
        C = -b / a
        D = k / 2.0

        force = mm.CustomExternalForce('A*x^4+B*x^2+C*x + D*(y^2+z^2)')
        force.addGlobalParameter('A', A)
        force.addGlobalParameter('B', B)
        force.addGlobalParameter('C', C)
        force.addGlobalParameter('D', D)

        for ii in range(n_particles):
            force.addParticle(ii, [])
        _ = self.system.addForce(force)

        # Coordinates

        if coordinates is None:
            coordinates = np.zeros([self.parameters['n_particles'], 3],
                                   np.float32) * unit.nanometers

        self.set_coordinates(coordinates)

        # Potential expresion and constants

        x, y, z, Eo, a, b, k = sy.symbols('x y z Eo a b k')
        self.potential_expression = Eo * (
            (x / a)**4 - 2.0 *
            (x / a)**2) - (b / a) * x + 0.5 * k * (y**2 + z**2)
        del (x, y, z, Eo, a, b, k)
Beispiel #16
0
def generate_topology(non_omm_topology, non_element_types=None):
    if non_element_types is None:
        non_element_types = set()

    topology = app.Topology()
    chain = topology.addChain()
    if isinstance(non_omm_topology, pmd.Structure):
        residue = topology.addResidue(non_omm_topology.title, chain)
        atoms = dict()  # pmd.Atom: omm.Atom

        # Create atoms in the residue.
        for pmd_atom in non_omm_topology.atoms:
            name = pmd_atom.name
            if pmd_atom.element in non_element_types:
                element = non_element_types[pmd_atom.element]
            else:
                if pmd_atom.atomic_number != 0:
                    element = elem.Element.getByAtomicNumber(
                        pmd_atom.atomic_number)
                else:  # TODO: more robust element detection or enforcement of symbols
                    element = elem.Element.getBySymbol(pmd_atom.name)

            omm_atom = topology.addAtom(name, element, residue)
            atoms[pmd_atom] = omm_atom
            omm_atom.bond_partners = []

        # Create bonds.
        for bond in non_omm_topology.bonds:
            atom1 = atoms[bond.atom1]
            atom2 = atoms[bond.atom2]
            topology.addBond(atom1, atom2)
            atom1.bond_partners.append(atom2)
            atom2.bond_partners.append(atom1)
        if non_omm_topology.box_vectors and np.any(
            [x._value for x in non_omm_topology.box_vectors]):
            topology.setPeriodicBoxVectors(non_omm_topology.box_vectors)

    elif isinstance(non_omm_topology, mb.Compound):
        residue = topology.addResidue(non_omm_topology.name, chain)
        atoms = dict()  # mb.Particle: omm.Atom

        # Create atoms in the residue.
        for mb_particle in non_omm_topology.particles():
            name = mb_particle.name
            if mb_particle.name in non_element_types:
                element = non_element_types[mb_particle.name]
            else:
                element = elem.Element.getBySymbol(mb_particle.name)

            omm_atom = topology.addAtom(name, element, residue)
            atoms[mb_particle] = omm_atom
            omm_atom.bond_partners = []

        # Create bonds.
        for bond in non_omm_topology.bonds():
            atom1 = atoms[bond[0]]
            atom2 = atoms[bond[1]]
            topology.addBond(atom1, atom2)
            atom1.bond_partners.append(atom2)
            atom2.bond_partners.append(atom1)
        bounding_box = non_omm_topology.boundingbox
        box_vectors = np.zeros(shape=(3, 3))
        box_vectors[0, 0] = non_omm_topology.periodicity[0] or bounding_box[0]
        box_vectors[1, 1] = non_omm_topology.periodicity[1] or bounding_box[1]
        box_vectors[2, 2] = non_omm_topology.periodicity[2] or bounding_box[2]
        topology.setPeriodicBoxVectors(box_vectors)
    else:
        raise FoyerError('Unknown topology format: {}\n'
                         'Supported formats are: '
                         '"parmed.Structure", '
                         '"mbuild.Compound", '
                         '"openmm.app.Topology"'.format(topology))
    return topology
Beispiel #17
0
def distributeLipids(boxsize,
                     resnames,
                     sigmas,
                     cutoff,
                     mass=39.9 * unit.amu,  # argon
                     epsilon=0.238 * unit.kilocalories_per_mole,  # argon,
                     switch_width=3.4 * unit.angstrom,  # argon
                     ):
        nparticles = len(resnames)
                
        # Determine Lennard-Jones cutoff.
        cutoff = cutoff * unit.angstrom

        cutoff_type = openmm.NonbondedForce.CutoffPeriodic

        # Create an empty system object.
        system = openmm.System()

        # Periodic box vectors.
        a = unit.Quantity((boxsize[0] * unit.angstrom, 0 * unit.angstrom, 0 * unit.angstrom))
        b = unit.Quantity((0 * unit.angstrom, boxsize[1] * unit.angstrom, 0 * unit.angstrom))
        c = unit.Quantity((0 * unit.angstrom, 0 * unit.angstrom, boxsize[2] * unit.angstrom))
        system.setDefaultPeriodicBoxVectors(a, b, c)

        # Set up periodic nonbonded interactions with a cutoff.
        nb = openmm.NonbondedForce()
        nb.setNonbondedMethod(cutoff_type)
        nb.setCutoffDistance(cutoff)
        nb.setUseDispersionCorrection(True)

        nb.setUseSwitchingFunction(False)
        if (switch_width is not None):
            nb.setUseSwitchingFunction(True)
            nb.setSwitchingDistance(cutoff - switch_width)

        for s in sigmas:
            system.addParticle(mass)
            nb.addParticle(0.0 * unit.elementary_charge, s * unit.angstrom, epsilon)

        positions = subrandom_particle_positions(nparticles, system.getDefaultPeriodicBoxVectors(), 2)

        # Add the nonbonded force.
        system.addForce(nb)

        # Add a restraining potential to keep atoms in z=0
        energy_expression = 'k * (z^2)'
        force = openmm.CustomExternalForce(energy_expression)
        force.addGlobalParameter('k', 10)
        for particle_index in range(nparticles):
            force.addParticle(particle_index, [])
        system.addForce(force)

        # Create topology.
        topology = app.Topology()
        chain = topology.addChain()
        elems = ['Ar', 'Cl', 'Na']
        _, idx = np.unique(resnames, return_inverse=True)
        for i in idx:
            element = app.Element.getBySymbol(elems[i])
            residue = topology.addResidue(elems[i], chain)
            topology.addAtom(elems[i], element, residue)

        topology.setUnitCellDimensions(unit.Quantity(boxsize, unit.angstrom)) 
            
        # Simulate it
        from simtk.openmm import LangevinIntegrator, VerletIntegrator
        from simtk.openmm.app import Simulation, PDBReporter, StateDataReporter, PDBFile
        from simtk.unit import kelvin, picoseconds, picosecond, angstrom
        from sys import stdout
        from mdtraj.reporters import DCDReporter
        nsteps = 10000
        freq = 1

        integrator = VerletIntegrator(0.002 * picoseconds)
        simulation = Simulation(topology, system, integrator)
        simulation.context.setPositions(positions)
        simulation.minimizeEnergy()
        # simulation.reporters.append(DCDReporter('output.dcd', 1))
        # simulation.reporters.append(StateDataReporter(stdout, 1000, potentialEnergy=True, totalEnergy=True, step=True, separator='   '))
        simulation.step(nsteps)

        state = simulation.context.getState(getPositions=True, enforcePeriodicBox=True)
        allfinalpos = state.getPositions(asNumpy=True).value_in_unit(angstrom)

        # with open('topology.pdb', 'w') as f:
        #     PDBFile.writeFile(topology, positions, f)

        # from htmd.molecule.molecule import Molecule
        # mol = Molecule('topology.pdb')
        # mol.read('output.dcd')

        return allfinalpos
Beispiel #18
0
def prep_system(box_width):
    # if model not in supported_models:
    # raise Exception("Specified water model '%s' is not in list of supported models: %s" % (model, str(supported_models)))

    # Load forcefield for solvent model and ions.
    # force_fields = ['tip3p.xml']
    # if ionic_strength != 0.0*unit.molar:
    # force_fields.append('amber99sb.xml')  # For the ions.
    ff = app.ForceField('tip3p.xml')

    # Create empty topology and coordinates.
    top = app.Topology()
    pos = unit.Quantity((), unit.angstroms)

    # Create new Modeller instance.
    m = app.Modeller(top, pos)

    boxSize = Vec3(box_width, box_width, box_width) * unit.nanometers
    # boxSize = unit.Quantity(numpy.ones([3]) * box_edge / box_edge.unit, box_edge.unit)
    m.addSolvent(ff, boxSize=boxSize, model='tip3p')

    system = ff.createSystem(m.getTopology(),
                             nonbondedMethod=app.NoCutoff,
                             constraints=None,
                             rigidWater=False)

    positions = m.getPositions()

    positions = unit.Quantity(np.array(positions / positions.unit),
                              positions.unit)

    # pdb_str = io.StringIO()
    fname = "debug.pdb"

    fhandle = open(fname, "w")

    PDBFile.writeHeader(m.getTopology(), fhandle)
    PDBFile.writeModel(m.getTopology(), positions, fhandle, 0)
    PDBFile.writeFooter(m.getTopology(), fhandle)

    return system, positions, np.eye(3) * box_width, fname

    assert 0

    # , positiveIon=positive_ion,
    # negativeIon=negative_ion, ionicStrength=ionic_strength)

    # Get new topology and coordinates.
    newtop = m.getTopology()
    newpos = m.getPositions()

    # Convert positions to numpy.
    positions = unit.Quantity(numpy.array(newpos / newpos.unit), newpos.unit)

    # Create OpenMM System.
    system = ff.createSystem(newtop,
                             nonbondedMethod=nonbondedMethod,
                             nonbondedCutoff=cutoff,
                             constraints=None,
                             rigidWater=constrained,
                             removeCMMotion=False)

    # Set switching function and dispersion correction.
    forces = {
        system.getForce(index).__class__.__name__: system.getForce(index)
        for index in range(system.getNumForces())
    }

    forces['NonbondedForce'].setUseSwitchingFunction(False)
    if switch_width is not None:
        forces['NonbondedForce'].setUseSwitchingFunction(True)
        forces['NonbondedForce'].setSwitchingDistance(cutoff - switch_width)

    forces['NonbondedForce'].setUseDispersionCorrection(dispersion_correction)
    forces['NonbondedForce'].setEwaldErrorTolerance(ewaldErrorTolerance)

    n_atoms = system.getNumParticles()
    self.ndof = 3 * n_atoms - (constrained * n_atoms)

    self.topology = m.getTopology()
    self.system = system
    self.positions = positions
Beispiel #19
0
    def __init__(self, nx=3, ny=3, nz=3,
                 K=100.0, b=2.0, mass=39.948 * unit.amu, well_radius=1.0,
                 grid_spacing=1.0 * unit.angstrom,
                 coupling_strength=100.0 * unit.kilocalories_per_mole / unit.angstrom,
                 **kwargs):
        """Initialize particles on a 3D grid of specified size.

        Parameters
        ----------
        nx, ny, nz : ints
            number of particles in x, y, z directions, respectively
        K : float
            well depth
        b : float
            exponent
        mass : simtk.unit.Quantity
            particle mass
        grid_spacing : simtk.unit.Quantity
            increment between grid points
        coupling_strength : simtk.unit.quantity
            strength of HarmonicBond force between each neighboring pair of particles

        Attributes
        ----------
        topology, positions, system
        """

        # 1. Initialize
        # 2. Set particles on a 3D grid, use a CustomExternalForce to place each particle in a well
        # 3. Add a HarmonicBondForce to each neighboring pair of particles.


        ### 1. Initialize

        TestSystem.__init__(self, **kwargs)
        # Set unit of well-depth appropriately
        #K *= unit.kilocalories_per_mole / unit.angstroms ** b

        # Determine total number of atoms.
        natoms = nx * ny * nz

        # Create an empty system object.
        system = openmm.System()

        ### 2. Put particles on a 3D grid

        positions = unit.Quantity(np.zeros([natoms, 3], np.float32), unit.angstrom)

        atom_index = 0

        # Store the atom indices in a 3-way array
        # so that we can conveniently determine nearest neighbors
        atom_indices = np.zeros((nx, ny, nz), dtype=int)
        energy_expression = "{K} * (sqrt((x - x0)^2 + (y - y0)^2 + (z - z0)^2) / {r})^{b};".format(
            b=b, K=K, r=well_radius)
        force = openmm.CustomExternalForce(energy_expression)
        force.addPerParticleParameter("x0")
        force.addPerParticleParameter("y0")
        force.addPerParticleParameter("z0")

        for i in range(nx):
            for j in range(ny):
                for k in range(nz):
                    system.addParticle(mass)

                    xyz = (grid_spacing.value_in_unit(unit.angstrom)) * np.array([i, j, k], dtype=float)
                    positions[atom_index] = (xyz + np.random.randn(3)*0.01) * unit.angstrom

                    atom_indices[i, j, k] = atom_index

                    # Add this particle's well
                    force.addParticle(atom_index, xyz)

                    atom_index += 1
        system.addForce(force)

        ### 3. Couple each pair of neighbors

        # Find each pair of neighbors in this grid.
        # Connect each particle (i,j,k), to its "forward" neighbors,
        #   (i+1, j, k), (i, j+1, k), (i, j, k+1),
        # (if they exist)
        bonds = []
        for i in range(nx):
            for j in range(ny):
                for k in range(nz):
                    if (i + 1) < nx:
                        bonds.append((atom_indices[i, j, k], atom_indices[i + 1, j, k]))
                    if (j + 1) < ny:
                        bonds.append((atom_indices[i, j, k], atom_indices[i, j + 1, k]))
                    if (k + 1) < nz:
                        bonds.append((atom_indices[i, j, k], atom_indices[i, j, k + 1]))

        # Add these HarmonicBondForces to the system
        force = openmm.HarmonicBondForce()
        for bond in bonds:
            force.addBond(int(bond[0]), int(bond[1]), grid_spacing, coupling_strength)
        system.addForce(force)

        # Create topology.
        topology = app.Topology()
        element = app.Element.getBySymbol('Ar')
        chain = topology.addChain()
        for particle in range(system.getNumParticles()):
            residue = topology.addResidue('Ar', chain)
            topology.addAtom('Ar', element, residue)

        # Set topology, positions, system as instance attributes
        self.topology = topology
        self.positions = positions
        self.system = system
Beispiel #20
0
    def _addAtomsToTopology(self, heavyAtomsOnly, omitUnknownMolecules):
        """Create a new Topology in which missing atoms have been added."""
        
        newTopology = app.Topology()
        newPositions = []*unit.nanometer
        newAtoms = []
        existingAtomMap = {}
        addedAtomMap = {}
        addedOXT = []
        for chain in self.topology.chains():
            if omitUnknownMolecules and not any(residue.name in self.templates for residue in chain.residues()):
                continue
            chainResidues = list(chain.residues())
            newChain = newTopology.addChain()
            for indexInChain, residue in enumerate(chain.residues()):
                
                # Insert missing residues here.
                
                if (chain.index, indexInChain) in self.missingResidues:
                    insertHere = self.missingResidues[(chain.index, indexInChain)]
                    endPosition = self._computeResidueCenter(residue)
                    if indexInChain > 0:
                        startPosition = self._computeResidueCenter(chainResidues[indexInChain-1])
                    else:
                        outward = endPosition-self.centroid
                        norm = unit.norm(outward)
                        if norm > 0*unit.nanometer:
                            outward *= len(insertHere)*0.5*unit.nanometer/norm
                        startPosition = endPosition+outward
                    self._addMissingResiduesToChain(newChain, insertHere, startPosition, endPosition, residue, newAtoms, newPositions)
                
                # Create the new residue and add existing heavy atoms.
                                
                newResidue = newTopology.addResidue(residue.name, newChain)
                addResiduesAfter = (residue == chainResidues[-1] and (chain.index, indexInChain+1) in self.missingResidues)
                for atom in residue.atoms():
                    if not heavyAtomsOnly or (atom.element is not None and atom.element != hydrogen):
                        if atom.name == 'OXT' and (chain.index, indexInChain+1) in self.missingResidues:
                            continue # Remove terminal oxygen, since we'll add more residues after this one
                        newAtom = newTopology.addAtom(atom.name, atom.element, newResidue)
                        existingAtomMap[atom] = newAtom
                        newPositions.append(self.positions[atom.index])
                if residue in self.missingAtoms:
                    
                    # Find corresponding atoms in the residue and the template.
                    
                    template = self.templates[residue.name]
                    atomPositions = dict((atom.name, self.positions[atom.index]) for atom in residue.atoms())
                    points1 = []
                    points2 = []
                    for atom in template.topology.atoms():
                        if atom.name in atomPositions:
                            points1.append(atomPositions[atom.name].value_in_unit(unit.nanometer))
                            points2.append(template.positions[atom.index].value_in_unit(unit.nanometer))
                    
                    # Compute the optimal transform to overlay them.
                    
                    (translate2, rotate, translate1) = _overlayPoints(points1, points2)
                    
                    # Add the missing atoms.
                    
                    addedAtomMap[residue] = {}
                    for atom in self.missingAtoms[residue]:
                        newAtom = newTopology.addAtom(atom.name, atom.element, newResidue)
                        newAtoms.append(newAtom)
                        addedAtomMap[residue][atom] = newAtom
                        templatePosition = template.positions[atom.index].value_in_unit(unit.nanometer)
                        newPositions.append((mm.Vec3(*np.dot(rotate, templatePosition+translate2))+translate1)*unit.nanometer)
                if residue in self.missingTerminals:
                    terminalsToAdd = self.missingTerminals[residue]
                else:
                    terminalsToAdd = None

                # If this is the end of the chain, add any missing residues that come after it.
                
                if residue == chainResidues[-1] and (chain.index, indexInChain+1) in self.missingResidues:
                    insertHere = self.missingResidues[(chain.index, indexInChain+1)]
                    if len(insertHere) > 0:
                        startPosition = self._computeResidueCenter(residue)
                        outward = startPosition-self.centroid
                        norm = unit.norm(outward)
                        if norm > 0*unit.nanometer:
                            outward *= len(insertHere)*0.5*unit.nanometer/norm
                        endPosition = startPosition+outward
                        self._addMissingResiduesToChain(newChain, insertHere, startPosition, endPosition, residue, newAtoms, newPositions)
                        newResidue = list(newChain.residues())[-1]
                        if newResidue.name in proteinResidues:
                            terminalsToAdd = ['OXT']
                        else:
                            terminalsToAdd = None
                
                # If a terminal OXT is missing, add it.
                
                if terminalsToAdd is not None:
                    atomPositions = dict((atom.name, newPositions[atom.index].value_in_unit(unit.nanometer)) for atom in newResidue.atoms())
                    if 'OXT' in terminalsToAdd:
                        newAtom = newTopology.addAtom('OXT', oxygen, newResidue)
                        newAtoms.append(newAtom)
                        addedOXT.append(newAtom)
                        d_ca_o = atomPositions['O']-atomPositions['CA']
                        d_ca_c = atomPositions['C']-atomPositions['CA']
                        d_ca_c /= unit.sqrt(unit.dot(d_ca_c, d_ca_c))
                        v = d_ca_o - d_ca_c*unit.dot(d_ca_c, d_ca_o)
                        newPositions.append((atomPositions['O']+2*v)*unit.nanometer)
        newTopology.setUnitCellDimensions(self.topology.getUnitCellDimensions())
        newTopology.createStandardBonds()
        newTopology.createDisulfideBonds(newPositions)
        
        # Return the results.
        
        return (newTopology, newPositions, newAtoms, existingAtomMap)
Beispiel #21
0
    def __init__(self,
                 atom_1='Ar',
                 atom_2='Xe',
                 mass_1=None,
                 sigma_1=None,
                 epsilon_1=None,
                 mass_2=None,
                 sigma_2=None,
                 epsilon_2=None,
                 cutoff_distance=None,
                 switching_distance=None,
                 box=None,
                 coordinates=None):

        super().__init__()

        # Parameters

        if (mass_1 is not None) or (sigma_1 is not None) or (epsilon_1
                                                             is not None):
            if mass_1 is None:
                raise ValueError(
                    'A value for the input argument "mass_1" is needed.')
            if sigma_1 is None:
                raise ValueError(
                    'A value for the input argument "sigma_1" is needed.')
            if epsilon_1 is None:
                raise ValueError(
                    'A value for the input argument "epsilon_1" is needed.')
        elif atom_1 is not None:
            mass_1 = atoms_LJ[atom_1]['mass']
            sigma_1 = atoms_LJ[atom_1]['sigma']
            epsilon_1 = atoms_LJ[atom_1]['epsilon']

        if (mass_2 is not None) or (sigma_2 is not None) or (epsilon_2
                                                             is not None):
            if mass_2 is None:
                raise ValueError(
                    'A value for the input argument "mass_2" is needed.')
            if sigma_2 is None:
                raise ValueError(
                    'A value for the input argument "sigma_2" is needed.')
            if epsilon_2 is None:
                raise ValueError(
                    'A value for the input argument "epsilon_2" is needed.')
        elif atom_2 is not None:
            mass_2 = atoms_LJ[atom_2]['mass']
            sigma_2 = atoms_LJ[atom_2]['sigma']
            epsilon_2 = atoms_LJ[atom_2]['epsilon']

        self.parameters['mass_1'] = mass_1
        self.parameters['sigma_1'] = sigma_1
        self.parameters['epsilon_1'] = epsilon_1

        self.parameters['mass_2'] = mass_2
        self.parameters['sigma_2'] = sigma_2
        self.parameters['epsilon_2'] = epsilon_2

        if box is not None:

            reduced_sigma = self.get_reduced_sigma()

            if cutoff_distance is None:
                cutoff_distance = 4.0 * reduced_sigma

            if switching_distance is None:
                switching_distance = 3.0 * reduced_sigma

        self.parameters['box'] = box
        self.parameters['cutoff_distance'] = cutoff_distance
        self.parameters['switching_distance'] = switching_distance

        # OpenMM topology

        self.topology = app.Topology()

        try:
            dummy_element = app.element.get_by_symbol('DUM')
        except:
            dummy_element = app.Element(0, 'DUM', 'DUM', 0.0 * unit.amu)

        chain = self.topology.addChain('A')
        residue = self.topology.addResidue('DUM_0', chain)
        atom = self.topology.addAtom(name='DUM_0',
                                     element=dummy_element,
                                     residue=residue)
        residue = self.topology.addResidue('DUM_1', chain)
        atom = self.topology.addAtom(name='DUM_1',
                                     element=dummy_element,
                                     residue=residue)

        # OpenMM system

        self.system = mm.System()

        non_bonded_force = mm.NonbondedForce()

        if box is not None:
            non_bonded_force.setNonbondedMethod(
                mm.NonbondedForce.CutoffPeriodic)
            non_bonded_force.setUseSwitchingFunction(True)
            non_bonded_force.setCutoffDistance(cutoff_distance)
            non_bonded_force.setSwitchingDistance(switching_distance)
        else:
            non_bonded_force.setNonbondedMethod(mm.NonbondedForce.NoCutoff)

        self.system.addParticle(mass_1)
        charge_1 = 0.0 * unit.elementary_charge
        non_bonded_force.addParticle(charge_1, sigma_1, epsilon_1)

        self.system.addParticle(mass_2)
        charge_2 = 0.0 * unit.elementary_charge
        non_bonded_force.addParticle(charge_2, sigma_2, epsilon_2)

        _ = self.system.addForce(non_bonded_force)

        # Coordinates

        if coordinates is not None:
            self.set_coordinates(coordinates)

        # Box

        if box is not None:
            self.set_box(box)

        # Potential expresion

        d, eps_r, sigma_r = symbols('d eps_r sigma_r')
        self.potential_expression = 4.0 * eps_r * ((sigma_r / d)**12 -
                                                   (sigma_r / d)**6)
        del (d, eps_r, sigma_r)
Beispiel #22
0
def empty_topology():
    """Empty topology."""
    return app.Topology()
Beispiel #23
0
def build_two_residues():
    alanine_topology = app.Topology()
    alanine_positions = unit.Quantity(np.zeros((22, 3)), unit.nanometer)
    leucine_topology = app.Topology()
    leucine_positions = unit.Quantity(np.zeros((31, 3)), unit.nanometer)

    ala_chain = alanine_topology.addChain(id='A')
    leu_chain = leucine_topology.addChain(id='A')

    ala_ace = alanine_topology.addResidue('ACE', ala_chain)
    ala_res = alanine_topology.addResidue('ALA', ala_chain)
    ala_nme = alanine_topology.addResidue('NME', ala_chain)
    leu_ace = leucine_topology.addResidue('ACE', leu_chain)
    leu_res = leucine_topology.addResidue('LEU', leu_chain)
    leu_nme = leucine_topology.addResidue('NME', leu_chain)

    ala_atoms = dict()
    leu_atoms = dict()
    atom_map = dict()

    for core_atom_name, [element, position] in ace.items():
        position = np.asarray(position)
        alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom
        leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom

        ala_atom = alanine_topology.addAtom(core_atom_name, element, ala_ace)
        leu_atom = leucine_topology.addAtom(core_atom_name, element, leu_ace)

        ala_atoms['ace-' + core_atom_name] = ala_atom
        leu_atoms['ace-' + core_atom_name] = leu_atom
        atom_map[ala_atom.index] = leu_atom.index

    for core_atom_name, [element, position] in core.items():
        position = np.asarray(position)
        alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom
        leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom

        ala_atom = alanine_topology.addAtom(core_atom_name, element, ala_res)
        leu_atom = leucine_topology.addAtom(core_atom_name, element, leu_res)

        ala_atoms[core_atom_name] = ala_atom
        leu_atoms[core_atom_name] = leu_atom
        atom_map[ala_atom.index] = leu_atom.index

    for ala_atom_name, [element, position] in ala_unique.items():
        position = np.asarray(position)
        alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom
        ala_atom = alanine_topology.addAtom(ala_atom_name, element, ala_res)
        ala_atoms[ala_atom_name] = ala_atom

    for leu_atom_name, [element, position] in leu_unique.items():
        position = np.asarray(position)
        leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom
        leu_atom = leucine_topology.addAtom(leu_atom_name, element, leu_res)
        leu_atoms[leu_atom_name] = leu_atom

    for core_atom_name, [element, position] in nme.items():
        position = np.asarray(position)
        alanine_positions[len(ala_atoms.keys())] = position * unit.angstrom
        leucine_positions[len(leu_atoms.keys())] = position * unit.angstrom

        ala_atom = alanine_topology.addAtom(core_atom_name, element, ala_nme)
        leu_atom = leucine_topology.addAtom(core_atom_name, element, leu_nme)

        ala_atoms['nme-' + core_atom_name] = ala_atom
        leu_atoms['nme-' + core_atom_name] = leu_atom
        atom_map[ala_atom.index] = leu_atom.index

    for bond in core_bonds:
        alanine_topology.addBond(ala_atoms[bond[0]], ala_atoms[bond[1]])
        leucine_topology.addBond(leu_atoms[bond[0]], leu_atoms[bond[1]])
    for bond in ala_bonds:
        alanine_topology.addBond(ala_atoms[bond[0]], ala_atoms[bond[1]])
    for bond in leu_bonds:
        leucine_topology.addBond(leu_atoms[bond[0]], leu_atoms[bond[1]])

    return alanine_topology, alanine_positions, leucine_topology, leucine_positions, atom_map
Beispiel #24
0
def run(opts):
    system_xml_file = opts.system
    integrator_xml_file = opts.integrator
    coords_f = opts.coords
    platform_name = opts.platform
    deviceid = opts.device
    write_freq = opts.write_freq
    output = opts.output
    nsteps = opts.nsteps

    platform_properties = {
        'OpenCLPrecision': 'mixed',
        'OpenCLPlatformIndex': '0',
        'OpenCLDeviceIndex': '0',
        'CudaPrecision': 'mixed',
        'CudaDeviceIndex': '0',
        'CpuThreads': '1'
    }

    platform_properties['CudaDeviceIndex'] = deviceid
    platform_properties['OpenCLDeviceIndex'] = deviceid

    with open(system_xml_file, 'r') as f:
        system = openmm.XmlSerializer.deserialize(f.read())

    with open(integrator_xml_file, 'r') as f:
        integrator = openmm.XmlSerializer.deserialize(f.read())
        integrator.setRandomNumberSeed(random.randint(0, 2**16))

    platform = openmm.Platform.getPlatformByName(platform_name)
    properties = {
        key: platform_properties[key]
        for key in platform_properties
        if key.lower().startswith(platform_name.lower())
    }
    if platform_name == 'CPU':
        properties = {'CpuThreads': '1'}

    print properties

    # Create dummy topology to satisfy Simulation object
    topology = app.Topology()
    volume = wcadimer.natoms / wcadimer.density
    length = volume**(1.0 / 3.0)
    L = length.value_in_unit(units.nanometer)
    topology.setUnitCellDimensions(Vec3(L, L, L) * units.nanometer)

    simulation = app.Simulation(topology, system, integrator, platform,
                                properties)

    init_data = np.load(coords_f)

    coords = units.Quantity(init_data['coord'], units.nanometer)
    simulation.context.setPositions(coords)

    if 'veloc' in init_data:
        velocs = units.Quantity(init_data['veloc'],
                                units.nanometer / units.picosecond)
        simulation.context.setVelocities(velocs)
    else:
        simulation.context.setVelocitiesToTemperature(wcadimer.temperature)

    # Attach reporters
    simulation.reporters.append(
        HDF5Reporter(output + '.h5', write_freq, atomSubset=[0, 1]))
    simulation.reporters.append(
        app.StateDataReporter(stdout,
                              20 * write_freq,
                              step=True,
                              potentialEnergy=True,
                              temperature=True,
                              progress=True,
                              remainingTime=True,
                              speed=True,
                              totalSteps=nsteps,
                              separator='\t'))

    # Run segment
    simulation.step(nsteps)

    # Write restart data
    state = simulation.context.getState(getPositions=True, getVelocities=True)

    coords = state.getPositions(asNumpy=True)
    velocs = state.getVelocities(asNumpy=True)

    np.savez_compressed(output + '_restart.npz',
                        coords,
                        coord=coords,
                        veloc=velocs)
Beispiel #25
0
    def extract(self, chains_to_keep, extract_protein):
        '''Extract the protein or ligand from the complex and return its energy. 

		Parameters
		----------
		chains_to_keep : list of strings
			Chain id(s) to keep
		extract_protein : boolean
			If true, extract protein. Otherwise, extract ligand.

		Returns
		-------
		float
			Final energy in kcal/mol
		'''

        try:
            self.minimizedState.getPositions()
        except Exception:
            print(
                "The System has not been minimized -- you must minimize before extracting."
            )

        if not isinstance(extract_protein, bool):
            raise TypeError(
                "extract_protein should be boolean indicating whether to extract the protein (True) or ligand (False)"
            )

        ## Extract topology
        if extract_protein:
            print("\tExtracting P from PL...")
        else:
            print("\tExtracting L from PL...")

        # Create new topology
        new_topology = app.Topology()

        # Copy residues and atoms to new topology for chains_to_keep
        d_old_to_new = {
        }  # Key: atom in old topology, Value: atom in new topology
        for chain in self.complexTopology.chains():
            if chain.id in chains_to_keep:
                new_chain = new_topology.addChain(id=chain.id)
                for res in chain.residues():
                    # Copy residues and atoms
                    new_res = new_topology.addResidue(res.name,
                                                      new_chain,
                                                      id=res.id)
                    for atom in res.atoms():
                        new_atom = new_topology.addAtom(
                            atom.name, atom.element, new_res)
                        d_old_to_new[atom] = new_atom

        # Make list of atoms to delete
        atoms_to_delete = []
        for res in self.complexTopology.residues():
            if res.chain.id not in chains_to_keep:
                for atom in res.atoms():
                    atoms_to_delete.append(atom)

        # Copy bonds to new topology, except bonds involving atoms to delete
        for bond in self.complexTopology.bonds():
            atom_1 = bond[0]
            atom_2 = bond[1]
            if (atom_1 in atoms_to_delete) or (atom_2 in atoms_to_delete):
                continue
            atom_1_new = d_old_to_new[atom_1]
            atom_2_new = d_old_to_new[atom_2]
            new_topology.addBond(atom_1_new, atom_2_new)

        ## Extract the positions
        atoms = [
            atom.index for atom in self.complexTopology.atoms()
            if atom.residue.chain.id in chains_to_keep
        ]
        positions = [
            position
            for i, position in enumerate(self.minimizedState.getPositions())
            if i in atoms
        ]

        ## Extract the energy
        # Set up system
        system = self.forcefield.createSystem(
            new_topology,
            nonbondedMethod=app.CutoffNonPeriodic,
            nonbondedCutoff=1.2 * unit.nanometer,
            constraints=app.HBonds,
            hydrogenMass=4 * unit.amu,
            soluteDielectric=1,
            solventDielectric=1)

        # Set up integrator
        integrator = openmmtools.integrators.LangevinIntegrator(
            300 * unit.kelvin, 1 / unit.picosecond, 4 * unit.femtosecond)

        # Set up simulation
        simulation = app.Simulation(new_topology, system, integrator,
                                    self.platform)
        simulation.context.setPositions(positions)

        # Get the initial energy
        initial_state = simulation.context.getState(getEnergy=True,
                                                    getPositions=True)
        initial_energy = initial_state.getPotentialEnergy(
        ) / unit.kilocalories_per_mole  # before conversion: kJ/mol
        print('\t  Energy : %8.3f kcal/mol' % (initial_energy))

        if extract_protein:
            self.proteinEnergy = initial_energy
        else:
            self.ligandEnergy = initial_energy
Beispiel #26
0
import pandas as pd
import simtk.openmm.app as app
import simtk.openmm as mm
import simtk.unit as u
import mdtraj as md

# 0.2 * 1000 / 18.015

temperature = 300.0 * u.kelvin
pressure = 1.0 * u.atmospheres
stderr_tolerance = 0.0001
ionicStrength = 2.0 * u.molar

ff = app.ForceField("tip3p.xml", "amber10.xml")

mmtop = app.Topology()
positions = []
modeller = app.Modeller(mmtop, positions)
modeller.addSolvent(ff,
                    boxSize=mm.Vec3(2.2, 2.2, 2.2) * u.nanometers,
                    ionicStrength=ionicStrength)

system = ff.createSystem(modeller.topology, nonbondedMethod=app.CutoffPeriodic)

output_frequency = 125
friction = 1.0 / u.picoseconds
timestep = 2.0 * u.femtoseconds
barostat_frequency = 25
n_steps = 100000

csv_filename = "density_%d_%0.1f.csv" % (temperature / temperature.unit,
Beispiel #27
0
import atomsmm
from simtk import openmm
from simtk import unit
from simtk.openmm import app
from sys import stdout

temp = 300 * unit.kelvin
rigid_water = False
simulation_platform = 'CUDA'
pressure_computer_platform = 'CUDA'

modeller = app.Modeller(app.Topology(), [])
force_field = app.ForceField('tip3p.xml')
modeller.addSolvent(force_field, numAdded=500)
topology = modeller.getTopology()
system = force_field.createSystem(topology,
                                  nonbondedMethod=app.PME,
                                  rigidWater=rigid_water)


def platform(name):
    return [
        openmm.Platform.getPlatformByName(name),
        dict(Precision='mixed') if name == 'CUDA' else dict()
    ]


integrator = openmm.LangevinIntegrator(temp, 0.1 / unit.femtoseconds,
                                       1.0 * unit.femtosecond)
system.addForce(openmm.MonteCarloBarostat(1 * unit.atmospheres, temp, 20))
simulation = app.Simulation(topology, system, integrator,
Beispiel #28
0
def oemol_to_openmmTop(mol):
    """
    This function converts an OEMol to an openmm topology
    The OEMol coordinates are assumed to be in Angstrom unit

    Parameters:
    -----------
    mol: OEMol molecule
        The molecule to convert

    Return:
    -------
    topology : OpenMM Topology
        The generated OpenMM topology
    positions : OpenMM Quantity
        The molecule atom positions associated with the
        generated topology in Angstrom units
    """
    # OE Hierarchical molecule view
    hv = oechem.OEHierView(
        mol, oechem.OEAssumption_BondedResidue +
        oechem.OEAssumption_ResPerceived + oechem.OEAssumption_PDBOrder)

    # Create empty OpenMM Topology
    topology = app.Topology()
    # Dictionary used to map oe atoms to openmm atoms
    oe_atom_to_openmm_at = {}

    for chain in hv.GetChains():

        # Create empty OpenMM Chain
        openmm_chain = topology.addChain(chain.GetChainID())

        for frag in chain.GetFragments():

            for hres in frag.GetResidues():

                # Get OE residue
                oe_res = hres.GetOEResidue()
                # Create OpenMM residue
                openmm_res = topology.addResidue(oe_res.GetName(),
                                                 openmm_chain)

                for oe_at in hres.GetAtoms():
                    # Select atom element based on the atomic number
                    element = app.element.Element.getByAtomicNumber(
                        oe_at.GetAtomicNum())
                    # Add atom OpenMM atom to the topology
                    openmm_at = topology.addAtom(oe_at.GetName(), element,
                                                 openmm_res)
                    openmm_at.index = oe_at.GetIdx()
                    # Add atom to the mapping dictionary
                    oe_atom_to_openmm_at[oe_at] = openmm_at

    if topology.getNumAtoms() != mol.NumAtoms():
        raise ValueError(
            "OpenMM topology and OEMol number of atoms mismatching: "
            "OpenMM = {} vs OEMol  = {}".format(topology.getNumAtoms(),
                                                mol.NumAtoms()))

    # Count the number of bonds in the openmm topology
    omm_bond_count = 0

    def IsAmideBond(oe_bond):

        # This supporting function checks if the passed bond is an amide bond or not.
        # Our definition of amide bond C-N between a Carbon and a Nitrogen atom is:
        #          O
        #          ║
        #  CA or O-C-N-
        #            |

        # The amide bond C-N is a single bond
        if oe_bond.GetOrder() != 1:
            return False

        atomB = oe_bond.GetBgn()
        atomE = oe_bond.GetEnd()

        # The amide bond is made by Carbon and Nitrogen atoms
        if not (atomB.IsCarbon() and atomE.IsNitrogen() or
                (atomB.IsNitrogen() and atomE.IsCarbon())):
            return False

        # Select Carbon and Nitrogen atoms
        if atomB.IsCarbon():
            C_atom = atomB
            N_atom = atomE
        else:
            C_atom = atomE
            N_atom = atomB

        # Carbon and Nitrogen atoms must have 3 neighbour atoms
        if not (C_atom.GetDegree() == 3 and N_atom.GetDegree() == 3):
            return False

        double_bonds = 0
        single_bonds = 0

        for bond in C_atom.GetBonds():
            # The C-O bond can be single or double.
            if (bond.GetBgn() == C_atom and bond.GetEnd().IsOxygen()) or \
                    (bond.GetBgn().IsOxygen() and bond.GetEnd() == C_atom):
                if bond.GetOrder() == 2:
                    double_bonds += 1
                if bond.GetOrder() == 1:
                    single_bonds += 1
            # The CA-C bond is single
            if (bond.GetBgn() == C_atom and bond.GetEnd().IsCarbon()) or \
                    (bond.GetBgn().IsCarbon() and bond.GetEnd() == C_atom):
                if bond.GetOrder() == 1:
                    single_bonds += 1
        # Just one double and one single bonds are connected to C
        # In this case the bond is an amide bond
        if double_bonds == 1 and single_bonds == 1:
            return True
        else:
            return False

    # Creating bonds
    for oe_bond in mol.GetBonds():

        omm_bond_count += 1

        # Set the bond type
        if oe_bond.GetType() is not "":
            if oe_bond.GetType() in [
                    'Single', 'Double', 'Triple', 'Aromatic', 'Amide'
            ]:
                omm_bond_type = oe_bond.GetType()
            else:
                omm_bond_type = None
        else:
            if oe_bond.IsAromatic():
                oe_bond.SetType("Aromatic")
                omm_bond_type = "Aromatic"
            elif oe_bond.GetOrder() == 2:
                oe_bond.SetType("Double")
                omm_bond_type = "Double"
            elif oe_bond.GetOrder() == 3:
                oe_bond.SetType("Triple")
                omm_bond_type = "Triple"
            elif IsAmideBond(oe_bond):
                oe_bond.SetType("Amide")
                omm_bond_type = "Amide"
            elif oe_bond.GetOrder() == 1:
                oe_bond.SetType("Single")
                omm_bond_type = "Single"
            else:
                omm_bond_type = None

        topology.addBond(oe_atom_to_openmm_at[oe_bond.GetBgn()],
                         oe_atom_to_openmm_at[oe_bond.GetEnd()],
                         type=omm_bond_type,
                         order=oe_bond.GetOrder())

    if omm_bond_count != mol.NumBonds():
        raise ValueError(
            "OpenMM topology and OEMol number of bonds mismatching: "
            "OpenMM = {} vs OEMol  = {}".format(omm_bond_count,
                                                mol.NumBonds()))

    dic = mol.GetCoords()
    positions = [Vec3(v[0], v[1], v[2])
                 for k, v in dic.items()] * unit.angstrom

    return topology, positions
    def __init__(self,
                 box_edge=25.0 * unit.angstroms,
                 cutoff=9 * unit.angstroms,
                 model='tip3p',
                 switch_width=1.5 * unit.angstroms,
                 constrained=True,
                 dispersion_correction=True,
                 nonbondedMethod=app.PME,
                 ewaldErrorTolerance=5E-4,
                 **kwargs):
        """
        Create a water box test system.
        Parameters
        ----------
        box_edge : simtk.unit.Quantity with units compatible with nanometers, optional, default = 2.5 nm
           Edge length for cubic box [should be greater than 2*cutoff]
        cutoff : simtk.unit.Quantity with units compatible with nanometers, optional, default = 0.9 nm
           Nonbonded cutoff
        model : str, optional, default = 'tip3p'
           The name of the water model to use ['tip3p', 'tip4p', 'tip4pew', 'tip5p', 'spce']
        switch_width : simtk.unit.Quantity with units compatible with nanometers, optional, default = 0.5 A
           Sets the width of the switch function for Lennard-Jones.
        constrained : bool, optional, default=True
           Sets whether water geometry should be constrained (rigid water implemented via SETTLE) or flexible.
        dispersion_correction : bool, optional, default=True
           Sets whether the long-range dispersion correction should be used.
        nonbondedMethod : simtk.openmm.app nonbonded method, optional, default=app.PME
           Sets the nonbonded method to use for the water box (one of app.CutoffPeriodic, app.Ewald, app.PME).
        ewaldErrorTolerance : float, optional, default=5E-4
           The Ewald or PME tolerance.  Used only if nonbondedMethod is Ewald or PME.
        Examples
        --------
        Create a default waterbox.
        >>> waterbox = WaterBox()
        >>> [system, positions] = [waterbox.system, waterbox.positions]
        Use reaction-field electrostatics instead.
        >>> waterbox = WaterBox(nonbondedMethod=app.CutoffPeriodic)
        Control the cutoff.
        >>> waterbox = WaterBox(box_edge=3.0*unit.nanometers, cutoff=1.0*unit.nanometers)
        Use a different water model.
        >>> waterbox = WaterBox(model='spce')
        Use a five-site water model.
        >>> waterbox = WaterBox(model='tip5p')
        Turn off the switch function.
        >>> waterbox = WaterBox(switch_width=None)
        Set the switch width.
        >>> waterbox = WaterBox(switch_width=0.8*unit.angstroms)
        Turn of long-range dispersion correction.
        >>> waterbox = WaterBox(dispersion_correction=False)
        """

        TestSystem.__init__(self, **kwargs)

        supported_models = ['tip3p', 'tip4pew', 'tip5p', 'spce']
        if model not in supported_models:
            raise Exception(
                "Specified water model '%s' is not in list of supported models: %s"
                % (model, str(supported_models)))

        # Load forcefield for solvent model.
        ff = app.ForceField('gcmc.xml')

        # Create empty topology and coordinates.
        top = app.Topology()
        pos = unit.Quantity((), unit.angstroms)

        # Create new Modeller instance.
        m = app.Modeller(top, pos)

        # Add solvent to specified box dimensions.
        boxSize = unit.Quantity(
            np.ones([3]) * box_edge / box_edge.unit, box_edge.unit)
        m.addSolvent(ff,
                     boxSize=boxSize,
                     model=model,
                     neutralize=False,
                     positiveIon='Na+',
                     negativeIon='Cl-',
                     **kwargs)

        # Get new topology and coordinates.
        newtop = m.getTopology()
        newpos = m.getPositions()

        # Convert positions to np.
        positions = unit.Quantity(np.array(newpos / newpos.unit), newpos.unit)

        # Create OpenMM System.
        self.forcefieldOptions = {
            'nonbondedMethod': nonbondedMethod,
            'nonbondedCutoff': cutoff,
            'constraints': None,
            'rigidWater': constrained,
            'removeCMMotion': False
        }
        system = ff.createSystem(newtop, **(self.forcefieldOptions))

        # Set switching function and dispersion correction.
        forces = {
            system.getForce(index).__class__.__name__: system.getForce(index)
            for index in range(system.getNumForces())
        }

        forces['NonbondedForce'].setUseSwitchingFunction(False)
        if switch_width is not None:
            forces['NonbondedForce'].setUseSwitchingFunction(True)
            forces['NonbondedForce'].setSwitchingDistance(cutoff -
                                                          switch_width)

        forces['NonbondedForce'].setUseDispersionCorrection(
            dispersion_correction)
        forces['NonbondedForce'].setEwaldErrorTolerance(ewaldErrorTolerance)

        self.ndof = 3 * system.getNumParticles() - 3 * constrained

        self.topology = newtop
        self.system = system
        self.positions = positions
        self.forcefield = ff
import numpy as np
import argparse
import subprocess

# Read filename
parser = argparse.ArgumentParser(description='correct equilibrated.pdb')
parser.add_argument('name', type=str, help='name of file for which to correct')
args = parser.parse_args()
pdb = app.PDBFile(args.name)

# Get old topology and positions
old_topology = pdb.getTopology()
old_positions = pdb.positions

# Create new topology and positions
new_topology = app.Topology()
new_topology.setPeriodicBoxVectors(old_topology.getPeriodicBoxVectors())
positions_R, positions_X, positions_C, positions_D, positions_E, positions_Y = list(
), list(), list(), list(), list(), list()

# Create new chains
new_chain_R = new_topology.addChain(id="R")
new_chain_X = new_topology.addChain(id="X")
new_chain_C = new_topology.addChain(id="C")
new_chain_D = new_topology.addChain(id="D")
new_chain_E = new_topology.addChain(id="E")
new_chain_Y = new_topology.addChain(id="Y")

# Specify the starting residue ids for each chain
d_current_start = {"C": 18, "E": 1, "R": 332, "X": 1, "D": 1}