Exemple #1
0
    def dfs(at1: Atom, atom_set: Set[Atom]):
        at1._visited = True
        atom_set.add(at1)
        for at2 in at1.neighbors():

            if at2._visited:
                continue
            dfs(at2, atom_set)
Exemple #2
0
def set_dihed(self,
              angle: float,
              anchor: Atom,
              cap: Sequence[Atom],
              opt: bool = True,
              unit: str = 'degree') -> None:
    """Change all valid dihedral angles into a specific value.

    Performs an inplace update of this instance.

    Parameters
    ----------
    angle : :class:`float`
        The desired dihedral angle.

    anchor : |plams.Atom|
        The ligand anchor atom.

    opt : :class:`bool`
        Whether or not the dihedral adjustment should be followed up by an RDKit UFF optimization.

    unit : :class:`str`
        The input unit.

    """
    cap_atnum = []
    for at in cap:
        cap_atnum.append(at.atnum)
        at.atnum = 0

    angle = Units.convert(angle, unit, 'degree')
    bond_iter = (bond for bond in self.bonds
                 if bond.atom1.atnum != 1 and bond.atom2.atnum != 1
                 and bond.order == 1 and not self.in_ring(bond))

    # Correction factor for, most importantly, tri-valent anchors (e.g. P(R)(R)R)
    dihed_cor = angle / 2
    neighbors = anchor.neighbors()
    if len(neighbors) > 2:
        atom_list = [anchor] + sorted(neighbors, key=lambda at: -at.atnum)[:3]
        improper = get_dihed(atom_list)
        dihed_cor *= np.sign(improper)

    for bond in bond_iter:
        # Gather lists of all non-hydrogen neighbors
        n1, n2 = self.neighbors_mod(bond.atom1), self.neighbors_mod(bond.atom2)

        # Remove all atoms in `bond`
        n1 = [atom for atom in n1 if atom is not bond.atom2]
        n2 = [atom for atom in n2 if atom is not bond.atom1]

        # Remove all non-subsituted atoms
        # A special case consists of anchor atoms; they can stay
        if len(n1) > 1:
            n1 = [
                atom for atom in n1 if (len(self.neighbors_mod(atom)) > 1
                                        or atom is anchor or atom.atnum == 0)
            ]
        if len(n2) > 1:
            n2 = [
                atom for atom in n2 if (len(self.neighbors_mod(atom)) > 1
                                        or atom is anchor or atom.atnum == 0)
            ]

        # Set `bond` in an anti-periplanar conformation
        if n1 and n2:
            dihed = get_dihed((n1[0], bond.atom1, bond.atom2, n2[0]))
            if anchor not in bond:
                self.rotate_bond(bond,
                                 bond.atom1,
                                 angle - dihed,
                                 unit='degree')
            else:
                dihed -= dihed_cor
                self.rotate_bond(bond, bond.atom1, -dihed, unit='degree')
                dihed_cor *= -1

    for at, atnum in zip(cap, cap_atnum):
        at.atnum = atnum

    if opt:
        rdmol = molkit.to_rdmol(self)
        UFF(rdmol).Minimize()
        self.from_rdmol(rdmol)
Exemple #3
0
 def _besides_ring(atom: Atom) -> bool:
     """Check if any neighboring atoms are part of a ring system."""
     return any(plams_mol.in_ring(at) for at in atom.neighbors())