Ejemplo n.º 1
0
    def trigonal(self, atom):
        """Add hydrogens in trigonal geometry.

        Args:
            atom:  atom to protonate
        """
        _LOGGER.debug(
            'TRIGONAL - {0:d} bonded atoms'.format(len(atom.bonded_atoms))
        )
        rot_angle = math.radians(120.0)
        cvec = Vector(atom1=atom)
        # 0 bonds
        if len(atom.bonded_atoms) == 0:
            pass
        # 1 bond
        if len(atom.bonded_atoms) == 1 and atom.number_of_protons_to_add > 0:
            # Add another atom with the right angle to the first one
            avec = Vector(atom1=atom, atom2=atom.bonded_atoms[0])
            # use plane of bonded trigonal atom - e.g. arg
            self.set_steric_number_and_lone_pairs(atom.bonded_atoms[0])
            if (atom.bonded_atoms[0].steric_number == 3
                    and len(atom.bonded_atoms[0].bonded_atoms) > 1):
                # use other atoms bonded to the neighbour to establish the
                # plane, if possible
                other_atom_indices = []
                for i, bonded_atom in enumerate(
                        atom.bonded_atoms[0].bonded_atoms):
                    if bonded_atom != atom:
                        other_atom_indices.append(i)
                vec1 = Vector(atom1=atom, atom2=atom.bonded_atoms[0])
                vec2 = Vector(atom1=atom.bonded_atoms[0],
                              atom2=atom.bonded_atoms[0]
                              .bonded_atoms[other_atom_indices[0]])
                axis = vec1**vec2
                # this is a trick to make sure that the order of atoms doesn't
                # influence the final postions of added protons
                if len(other_atom_indices) > 1:
                    vec3 = Vector(atom1=atom.bonded_atoms[0],
                                  atom2=atom.bonded_atoms[0]
                                  .bonded_atoms[other_atom_indices[1]])
                    axis2 = vec1**vec3
                    if axis*axis2 > 0:
                        axis = axis+axis2
                    else:
                        axis = axis-axis2
            else:
                axis = avec.orthogonal()
            avec = rotate_vector_around_an_axis(rot_angle, axis, avec)
            avec = self.set_bond_distance(avec, atom.element)
            self.add_proton(atom, cvec+avec)
        # 2 bonds
        if len(atom.bonded_atoms) == 2 and atom.number_of_protons_to_add > 0:
            # Add another atom with the right angle to the first two
            avec1 = Vector(atom1=atom, atom2=atom.bonded_atoms[0]).rescale(1.0)
            avec2 = Vector(atom1=atom, atom2=atom.bonded_atoms[1]).rescale(1.0)

            new_a = -avec1 - avec2
            new_a = self.set_bond_distance(new_a, atom.element)
            self.add_proton(atom, cvec+new_a)
Ejemplo n.º 2
0
def are_atoms_planar(atoms):
    """Test whether a group of atoms are planar.

    Args:
        atoms:  list of atoms
    Returns:
        Boolean
    """
    if len(atoms) == 0:
        return False
    if len(atoms) < 4:
        return False
    vec1 = Vector(atom1=atoms[0], atom2=atoms[1])
    vec2 = Vector(atom1=atoms[0], atom2=atoms[2])
    norm = (vec1**vec2).rescale(1.0)
    margin = PLANARITY_MARGIN
    for atom in atoms[3:]:
        vec = Vector(atom1=atoms[0], atom2=atom).rescale(1.0)
        if abs(vec * norm) > margin:
            return False
    return True
Ejemplo n.º 3
0
    def tetrahedral(self, atom):
        """Protonate atom in tetrahedral geometry.

        Args:
            atom:  atom to protonate.
        """
        debug('TETRAHEDRAL - {0:d} bonded atoms'.format(len(
            atom.bonded_atoms)))
        # TODO - might be good to move tetrahedral angle to constant
        rot_angle = math.radians(109.5)
        cvec = Vector(atom1=atom)
        # 0 bonds
        if len(atom.bonded_atoms) == 0:
            pass
        # 1 bond
        if len(atom.bonded_atoms) == 1 and atom.number_of_protons_to_add > 0:
            # Add another atom with the right angle to the first one
            avec = Vector(atom1=atom, atom2=atom.bonded_atoms[0])
            axis = avec.orthogonal()
            avec = rotate_vector_around_an_axis(rot_angle, axis, avec)
            avec = self.set_bond_distance(avec, atom.element)
            self.add_proton(atom, cvec + avec)
        # 2 bonds
        if len(atom.bonded_atoms) == 2 and atom.number_of_protons_to_add > 0:
            # Add another atom with the right angle to the first two
            avec1 = Vector(atom1=atom, atom2=atom.bonded_atoms[0]).rescale(1.0)
            avec2 = Vector(atom1=atom, atom2=atom.bonded_atoms[1]).rescale(1.0)
            axis = avec1 + avec2
            new_a = rotate_vector_around_an_axis(math.radians(90), axis,
                                                 -avec1)
            new_a = self.set_bond_distance(new_a, atom.element)
            self.add_proton(atom, cvec + new_a)
        # 3 bonds
        if len(atom.bonded_atoms) == 3 and atom.number_of_protons_to_add > 0:
            avec1 = Vector(atom1=atom, atom2=atom.bonded_atoms[0]).rescale(1.0)
            avec2 = Vector(atom1=atom, atom2=atom.bonded_atoms[1]).rescale(1.0)
            avec3 = Vector(atom1=atom, atom2=atom.bonded_atoms[2]).rescale(1.0)
            new_a = -avec1 - avec2 - avec3
            new_a = self.set_bond_distance(new_a, atom.element)
            self.add_proton(atom, cvec + new_a)