Ejemplo n.º 1
0
 def test_two_particle_vsite(self):
     """ Tests assignment of 2-particle virtual site """
     struct = pmd.Structure()
     struct.add_atom(pmd.Atom(name='C', atomic_number=6), 'RES', 1)
     struct.add_atom(pmd.Atom(name='C', atomic_number=6), 'RES', 1)
     struct.add_atom(pmd.ExtraPoint(name='EP', atomic_number=0), 'RES', 1)
     struct.bond_types.append(pmd.BondType(10, 1.0))
     struct.bond_types.append(pmd.BondType(10, 0.5))
     struct.bond_types.claim()
     struct.bonds.append(pmd.Bond(struct[0], struct[1],
                                  type=struct.bond_types[0])
     )
     struct.bonds.append(pmd.Bond(struct[1], struct[2],
                                  type=struct.bond_types[1])
     )
     # This should be a two-particle virtual site
     struct.coordinates = [[0, 0, 0], [0, 0, 1], [0, 0, 1.5]]
     system = mm.System()
     system.addParticle(struct[0].mass)
     system.addParticle(struct[1].mass)
     system.addParticle(struct[2].mass)
     struct.omm_set_virtual_sites(system)
     # Make sure the third atom is a virtual site
     self.assertTrue(system.isVirtualSite(2))
     self.assertIsInstance(system.getVirtualSite(2), mm.TwoParticleAverageSite)
Ejemplo n.º 2
0
 def test_duplicate_bond_type(self):
     """ Tests handling of duplicate bond type in ParameterSet """
     struct = pmd.Structure()
     struct.add_atom(pmd.Atom('CA', type='CX'), 'ALA', 1)
     struct.add_atom(pmd.Atom('CB', type='CY'), 'ALA', 1)
     struct.add_atom(pmd.Atom('CD', type='CX'), 'GLY', 2)
     struct.add_atom(pmd.Atom('CE', type='CY'), 'GLY', 2)
     struct.bond_types.append(pmd.BondType(10.0, 1.0))
     struct.bond_types.append(pmd.BondType(11.0, 1.1))
     struct.bond_types.claim()
     struct.bonds.append(pmd.Bond(struct[0], struct[1], type=struct.bond_types[0]))
     struct.bonds.append(pmd.Bond(struct[2], struct[3], type=struct.bond_types[1]))
     with self.assertRaises(pmd.exceptions.ParameterError):
         pmd.ParameterSet.from_structure(struct, allow_unequal_duplicates=False)
Ejemplo n.º 3
0
def _write_pdb(xyzname, resname):

    bname = os.path.basename(xyzname)

    lines = []
    with open(xyzname, "r") as f:
        lines = f.readlines()[2:]

    s = parmed.Structure()
    r = parmed.Residue(name=resname, number=1, list=s.residues)
    s.residues.append(r)

    for i, atom_line in enumerate(lines, 1):
        data = atom_line.strip().split()
        a = parmed.Atom(list=s.atoms,
                        atomic_number=parmed.periodic_table.AtomicNum[data[0]],
                        name=data[0] + "%d" % i)
        a.number = i
        a.xx = float(data[1])
        a.xy = float(data[2])
        a.xz = float(data[3])
        r.add_atom(a)
        s.atoms.append(a)

    s.write_pdb(os.path.splitext(bname)[0] + ".pdb")
Ejemplo n.º 4
0
def test_assign_histidine():
    fn = get_fn('4lzt/4lzt_h.pdb')
    parm = pmd.load_file(fn)
    his_residues = [
        res.name for res in parm.residues
        if res.name in {'HIS', 'HIE', 'HID', 'HIP'}
    ]
    assert his_residues == ['HIS']

    pdbfixer = AmberPDBFixer(parm)
    pdbfixer.assign_histidine()
    his_residues = [
        res.name for res in pdbfixer.parm.residues
        if res.name in {'HIS', 'HIE', 'HID', 'HIP'}
    ]
    assert his_residues == ['HID']

    # Do not rename to HIS if this residue does not
    # have hydrogen.
    parm2 = pmd.Structure()
    for resnum, resname in enumerate(['HIE', 'HID', 'HIS']):
        atom = pmd.Atom(name='C', atomic_number=6)
        parm2.add_atom(atom, resname, resnum=resnum, chain='A')
    fixer2 = AmberPDBFixer(parm2)
    fixer2.assign_histidine()
    assert ['HIE', 'HID', 'HIS'] == [res.name for res in fixer2.parm.residues]
def mol_to_parmed(mol):
    """ Convert MDT Molecule to parmed Structure
    Args:
        mol (moldesign.Molecule):

    Returns:
        parmed.Structure
    """
    struc = parmed.Structure()
    struc.title = mol.name

    pmedatoms = []
    for atom in mol.atoms:
        pmedatm = parmed.Atom(atomic_number=atom.atomic_number,
                              name=atom.name,
                              mass=atom.mass.value_in(u.dalton),
                              number=utils.if_not_none(atom.pdbindex, -1))
        pmedatm.xx, pmedatm.xy, pmedatm.xz = atom.position.value_in(u.angstrom)
        pmedatoms.append(pmedatm)
        struc.add_atom(pmedatm,
                       resname=utils.if_not_none(atom.residue.resname, 'UNL'),
                       resnum=utils.if_not_none(atom.residue.pdbindex, -1),
                       chain=utils.if_not_none(atom.chain.name, ''))

    for bond in mol.bonds:
        struc.bonds.append(
            parmed.Bond(pmedatoms[bond.a1.index],
                        pmedatoms[bond.a2.index],
                        order=bond.order))
    return struc
Ejemplo n.º 6
0
    def test_atom_serialization(self):
        """ Tests the serialization of Atom """
        atom = pmd.Atom(
            atomic_number=random.randint(1, 100),
            name=random.choice(uppercase) + random.choice(uppercase),
            type=random.choice(uppercase) + random.choice(uppercase),
            charge=random.random() * 2 - 1,
            mass=random.random() * 30 + 1,
            nb_idx=random.randint(1, 20),
            solvent_radius=random.random() * 2,
            screen=random.random() * 2,
            tree='M',
            join=random.random() * 2,
            irotat=random.random(),
            occupancy=random.random(),
            bfactor=random.random() * 10,
            altloc=random.choice(uppercase),
            rmin=random.random() * 2,
            epsilon=random.random() / 2,
            rmin14=random.random() * 2,
            epsilon14=random.random() / 2)
        atom.xx, atom.xy, atom.xz = (random.random() * 100 - 50
                                     for i in range(3))
        atom.number = random.randint(1, 100)
        atom.vx, atom.vy, atom.vz = (random.random() * 100 - 50
                                     for i in range(3))
        atom.multipoles = np.random.rand(10) * 10

        fobj = BytesIO()
        pickle.dump(atom, fobj)
        fobj.seek(0)
        unpickled = pickle.load(fobj)

        self.assertIsInstance(unpickled, pmd.Atom)
        self._equal_atoms(unpickled, atom)
Ejemplo n.º 7
0
    def _add_particles(self, topol):
        err_msg = 'Unknown spin label type {{}}. Allowed values are: {}'
        err_msg = err_msg.format(', '.join(self.ALLOWED_TYPES))

        # we use the same radius and screen as for oxygen
        if not self.explicit:
            radius, screen = self._find_radius_and_screen(topol)

        # find all the unique types of spin labels
        types = set(self.params.values())

        for key in self.params:
            if self.params[key] not in self.ALLOWED_TYPES:
                raise ValueError(err_msg.format(self.params[key]))

            # create the particle
            atom = pmd.Atom(None, 8, 'OND', 'OND', 0.0, 16.00)
            if not self.explicit:
                atom.solvent_radius = radius
                atom.screen = screen

            # add to system
            topol.add_atom_to_residue(atom, topol.residues[key - 1])

            # find the other atoms
            ca = topol.view[':{},@CA'.format(key)].atoms[0]
            cb = topol.view[':{},@CB'.format(key)].atoms[0]
            n = topol.view[':{},@N'.format(key)].atoms[0]

            # set position
            ca_pos = np.array((ca.xx, ca.xy, ca.xz))
            n_pos = np.array((n.xx, n.xy, n.xz))
            cb_pos = np.array((cb.xx, cb.xy, cb.xz))

            direction = (ca_pos - cb_pos) / np.linalg.norm(ca_pos - cb_pos)
            new_pos = (ca_pos -
                       self.bond_params[self.params[key]][1].value_in_unit(u.angstrom) * direction +
                       ca_pos - n_pos)

            atom.xx = new_pos[0]
            atom.xy = new_pos[1]
            atom.xz = new_pos[2]
        topol.remake_parm()

        # setup the new non-bonded parameters
        for t in types:
            indices = [index for index in self.params
                       if self.params[index] == t]
            selection_string = '(:{residue_mask})&(@{atom_name})'.format(
                residue_mask=','.join(str(i) for i in indices),
                atom_name=t)
            action = pmd.tools.addLJType(
                topol,
                selection_string,
                radius=self.lj_params[t][0].value_in_unit(u.angstrom),
                epsilon=self.lj_params[t][1].value_in_unit(u.kilocalorie_per_mole)
            )
            action.execute()
Ejemplo n.º 8
0
 def get_structure_string(self):
     """Require `parmed` package.
     """
     import parmed as pmd
     c = self._schrodinger_structure
     s = pmd.Structure()
     fsys = c.fsys_ct if hasattr(c, 'fsys_ct') else c
     for atom in fsys.atom:
         parm_atom = pmd.Atom(name=atom.pdbname.strip(), atomic_number=atom.atomic_number)
         s.add_atom(parm_atom, atom.pdbres.strip(), atom.resnum, chain=atom.chain)
     s.coordinates = fsys.getXYZ()
     return ParmEdStructure(s).get_structure_string()
Ejemplo n.º 9
0
 def test_duplicate_angle_type(self):
     """ Tests handling of duplicate angle type in ParameterSet """
     struct = pmd.Structure()
     struct.add_atom(pmd.Atom('CA', type='CX'), 'ALA', 1)
     struct.add_atom(pmd.Atom('CB', type='CY'), 'ALA', 1)
     struct.add_atom(pmd.Atom('CC', type='CZ'), 'ALA', 1)
     struct.add_atom(pmd.Atom('CD', type='CX'), 'GLY', 2)
     struct.add_atom(pmd.Atom('CE', type='CY'), 'GLY', 2)
     struct.add_atom(pmd.Atom('CF', type='CZ'), 'GLY', 2)
     struct.angle_types.append(pmd.AngleType(10.0, 120.0))
     struct.angle_types.append(pmd.AngleType(11.0, 109.0))
     struct.angle_types.claim()
     struct.angles.append(
         pmd.Angle(struct[0],
                   struct[1],
                   struct[2],
                   type=struct.angle_types[0]))
     struct.angles.append(
         pmd.Angle(struct[3],
                   struct[4],
                   struct[5],
                   type=struct.angle_types[1]))
     self.assertRaises(
         pmd.exceptions.ParameterError, lambda: pmd.ParameterSet.
         from_structure(struct, allow_unequal_duplicates=False))
Ejemplo n.º 10
0
def createStructureFromResidue(residue):
    # Create ParmEd structure for residue.
    structure = parmed.Structure()
    for a in residue.atoms():
        if a.element is None:
            atom = parmed.ExtraPoint(name=a.name)
        else:
            atom = parmed.Atom(atomic_number=a.element.atomic_number, name=a.name, mass=a.element.mass)
        structure.add_atom(atom, residue.name, residue.index, 'A')
        atommap[a] = atom
    for a1, a2 in topology.bonds():
        structure.bonds.append(Bond(atommap[a1], atommap[a2]))

    return structure
Ejemplo n.º 11
0
def add_ghost_atom_to_pqr_from_atoms_center_of_mass(pqr_filename,
                                                    atom_index_list,
                                                    new_pqr_filename=None):
    """
    Add a ghost atom to a PQR file at the location of the center
    of mass of the atoms listed.
    
    Parameters:
    -----------
    pqr_filename : str
        The name of the PQR file where the ghost atom will be added
        into the file itself.
        
    atom_index_list : list
        A list of integers which are atom indices. The center of mass
        will be found for these atoms, and the ghost atom will be 
        located at that center of mass.
        
    new_pqr_filename : str or None
        If None, the pqr_filename will be overwritten. Otherwise, the
        new PQR with the ghost atom will be written to this file.
    """

    if new_pqr_filename is None:
        new_pqr_filename = pqr_filename
    pqr_struct = parmed.load_file(pqr_filename, skip_bonds=True)
    center_of_mass = np.array([[0., 0., 0.]])
    total_mass = 0.0
    for atom_index in atom_index_list:
        atom_pos = pqr_struct.coordinates[atom_index, :]
        atom_mass = pqr_struct.atoms[atom_index].mass
        center_of_mass += atom_mass * atom_pos
        total_mass += atom_mass
    center_of_mass = center_of_mass / total_mass
    ghost_atom = parmed.Atom(name="GHO",
                             mass=0.0,
                             charge=0.0,
                             solvent_radius=0.0)
    ghost_structure = parmed.Structure()
    ghost_structure.add_atom(ghost_atom, "GHO", 1)
    ghost_structure.coordinates = np.array(center_of_mass)
    complex = pqr_struct + ghost_structure
    for residue in complex.residues:
        residue.chain = ""

    complex.save(new_pqr_filename, overwrite=True)
    ghost_index = len(complex.atoms)
    return ghost_index
Ejemplo n.º 12
0
def to_parmed(traj, all_coords=False):
    import parmed as pmd

    parm = pmd.Structure()
    for atom in traj.top.simplify().atoms:
        p_atom = pmd.Atom(name=atom.name,
                          type=atom.type,
                          atomic_number=atom.atomic_number,
                          charge=atom.charge,
                          mass=atom.mass)
        parm.add_atom(p_atom, resname=atom.resname, resnum=atom.resid)
        # chain=str(atom.molnum))
    if all_coords:
        parm.coordinates = traj.xyz
    else:
        parm.coordinates = traj.xyz[0]
    parm.box = traj.top.box
    return parm
Ejemplo n.º 13
0
    def test_urey_bradley_type(self):
        """ Tests handling getting urey-bradley types from Structure """
        warnings.filterwarnings('error',
                                category=pmd.exceptions.ParameterWarning)
        struct = pmd.Structure()
        struct.add_atom(pmd.Atom('CA', type='CX'), 'ALA', 1)
        struct.add_atom(pmd.Atom('CB', type='CY'), 'ALA', 1)
        struct.add_atom(pmd.Atom('CC', type='CZ'), 'ALA', 1)
        struct.add_atom(pmd.Atom('CD', type='CX'), 'GLY', 2)
        struct.add_atom(pmd.Atom('CE', type='CY'), 'GLY', 2)
        struct.add_atom(pmd.Atom('CF', type='CZ'), 'GLY', 2)
        struct.bond_types.append(pmd.BondType(100.0, 1.0))
        struct.bond_types.claim()
        struct.bonds.extend([
            pmd.Bond(struct[0], struct[1], type=struct.bond_types[0]),
            pmd.Bond(struct[1], struct[2], type=struct.bond_types[0]),
            pmd.Bond(struct[3], struct[4], type=struct.bond_types[0]),
            pmd.Bond(struct[4], struct[5], type=struct.bond_types[0]),
        ])
        struct.angle_types.append(pmd.AngleType(10.0, 120.0))
        struct.angle_types.append(pmd.AngleType(11.0, 109.0))
        struct.angle_types.claim()
        struct.angles.append(
            pmd.Angle(struct[0],
                      struct[1],
                      struct[2],
                      type=struct.angle_types[0]))
        struct.angles.append(
            pmd.Angle(struct[3],
                      struct[4],
                      struct[5],
                      type=struct.angle_types[0]))
        struct.urey_bradley_types.append(pmd.BondType(150.0, 2.0))
        struct.urey_bradley_types.claim()
        struct.urey_bradleys.extend([
            pmd.UreyBradley(struct[0],
                            struct[2],
                            type=struct.urey_bradley_types[0]),
            pmd.UreyBradley(struct[3],
                            struct[5],
                            type=struct.urey_bradley_types[0]),
        ])

        params = pmd.ParameterSet.from_structure(struct)
        self.assertEqual(len(params.urey_bradley_types), 2)
        for key, ubt in iteritems(params.urey_bradley_types):
            self.assertEqual(len(key), 3)
            self.assertEqual(ubt.req, 2.0)
            self.assertEqual(ubt.k, 150.0)
        warnings.filterwarnings('default',
                                category=pmd.exceptions.ParameterWarning)
Ejemplo n.º 14
0
    def to_parmed(self, title='', **kwargs):
        """Create a ParmEd Structure from a Compound. """
        structure = pmd.Structure()
        structure.title = title if title else self.name
        atom_mapping = {}  # For creating bonds below
        guessed_elements = set()
        for atom in self.particles():
            atomic_number = None
            name = ''.join(char for char in atom.name if not char.isdigit())
            try:
                atomic_number = AtomicNum[atom.name]
            except KeyError:
                element = element_by_name(atom.name)
                if name not in guessed_elements:
                    warn('Guessing that "{}" is element: "{}"'.format(
                        atom, element))
                    guessed_elements.add(name)
            else:
                element = atom.name

            atomic_number = atomic_number or AtomicNum[element]
            mass = Mass[element]
            pmd_atom = pmd.Atom(atomic_number=atomic_number,
                                name=atom.name,
                                mass=mass)
            pmd_atom.xx, pmd_atom.xy, pmd_atom.xz = atom.pos * 10  # Angstroms
            structure.add_atom(pmd_atom, resname='RES', resnum=1)
            atom_mapping[atom] = pmd_atom

        for atom1, atom2 in self.bonds():
            bond = pmd.Bond(atom_mapping[atom1], atom_mapping[atom2])
            structure.bonds.append(bond)

        box = self.boundingbox
        box_vector = np.empty(6)
        box_vector[3] = box_vector[4] = box_vector[5] = 90.0
        for dim, val in enumerate(self.periodicity):
            if val:
                box_vector[dim] = val * 10
            else:
                box_vector[dim] = box.lengths[dim] * 10 + 5
        structure.box = box_vector
        return structure
Ejemplo n.º 15
0
def _new_atom(parm, carbon, hydrogen, name):
    """
    Creates a new hydrogen atom and add the necessary topology

    Parameters
    ----------
    parm : parmed.Structure
        the topology
    carbon : parmed.Atom
        the carbon atom to which the hydrogen should be bonded
    hydrogen : parmed.Atom
        the other hydrogen, already in the topology
    name : string
        the name of the hydrogen atom

    Returns
    -------
    parmed.Atom
        the newly created atom
    """
    new = parmed.Atom(list=parm.atoms,
                      name=name,
                      type="HAL2",
                      charge=0.0,
                      mass=1.008000)
    new.residue = parm.residues[0]
    parm.residues[0].atoms.insert(hydrogen.idx + 1, new)
    parm.atoms.insert(hydrogen.idx + 1, new)
    # Add topology
    parm.bonds.append(parmed.Bond(carbon, new))
    for a in parm.adjusts:
        if a.atom1 == hydrogen:
            parm.adjusts.append(parmed.NonbondedException(new, a.atom2))
        elif a.atom2 == hydrogen:
            parm.adjusts.append(parmed.NonbondedException(a.atom1, new))
    for angle in hydrogen.angles:
        parm.angles.append(_new_angle(angle, hydrogen, new))
    parm.angles.append(parmed.Angle(hydrogen, carbon, new))
    parm.angles[-1].funct = 5
    for dihedral in hydrogen.dihedrals:
        parm.dihedrals.append(_new_dihedral(dihedral, hydrogen, new))
    return new
Ejemplo n.º 16
0
    def add_dummy_atoms_to_structure(
        structure: pmd.Structure,
        dummy_atom_offsets: List[np.ndarray],
        offset_coordinates: Optional[np.ndarray] = None,
    ):
        """A convenience method to add a number of dummy atoms to an existing
        ParmEd structure, and to position those atoms at a specified set of positions.

        Parameters
        ----------
        structure
            The structure to add the dummy atoms to.
        dummy_atom_offsets
            The list of positions (defined by a 3-d numpy array) of the dummy atoms
            to add.
        offset_coordinates
            An optional amount to offset each of the dummy atom positions by with
            shape=(3,).
        """

        if offset_coordinates is None:
            offset_coordinates = np.zeros(3)

        full_coordinates = np.vstack(
            [
                structure.coordinates,
                *[
                    offset_coordinates + dummy_atom_offset
                    for dummy_atom_offset in dummy_atom_offsets
                ],
            ]
        )

        for index in range(len(dummy_atom_offsets)):
            structure.add_atom(pmd.Atom(name="DUM"), f"DM{index + 1}", 1)

        structure.positions = full_coordinates
Ejemplo n.º 17
0
    def convert(self, obj):
        """Write selection at current trajectory frame to :class:`~parmed.structure.Structure`.

        Parameters
        -----------
        obj : AtomGroup or Universe or :class:`Timestep`
        """
        try:
            import parmed as pmd
        except ImportError:
            raise ImportError('ParmEd is required for ParmEdConverter but '
                              'is not installed. Try installing it with \n'
                              'pip install parmed')
        try:
            # make sure to use atoms (Issue 46)
            ag_or_ts = obj.atoms
        except AttributeError:
            if isinstance(obj, base.Timestep):
                raise ValueError("Writing Timesteps to ParmEd "
                                 "objects is not supported")
            else:
                raise_from(TypeError("No atoms found in obj argument"), None)

        # Check for topology information
        missing_topology = []
        try:
            names = ag_or_ts.names
        except (AttributeError, NoDataError):
            names = itertools.cycle(('X', ))
            missing_topology.append('names')
        try:
            resnames = ag_or_ts.resnames
        except (AttributeError, NoDataError):
            resnames = itertools.cycle(('UNK', ))
            missing_topology.append('resnames')

        if missing_topology:
            warnings.warn(
                "Supplied AtomGroup was missing the following attributes: "
                "{miss}. These will be written with default values. "
                "Alternatively these can be supplied as keyword arguments."
                "".format(miss=', '.join(missing_topology)))

        try:
            positions = ag_or_ts.positions
        except:
            positions = [None] * ag_or_ts.n_atoms

        try:
            velocities = ag_or_ts.velocities
        except:
            velocities = [None] * ag_or_ts.n_atoms

        atom_kwargs = []
        for atom, name, resname, xyz, vel in zip(ag_or_ts, names, resnames,
                                                 positions, velocities):
            akwargs = {'name': name}
            chain_seg = {'segid': atom.segid}
            for attrname in ('mass', 'charge', 'type', 'altLoc', 'tempfactor',
                             'occupancy', 'gbscreen', 'solventradius',
                             'nbindex', 'rmin', 'epsilon', 'rmin14',
                             'epsilon14', 'id'):
                try:
                    akwargs[MDA2PMD.get(attrname,
                                        attrname)] = getattr(atom, attrname)
                except AttributeError:
                    pass
            try:
                el = atom.element.lower().capitalize()
                akwargs['atomic_number'] = SYMB2Z[el]
            except (KeyError, AttributeError):
                try:
                    tp = atom.type.lower().capitalize()
                    akwargs['atomic_number'] = SYMB2Z[tp]
                except (KeyError, AttributeError):
                    pass
            try:
                chain_seg['chain'] = atom.chainID
            except AttributeError:
                pass
            try:
                chain_seg['inscode'] = atom.icode
            except AttributeError:
                pass
            atom_kwargs.append(
                (akwargs, resname, atom.resid, chain_seg, xyz, vel))

        struct = pmd.Structure()

        for akwarg, resname, resid, kw, xyz, vel in atom_kwargs:
            atom = pmd.Atom(**akwarg)
            if xyz is not None:
                atom.xx, atom.xy, atom.xz = xyz

            if vel is not None:
                atom.vx, atom.vy, atom.vz = vel

            atom.atom_type = pmd.AtomType(
                akwarg['name'],
                None,
                akwarg['mass'],
                atomic_number=akwargs.get('atomic_number'))
            struct.add_atom(atom, resname, resid, **kw)

        try:
            struct.box = ag_or_ts.dimensions
        except AttributeError:
            struct.box = None

        if hasattr(ag_or_ts, 'universe'):
            atomgroup = {
                atom: index
                for index, atom in enumerate(list(ag_or_ts))
            }
            get_atom_indices = functools.partial(get_indices_from_subset,
                                                 atomgroup=atomgroup,
                                                 universe=ag_or_ts.universe)
        else:
            get_atom_indices = lambda x: x

        # bonds
        try:
            params = ag_or_ts.bonds.atomgroup_intersection(ag_or_ts,
                                                           strict=True)
        except AttributeError:
            pass
        else:
            for p in params:
                atoms = [
                    struct.atoms[i] for i in map(get_atom_indices, p.indices)
                ]
                try:
                    for obj in p.type:
                        bond = pmd.Bond(*atoms, type=obj.type, order=obj.order)
                        struct.bonds.append(bond)
                    if isinstance(obj.type, pmd.BondType):
                        struct.bond_types.append(bond.type)
                        bond.type.list = struct.bond_types
                except (TypeError, AttributeError):
                    order = p.order if p.order is not None else 1
                    btype = getattr(p.type, 'type', None)

                    bond = pmd.Bond(*atoms, type=btype, order=order)
                    struct.bonds.append(bond)
                    if isinstance(bond.type, pmd.BondType):
                        struct.bond_types.append(bond.type)
                        bond.type.list = struct.bond_types

        # dihedrals
        try:
            params = ag_or_ts.dihedrals.atomgroup_intersection(ag_or_ts,
                                                               strict=True)
        except AttributeError:
            pass
        else:
            for p in params:
                atoms = [
                    struct.atoms[i] for i in map(get_atom_indices, p.indices)
                ]
                try:
                    for obj in p.type:
                        imp = getattr(obj, 'improper', False)
                        ign = getattr(obj, 'ignore_end', False)
                        dih = pmd.Dihedral(*atoms,
                                           type=obj.type,
                                           ignore_end=ign,
                                           improper=imp)
                        struct.dihedrals.append(dih)
                        if isinstance(dih.type, pmd.DihedralType):
                            struct.dihedral_types.append(dih.type)
                            dih.type.list = struct.dihedral_types
                except (TypeError, AttributeError):
                    btype = getattr(p.type, 'type', None)
                    imp = getattr(p.type, 'improper', False)
                    ign = getattr(p.type, 'ignore_end', False)
                    dih = pmd.Dihedral(*atoms,
                                       type=btype,
                                       improper=imp,
                                       ignore_end=ign)
                    struct.dihedrals.append(dih)
                    if isinstance(dih.type, pmd.DihedralType):
                        struct.dihedral_types.append(dih.type)
                        dih.type.list = struct.dihedral_types

        for param, pmdtype, trackedlist, typelist, clstype in (
            ('ureybradleys', pmd.UreyBradley, struct.urey_bradleys,
             struct.urey_bradley_types, pmd.BondType),
            ('angles', pmd.Angle, struct.angles, struct.angle_types,
             pmd.AngleType), ('impropers', pmd.Improper, struct.impropers,
                              struct.improper_types, pmd.ImproperType),
            ('cmaps', pmd.Cmap, struct.cmaps, struct.cmap_types,
             pmd.CmapType)):
            try:
                params = getattr(ag_or_ts, param)
                values = params.atomgroup_intersection(ag_or_ts, strict=True)
            except AttributeError:
                pass
            else:
                for v in values:
                    atoms = [
                        struct.atoms[i]
                        for i in map(get_atom_indices, v.indices)
                    ]

                    try:
                        for parmed_obj in v.type:
                            p = pmdtype(*atoms, type=parmed_obj.type)
                            trackedlist.append(p)
                            if isinstance(p.type, clstype):
                                typelist.append(p.type)
                                p.type.list = typelist
                    except (TypeError, AttributeError):
                        vtype = getattr(v.type, 'type', None)

                        p = pmdtype(*atoms, type=vtype)
                        trackedlist.append(p)
                        if isinstance(p.type, clstype):
                            typelist.append(p.type)
                            p.type.list = typelist
        return struct
Ejemplo n.º 18
0
    def _add_particles(self, topol):
        err_msg = 'Unknown spin label type {{}}. Allowed values are: {}'
        err_msg = err_msg.format(', '.join(self.ALLOWED_TYPES))

        # we use the same radius and screen as for oxygen
        if not self.explicit:
            radius, screen = self._find_radius_and_screen(topol)

        # find all the unique types of spin labels
        types = set(self.params.values())

        # create the bond types
        bond_types = {}
        for t in types:
            bond_k, bond_r = self.bond_params[t]
            topol.bond_types.append(
                pmd.BondType(bond_k, bond_r, list=topol.bond_types))
            bt = topol.bond_types[-1]
            bond_types[t] = bt

        # create the angle types
        angle_types = {}
        for t in types:
            angle_k, angle_theta = self.angle_params[t]
            topol.angle_types.append(
                pmd.AngleType(angle_k, angle_theta, list=topol.angle_types))
            at = topol.angle_types[-1]
            angle_types[t] = at

        # create the torsion types
        tors_types = {}
        for t in types:
            tors_k, tors_per, tors_phase = self.tors_params[t]
            topol.dihedral_types.append(
                pmd.DihedralType(tors_k,
                                 tors_per,
                                 tors_phase,
                                 list=topol.dihedral_types))
            tt = topol.dihedral_types[-1]
            tors_types[t] = tt

        for key in self.params:
            if self.params[key] not in self.ALLOWED_TYPES:
                raise ValueError(err_msg.format(self.params[key]))

            # create the particle
            atom = pmd.Atom(None, 8, 'OND', 'OND', 0.0, 16.00)
            if not self.explicit:
                atom.radii = radius
                atom.screen = screen

            # add to system
            topol.add_atom_to_residue(atom, topol.residues[key])

            # find the other atoms
            ca = topol.view[':{},@CA'.format(key + 1)].atoms[0]
            cb = topol.view[':{},@CB'.format(key + 1)].atoms[0]
            n = topol.view[':{},@N'.format(key + 1)].atoms[0]

            # add bond
            topol.bonds.append(pmd.Bond(atom, ca,
                                        bond_types[self.params[key]]))

            # add angle
            topol.angles.append(
                pmd.Angle(cb, ca, atom, angle_types[self.params[key]]))

            # add torsion
            topol.dihedrals.append(
                pmd.Dihedral(n,
                             ca,
                             cb,
                             atom,
                             type=tors_types[self.params[key]]))

            # set position
            ca_pos = np.array((ca.xx, ca.xy, ca.xz))
            n_pos = np.array((n.xx, n.xy, n.xz))
            cb_pos = np.array((cb.xx, cb.xy, cb.xz))

            direction = np.linalg.norm(ca_pos - n_pos)
            new_pos = cb_pos - self.bond_params[
                self.params[key]][1].value_in_unit(u.angstrom) * direction

            atom.xx = new_pos[0]
            atom.xy = new_pos[1]
            atom.xz = new_pos[2]
        topol.remake_parm()

        # setup the new non-bonded parameters
        for t in types:
            indices = [
                index + 1 for index in self.params if self.params[index] == t
            ]
            selection_string = '(:{residue_mask})&(@{atom_name})'.format(
                residue_mask=','.join(str(i) for i in indices), atom_name=t)
            print topol.LJ_radius
            action = pmd.tools.addLJType(
                topol,
                selection_string,
                radius=self.lj_params[t][0].value_in_unit(u.angstrom),
                epsilon=self.lj_params[t][1].value_in_unit(
                    u.kilocalorie_per_mole))
            action.execute()
            print topol.LJ_radius
Ejemplo n.º 19
0
def to_parmed(off_system: "System") -> pmd.Structure:
    """Convert an OpenFF System to a ParmEd Structure"""
    structure = pmd.Structure()
    _convert_box(off_system.box, structure)

    if "Electrostatics" in off_system.handlers.keys():
        has_electrostatics = True
        electrostatics_handler = off_system.handlers["Electrostatics"]
    else:
        has_electrostatics = False

    for topology_molecule in off_system.topology.topology_molecules:  # type: ignore[union-attr]
        for atom in topology_molecule.atoms:
            atomic_number = atom.atomic_number
            element = pmd.periodic_table.Element[atomic_number]
            mass = pmd.periodic_table.Mass[element]
            structure.add_atom(
                pmd.Atom(
                    atomic_number=atomic_number,
                    mass=mass,
                ),
                resname="FOO",
                resnum=0,
            )

    if "Bonds" in off_system.handlers.keys():
        bond_handler = off_system.handlers["Bonds"]
        bond_type_map: Dict = dict()
        for pot_key, pot in bond_handler.potentials.items():
            k = pot.parameters["k"].to(kcal_mol_a2).magnitude / 2
            length = pot.parameters["length"].to(unit.angstrom).magnitude
            bond_type = pmd.BondType(k=k, req=length)
            bond_type_map[pot_key] = bond_type
            structure.bond_types.append(bond_type)

        for top_key, pot_key in bond_handler.slot_map.items():
            idx_1, idx_2 = top_key.atom_indices
            bond_type = bond_type_map[pot_key]
            bond = pmd.Bond(
                atom1=structure.atoms[idx_1],
                atom2=structure.atoms[idx_2],
                type=bond_type,
            )
            structure.bonds.append(bond)

    structure.bond_types.claim()

    if "Angles" in off_system.handlers.keys():
        angle_handler = off_system.handlers["Angles"]
        angle_type_map: Dict = dict()
        for pot_key, pot in angle_handler.potentials.items():
            k = pot.parameters["k"].to(kcal_mol_rad2).magnitude / 2
            theta = pot.parameters["angle"].to(unit.degree).magnitude
            # TODO: Look up if AngleType already exists in struct
            angle_type = pmd.AngleType(k=k, theteq=theta)
            angle_type_map[pot_key] = angle_type
            structure.angle_types.append(angle_type)

        for top_key, pot_key in angle_handler.slot_map.items():
            idx_1, idx_2, idx_3 = top_key.atom_indices
            angle_type = angle_type_map[pot_key]
            structure.angles.append(
                pmd.Angle(
                    atom1=structure.atoms[idx_1],
                    atom2=structure.atoms[idx_2],
                    atom3=structure.atoms[idx_3],
                    type=angle_type,
                ))
            structure.angle_types.append(angle_type)

    structure.angle_types.claim()

    # ParmEd treats 1-4 scaling factors at the level of each DihedralType,
    # whereas SMIRNOFF captures them at the level of the non-bonded handler,
    # so they need to be stored here for processing dihedrals
    vdw_14 = off_system.handlers["vdW"].scale_14  # type: ignore[attr-defined]
    if has_electrostatics:
        coul_14 = off_system.handlers[
            "Electrostatics"].scale_14  # type: ignore[attr-defined]
    else:
        coul_14 = 1.0
    vdw_handler = off_system.handlers["vdW"]
    if "ProperTorsions" in off_system.handlers.keys():
        proper_torsion_handler = off_system.handlers["ProperTorsions"]
        proper_type_map: Dict = dict()
        for pot_key, pot in proper_torsion_handler.potentials.items():
            k = pot.parameters["k"].to(kcal_mol).magnitude
            periodicity = pot.parameters["periodicity"]
            phase = pot.parameters["phase"].magnitude
            proper_type = pmd.DihedralType(
                phi_k=k,
                per=periodicity,
                phase=phase,
                scnb=1 / vdw_14,
                scee=1 / coul_14,
            )
            proper_type_map[pot_key] = proper_type
            structure.dihedral_types.append(proper_type)

        for top_key, pot_key in proper_torsion_handler.slot_map.items():
            idx_1, idx_2, idx_3, idx_4 = top_key.atom_indices
            dihedral_type = proper_type_map[pot_key]
            structure.dihedrals.append(
                pmd.Dihedral(
                    atom1=structure.atoms[idx_1],
                    atom2=structure.atoms[idx_2],
                    atom3=structure.atoms[idx_3],
                    atom4=structure.atoms[idx_4],
                    type=dihedral_type,
                ))
            structure.dihedral_types.append(dihedral_type)

            key1 = TopologyKey(atom_indices=(idx_1, ))
            key4 = TopologyKey(atom_indices=(idx_4, ))
            vdw1 = vdw_handler.potentials[vdw_handler.slot_map[key1]]
            vdw4 = vdw_handler.potentials[vdw_handler.slot_map[key4]]
            sig1, eps1 = _lj_params_from_potential(vdw1)
            sig4, eps4 = _lj_params_from_potential(vdw4)
            sig = (sig1 + sig4) * 0.5
            eps = (eps1 * eps4)**0.5
            nbtype = pmd.NonbondedExceptionType(rmin=sig * 2**(1 / 6),
                                                epsilon=eps * vdw_14,
                                                chgscale=coul_14)
            structure.adjusts.append(
                pmd.NonbondedException(structure.atoms[idx_1],
                                       structure.atoms[idx_4],
                                       type=nbtype))
            structure.adjust_types.append(nbtype)

    structure.dihedral_types.claim()
    structure.adjust_types.claim()

    #    if False:  # "ImroperTorsions" in off_system.term_collection.terms:
    #        improper_term = off_system.term_collection.terms["ImproperTorsions"]
    #        for improper, smirks in improper_term.smirks_map.items():
    #            idx_1, idx_2, idx_3, idx_4 = improper
    #            pot = improper_term.potentials[improper_term.smirks_map[improper]]
    #            # TODO: Better way of storing periodic data in generally, probably need to improve Potential
    #            n = re.search(r"\d", "".join(pot.parameters.keys())).group()
    #            k = pot.parameters["k" + n].m  # kcal/mol
    #            periodicity = pot.parameters["periodicity" + n].m  # dimless
    #            phase = pot.parameters["phase" + n].m  # degree
    #
    #            dihedral_type = pmd.DihedralType(per=periodicity, phi_k=k, phase=phase)
    #            structure.dihedrals.append(
    #                pmd.Dihedral(
    #                    atom1=structure.atoms[idx_1],
    #                    atom2=structure.atoms[idx_2],
    #                    atom3=structure.atoms[idx_3],
    #                    atom4=structure.atoms[idx_4],
    #                    type=dihedral_type,
    #                )
    #            )

    vdw_handler = off_system.handlers["vdW"]
    for pmd_idx, pmd_atom in enumerate(structure.atoms):
        top_key = TopologyKey(atom_indices=(pmd_idx, ))
        smirks = vdw_handler.slot_map[top_key]
        potential = vdw_handler.potentials[smirks]
        element = pmd.periodic_table.Element[pmd_atom.element]
        sigma, epsilon = _lj_params_from_potential(potential)

        atom_type = pmd.AtomType(
            name=element + str(pmd_idx + 1),
            number=pmd_idx,
            atomic_number=pmd_atom.atomic_number,
            mass=pmd.periodic_table.Mass[element],
        )

        atom_type.set_lj_params(eps=epsilon, rmin=sigma * 2**(1 / 6) / 2)
        pmd_atom.atom_type = atom_type
        pmd_atom.type = atom_type.name
        pmd_atom.name = pmd_atom.type

    for pmd_idx, pmd_atom in enumerate(structure.atoms):
        if has_electrostatics:
            top_key = TopologyKey(atom_indices=(pmd_idx, ))
            partial_charge = electrostatics_handler.charges[
                top_key]  # type: ignore[attr-defined]
            unitless_ = partial_charge.to(unit.elementary_charge).magnitude
            pmd_atom.charge = float(unitless_)
            pmd_atom.atom_type.charge = float(unitless_)
        else:
            pmd_atom.charge = 0

    # Assign dummy residue names, GROMACS will not accept empty strings
    for res in structure.residues:
        res.name = "FOO"

    structure.positions = off_system.positions.to(
        unit.angstrom).magnitude  # type: ignore[attr-defined]
    for idx, pos in enumerate(structure.positions):
        structure.atoms[idx].xx = pos._value[0]
        structure.atoms[idx].xy = pos._value[1]
        structure.atoms[idx].xz = pos._value[2]

    return structure
Ejemplo n.º 20
0
def _create_atoms(struct, residue, template, hnames) :
    """
    Adds the necessary atoms to a parmed.Structure object

    Parameters
    ----------
    struct : parmed.Structure
        the structure
    residue : string
        the residue name
    template : string
        the name prefix of the carbon atoms
    hnames: string
        the name postfox of the hydrogen atoms
    """
    try :
        h9 = struct.view["@H9%s&:%s"%(hnames[0],residue)].atoms[0]
    except :
        h9 = struct.view["@H9%s&:%s"%("1",residue)].atoms[0]
    c8 = struct.view["@%s8&:%s"%(template,residue)].atoms[0]
    c9 = struct.view["@%s9&:%s"%(template,residue)].atoms[0]
    c10 = struct.view["@%s10&:%s"%(template,residue)].atoms[0]
    term_i = _find_chain_end(struct.view[":%s"%residue], 30, template)
    terminal = struct.view["@%s%d&:%s"%(template,term_i,residue)].atoms[0]
    term_res_idx = _get_atom_index(terminal.residue, terminal.name)

    v1 = geo.vnorm(np.asarray(_get_coords_from_atom_or_tuple(c9)) -
                    np.asarray(_get_coords_from_atom_or_tuple(c10)))
    v2 = geo.vnorm(np.asarray(_get_coords_from_atom_or_tuple(c9)) -
                np.asarray(_get_coords_from_atom_or_tuple(h9)))
    v1_v2 = geo.vnorm(np.cross(v1,v2))
    xyz = 0.5*(np.asarray(_get_coords_from_atom_or_tuple(c9)) +
                    np.asarray(_get_coords_from_atom_or_tuple(c10))) + 1.3*v1_v2
    catom = parmed.Atom(list=struct.atoms, name="%s%d"%(template, term_i+1))
    catom.residue = c10.residue
    catom.xx = xyz[0]
    catom.xy = xyz[1]
    catom.xz = xyz[2]
    c10.residue.atoms.insert(term_res_idx+4, catom)
    struct.atoms.insert(terminal.idx+4, catom)
    struct.bonds.append(parmed.Bond(c9,catom))
    struct.bonds.append(parmed.Bond(c10,catom))

    xyz  = geo.build_xyz(np.asarray(_get_coords_from_atom_or_tuple(catom)),
                        np.asarray(_get_coords_from_atom_or_tuple(c9)),
                        np.asarray(_get_coords_from_atom_or_tuple(c8)),
                        0.95, 118, 150)
    hatom1 = parmed.Atom(list=struct.atoms, name="H%d%s"%(term_i+1, hnames[0]))
    hatom1.residue = catom.residue
    hatom1.xx = xyz[0]
    hatom1.xy = xyz[1]
    hatom1.xz = xyz[2]
    catom.residue.atoms.insert(term_res_idx+5, hatom1)
    struct.atoms.insert(terminal.idx+5, hatom1)
    struct.bonds.append(parmed.Bond(catom, hatom1))

    xyz  = geo.build_xyz(np.asarray(_get_coords_from_atom_or_tuple(catom)),
                        np.asarray(_get_coords_from_atom_or_tuple(c9)),
                        np.asarray(_get_coords_from_atom_or_tuple(c8)),
                        0.95, 118, 350)
    hatom2 = parmed.Atom(list=struct.atoms, name="H%d%s"%(term_i+1, hnames[1]))
    hatom2.residue = catom.residue
    hatom2.xx = xyz[0]
    hatom2.xy = xyz[1]
    hatom2.xz = xyz[2]
    catom.residue.atoms.insert(term_res_idx+6, hatom2)
    struct.atoms.insert(terminal.idx+6, hatom2)
    struct.bonds.append(parmed.Bond(catom, hatom2))
Ejemplo n.º 21
0
def insertHbyList(ase_struct,
                  pmd_top,
                  implicitHbondingPartners,
                  bond_length=1.0):
    # make copies of passed structures as not to alter originals:
    new_pmd_top = pmd_top.copy(pmd.Structure)
    new_ase_struct = ase_struct.copy()

    # names stores the String IDs of all atoms as to facilitate later ASE ID -> Atom name mapping
    names = [a.name for a in pmd_top.atoms]
    # make copied atoms accessible by unchangable indices (standard list)
    originalAtoms = [a for a in new_pmd_top.atoms]

    implicitHbondingPartnersIdxHnoTuples = [
        (a.idx, implicitHbondingPartners[k]) for a in pmd_top.atoms
        for k in implicitHbondingPartners.keys() if a.name == k
    ]
    implicitHbondingPartnersIdxHnoDict = dict(
        implicitHbondingPartnersIdxHnoTuples)

    # build numbered neighbour list "manually"
    #i: list of atoms e.g. [0,0,0,1,1,2,2,...]
    i = np.array([b.atom1.idx for b in new_pmd_top.bonds])
    #j: list of bonding partners corresponding to i [1,2,3,...] ==> 0 has bondpartners 1,2 and 3; etc.
    j = np.array([b.atom2.idx for b in new_pmd_top.bonds])
    r = new_ase_struct.positions

    for k, Hno in implicitHbondingPartnersIdxHnoDict.items(
    ):  # for all atoms to append hydrogen to
        print('Adding {} H-atoms to {} (#{})...'.format(
            Hno, originalAtoms[k].name, k))
        for h in range(0, Hno):
            r = new_ase_struct.positions
            bondingPartners = j[i == k]
            print('bondingPartners', bondingPartners)
            partnerStr = ''
            for p in bondingPartners:
                if partnerStr == '':
                    partnerStr = originalAtoms[p].name
                else:
                    partnerStr += ', ' + originalAtoms[p].name
            print('Atom {} already has bonding partners {}'.format(
                originalAtoms[k].name, partnerStr))
            dr = (r[j[i == k]] - r[k]).mean(axis=0)
            # my understanding: dr is vector
            # from atom k's position towards the geometrical center of mass
            # it forms with its defined neighbours
            # r0 is a vector offset into the opposit direction:
            dr = dr / np.linalg.norm(dr)  #normalized vector in direction dr

            #calculate an orthogonal vector 'dr_ortho' on dr
            #and push the H atoms in dr+dr_ortho and dr-dr_ortho
            #if one has to add more than two H atoms introduce dr_ortho_2 = dr x dr_ortho
            dr_ortho = np.cross(dr, np.array([1, 0, 0]))
            if np.linalg.norm(
                    dr_ortho
            ) < 0.1:  #if dr and (1,0,0) have almost the same direction
                dr_ortho = np.cross(dr, np.array([0, 1, 0]))
            # (1-2*h) = {1,-1} for h={0,1}
            h_pos_vec = (dr + (1 - 2 * h) * dr_ortho
                         ) / np.linalg.norm(dr + (1 - 2 * h) * dr_ortho)
            r0 = r[k] - bond_length * h_pos_vec

            new_ase_struct += ase.Atom('H', r0)  # add atom in ase structure
            n_atoms = len(new_ase_struct)

            #introduce a corrector step for a added atom which is too close to others
            #do as many corrector stepps until all atoms are more than 1\AA appart
            c_step = 0
            while True:
                nl = NeighborList(cutoffs=[.5] * len(new_ase_struct),
                                  skin=0.09,
                                  self_interaction=False,
                                  bothways=True)
                nl.update(new_ase_struct)
                indices, offsets = nl.get_neighbors(-1)
                indices = np.delete(indices, np.where(indices == k))
                if len(indices) == 0:
                    break

                elif c_step > 15:
                    print(
                        'programm needs more than 15 corrector steps for H atom {} at atom {}'
                        .format(n_atoms, k))
                    sys.exit(15)
                    break

                print('too close atoms', indices)
                c_step += 1
                print('correcter step {} for H {} at atom {}'.format(
                    c_step, n_atoms - 1, k))
                # if indices not empty -> the atom(-1)=r_H is to close together
                # with atom a_close=indices[0], it is a H-atom belonging to atom 'k'=r_k .
                #correctorstep: corr_step = (r_H-a_close)/|(r_H-a_close)|
                #corrected_pos: corr_pos = ((r_H-r_k) + corr_step)/|((r_H-r_k) + corr_step)|
                #new H position: new_r_H = r_k + corr_pos
                r_H, r_k, a_close = np.take(new_ase_struct.get_positions(),
                                            [-1, k, indices[0]],
                                            axis=0)
                #print('r_H, r_k, a_close', r_H, r_k, a_close)
                corr_step = (r_H - a_close) / np.linalg.norm(
                    (r_H - a_close)
                )  #maybe introduce here a skaling Faktor s=0.3 or somthing like that to make tiny corrections and don't overshoot.
                corr_pos = ((r_H - r_k) + corr_step) / np.linalg.norm(
                    (r_H - r_k) + corr_step)
                new_r_H = r_k + bond_length * corr_pos
                #correct the H position to new_r_H in new_ase_struct
                trans = np.zeros([n_atoms, 3])
                trans[-1] = new_r_H - r_H
                new_ase_struct.translate(trans)

            #view(new_ase_struct)
            #sys.exit()

            i = np.append(i, k)  # manually update numbered neighbour lists
            j = np.append(j, len(new_ase_struct) - 1)

            # update pmd topology
            bondingPartner = originalAtoms[
                k]  # here we need the original numbering,
            # as ParmEd alters indices when adding atoms to the structure
            nameH = '{}{}'.format(
                h + 1, bondingPartner.name)  # atom needs a unique name
            print('Adding H-atom {} at position [ {}, {}, {} ]'.format(
                nameH, r0[0], r0[1], r0[2]))
            new_H = pmd.Atom(name=nameH, type='H', atomic_number=1)
            new_H.xx = r0[
                0]  # ParmEd documentation not very helpful, did not find any more compact assignment
            new_H.xy = r0[1]
            new_H.xz = r0[2]
            # do not understand ParmEd that well, apparently we need the Bond object in order to update topology
            new_Bond = pmd.Bond(bondingPartner, new_H)
            new_H.bond_to(
                bondingPartner)  # not sure, whether this is necessary
            new_pmd_top.bonds.append(new_Bond)
            new_pmd_top.add_atom_to_residue(new_H, bondingPartner.residue)
            originalAtoms.append(
                new_H)  # add atom to the bottom of "index-stiff" list
            names.append(nameH)  # append name of H-atom
    return new_ase_struct, new_pmd_top, names
Ejemplo n.º 22
0
    def patch(self, top_string, crd_string):
        INTOP = "in.top"
        INRST = "in.rst"
        OUTTOP = "out.top"
        OUTRST = "out.rst"

        with util.in_temp_dir():
            with open(INTOP, "wt") as outfile:
                outfile.write(top_string)
            with open(INRST, "wt") as outfile:
                outfile.write(crd_string)

            base = pmd.load_file(INTOP)
            crd = pmd.load_file(INRST)
            base.coordinates = crd.coordinates

            # create a new structure to add our dummy atoms to
            parm = pmd.Structure()

            # add in atom type for our dummy particles
            atype = pmd.AtomType("SDUM", 0, mass=12.0, charge=0.0)
            atype.set_lj_params(0.0, 0.0)

            for i in range(self.n_tensors):
                a1 = pmd.Atom(
                    name="S1",
                    atomic_number=atype.atomic_number,
                    type=str(atype),
                    charge=atype.charge,
                    mass=atype.mass,
                    solvent_radius=1.0,
                    screen=0.5,
                )
                a1.atom_type = atype

                a2 = pmd.Atom(
                    name="S2",
                    atomic_number=atype.atomic_number,
                    type=str(atype),
                    charge=atype.charge,
                    mass=atype.mass,
                    solvent_radius=1.0,
                    screen=0.5,
                )
                a2.atom_type = atype

                parm.add_atom(a1, resname="SDM", resnum=i)
                parm.add_atom(a2, resname="SDM", resnum=i)

            # we add noise here because we'll get NaN if the particles ever
            # end up exactly on top of each other
            parm.positions = np.zeros((2 * self.n_tensors, 3))

            # combine the old system with the new dummy atoms
            comb = base + parm
            last_index = comb.residues[-1].idx
            self.resids = list(range(last_index - self.n_tensors + 2, last_index + 2))

            comb.write_parm(OUTTOP)
            comb.write_rst7(OUTRST)
            with open(OUTTOP, "rt") as infile:
                top_string = infile.read()
            with open(OUTRST, "rt") as infile:
                crd_string = infile.read()
        return top_string, crd_string
Ejemplo n.º 23
0
    def _add_particles(self, topol):
        err_msg = "Unknown spin label type {{}}. Allowed values are: {}"
        err_msg = err_msg.format(", ".join(self.ALLOWED_TYPES))

        # we use the same radius and screen as for oxygen
        if not self.explicit:
            radius, screen = self._find_radius_and_screen(topol)

        # find all the unique types of spin labels
        types = set(self.params.values())

        for key in self.params:
            if self.params[key] not in self.ALLOWED_TYPES:
                raise ValueError(err_msg.format(self.params[key]))

            # create the particle
            atom = pmd.Atom(None, 8, "OND", "OND", 0.0, 16.00)
            if not self.explicit:
                atom.solvent_radius = radius
                atom.screen = screen

            # add to system
            topol.add_atom_to_residue(atom, topol.residues[int(key)])

            # find the other atoms
            ca = topol.view[f":{int(key)+1},@CA"].atoms[0]
            cb = topol.view[f":{int(key)+1},@CB"].atoms[0]
            n = topol.view[f":{int(key)+1},@N"].atoms[0]

            # Mark that the spin label and CA are connected.
            # This will not actually add a bond to the potential,
            # but will mark the connectivity between the atoms.
            atom.bond_to(ca)

            # set position
            ca_pos = np.array((ca.xx, ca.xy, ca.xz))
            n_pos = np.array((n.xx, n.xy, n.xz))
            cb_pos = np.array((cb.xx, cb.xy, cb.xz))

            direction = (ca_pos - cb_pos) / np.linalg.norm(ca_pos - cb_pos)
            new_pos = (ca_pos -
                       self.bond_params[self.params[key]][1].value_in_unit(
                           u.nanometer) * direction + ca_pos - n_pos)

            atom.xx = new_pos[0]
            atom.xy = new_pos[1]
            atom.xz = new_pos[2]
        topol.remake_parm()

        # setup the new non-bonded parameters
        for t in types:
            indices = [
                index for index in self.params if self.params[index] == t
            ]
            selection_string = "(:{residue_mask})&(@{atom_name})".format(
                residue_mask=",".join(str(i) for i in indices), atom_name=t)
            action = pmd.tools.addLJType(
                topol,
                selection_string,
                radius=self.lj_params[t][0].value_in_unit(u.angstrom),
                epsilon=self.lj_params[t][1].value_in_unit(
                    u.kilocalorie_per_mole),
            )
            action.execute()
Ejemplo n.º 24
0
 def test_ep_exceptions(self):
     """ Test Nonbonded exception handling with virtual sites """
     # Analyze the exception parameters for bonding pattern
     #
     # E1 -- A1 -- A2 -- A3 -- A4 -- A5 -- E5
     #             |     |     |
     #             E2    E3    E4
     struct = pmd.Structure()
     ep1 = ExtraPoint(name='E1', type='EP', atomic_number=0, weights=[1, 2])
     ep2 = ExtraPoint(name='E2', type='EP', atomic_number=0)
     ep3 = ExtraPoint(name='E3', type='EP', atomic_number=0)
     ep4 = ExtraPoint(name='E4', type='EP', atomic_number=0)
     ep5 = ExtraPoint(name='E5', type='EP', atomic_number=0)
     self.assertIs(ep1.parent, None)
     self.assertEqual(ep1.bond_partners, [])
     self.assertEqual(ep1.angle_partners, [])
     self.assertEqual(ep1.dihedral_partners, [])
     self.assertEqual(ep1.tortor_partners, [])
     self.assertEqual(ep1.exclusion_partners, [])
     a1 = pmd.Atom(name='A1', type='AX', charge=0.1, atomic_number=6)
     a2 = pmd.Atom(name='A2', type='AY', charge=0.1, atomic_number=6)
     a3 = pmd.Atom(name='A3', type='AZ', charge=0.1, atomic_number=7)
     a4 = pmd.Atom(name='A4', type='AX', charge=0.1, atomic_number=6)
     a5 = pmd.Atom(name='A5', type='AY', charge=0.1, atomic_number=6)
     a1.rmin = a2.rmin = a3.rmin = a4.rmin = a5.rmin = 0.5
     a1.epsilon = a2.epsilon = a3.epsilon = a4.epsilon = a5.epsilon = 1.0
     bond_type = pmd.BondType(10.0, 1.0)
     bond_type2 = pmd.BondType(10.0, 2.0)
     bond_type3 = pmd.BondType(10.0, 0.5)
     bond_type4 = pmd.BondType(10.0, math.sqrt(2))
     angle_type = pmd.AngleType(10.0, 90)
     dihedral_type = pmd.DihedralType(10.0, 2, 0)
     struct.add_atom(a1, 'RES', 1)
     struct.add_atom(a2, 'RES', 1)
     struct.add_atom(a3, 'RES', 1)
     struct.add_atom(a4, 'RES', 1)
     struct.add_atom(a5, 'RES', 1)
     struct.add_atom(ep1, 'RES', 1)
     struct.add_atom(ep2, 'RES', 1)
     struct.add_atom(ep3, 'RES', 1)
     struct.add_atom(ep4, 'RES', 1)
     struct.add_atom(ep5, 'RES', 1)
     struct.bonds.extend([
         pmd.Bond(a1, ep1, type=bond_type),
         pmd.Bond(ep2, a2, type=bond_type),
         pmd.Bond(a3, ep3, type=bond_type3),
         pmd.Bond(a4, ep4, type=bond_type)
     ])
     struct.bonds.extend([
         pmd.Bond(a1, a2, type=bond_type),
         pmd.Bond(a4, a3, type=bond_type4),
         pmd.Bond(a3, a2, type=bond_type4),
         pmd.Bond(a4, a5, type=bond_type2),
         pmd.Bond(a5, ep5, type=bond_type)
     ])
     struct.angles.extend([
         pmd.Angle(a1, a2, a3, type=angle_type),
         pmd.Angle(a2, a3, a4, type=angle_type),
         pmd.Angle(a3, a4, a5, type=angle_type)
     ])
     struct.dihedrals.extend([
         pmd.Dihedral(a1, a2, a3, a4, type=dihedral_type),
         pmd.Dihedral(a2, a3, a4, a5, type=dihedral_type)
     ])
     struct.bond_types.extend(
         [bond_type, bond_type3, bond_type2, bond_type4])
     struct.angle_types.append(angle_type)
     struct.dihedral_types.append(dihedral_type)
     # Test exclusions now
     a1.exclude(a5)
     system = struct.createSystem()
Ejemplo n.º 25
0
def _add_atom(parm, last_idx, template, htemplate):
    """
    Change the terminal hydrogen to a carbon and add three hydrogen atoms,
    also add bonded information

    Parameters
    ----------
    parm : parmed.Structure
        the topology
    last_idx : integer
        the index of the terminal carbon
    template : string
        the name prefix of the carbon atoms
    htemplate: string
        the name postfox of the hydrogen atoms
    """

    # Find all carbons preceeding the terminal carbon and the hydrogens
    # bonded to them
    carbons = []
    hydrogens = []
    for idx in range(last_idx - 2, last_idx + 1):
        carbons.append(_get_atom(parm, "%s%d" % (template, idx)))
        hydrogens.append(
            [_get_atom(parm, "H%d%s" % (idx, hstr)) for hstr in htemplate[:2]])

    # Change the charges of the carbon and hydrogens next to the terminal carbon
    carbons[1].charge = 0.0
    hydrogens[1][0].charge = 0.0
    hydrogens[1][1].charge = 0.0

    # Change the type and charge of the terminal carbon and its hydrogens
    carbons[2].charge = 0.0470
    carbons[2].type = "CTL2"
    for h in hydrogens[2]:
        h.charge = -0.0070
        h.type = "HAL2"

    # Find the final hydrogen and change it to a carbon
    hatom = _get_atom(parm, "H%d%s" % (last_idx, htemplate[2]))
    hatom.type = "CTL3"
    hatom.charge = -0.0810
    hatom.name = "%s%d" % (template, last_idx + 1)
    hatom.mass = 12.0110

    # Create 3 new hydrogen atoms and the topology information
    newatoms = []
    for i, hstr in enumerate(htemplate):
        newatom = parmed.Atom(list=parm.atoms,
                              name="H%d%s" % (last_idx + 1, hstr),
                              type="HAL3",
                              charge=0.0160,
                              mass=1.008000)
        newatom.residue = parm.residues[0]
        parm.residues[0].atoms.insert(hatom.idx + 1 + i, newatom)
        parm.atoms.insert(hatom.idx + 1 + i, newatom)
        parm.bonds.append(parmed.Bond(hatom, newatom))
        parm.adjusts.append(parmed.NonbondedException(carbons[1], newatom))
        parm.adjusts.append(parmed.NonbondedException(hydrogens[2][0],
                                                      newatom))
        parm.adjusts.append(parmed.NonbondedException(hydrogens[2][1],
                                                      newatom))
        parm.angles.append(parmed.Angle(carbons[2], hatom, newatom))
        parm.dihedrals.append(
            parmed.Dihedral(carbons[1], carbons[2], hatom, newatom))
        parm.dihedrals.append(
            parmed.Dihedral(hydrogens[2][0], carbons[2], hatom, newatom))
        parm.dihedrals.append(
            parmed.Dihedral(hydrogens[2][1], carbons[2], hatom, newatom))
        newatoms.append(newatom)

    # Add angles between thre three added hydrogens
    parm.angles.append(parmed.Angle(newatoms[0], hatom, newatoms[1]))
    parm.angles.append(parmed.Angle(newatoms[0], hatom, newatoms[2]))
    parm.angles.append(parmed.Angle(newatoms[1], hatom, newatoms[2]))

    # Correct the angle and dihedral types
    for angle in parm.angles[-12:]:
        angle.funct = 5
    for dihedral in parm.dihedrals[-9:]:
        dihedral.funct = 9