Exemple #1
0
        def add_hydrogens(atom):
            existing_bonds = list(atom.iter_bonds())
            bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE)
            num_hydrogens = self.parameters.num_hydrogens

            if len(existing_bonds) == 0:
                t = atom.transformation.t + numpy.array([0, bond_length, 0])
                H = Atom(name="auto H",
                         number=1,
                         transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                existing_bonds.append(bond)
                num_hydrogens -= 1

            main_direction = numpy.zeros(3, float)
            for bond in existing_bonds:
                shortest_vector = bond.shortest_vector_relative_to(atom.parent)
                if bond.children[1].target == atom:
                    shortest_vector *= -1
                main_direction += shortest_vector

            main_direction /= numpy.linalg.norm(main_direction)
            normal = random_orthonormal(main_direction)

            rotation = Rotation.from_properties(
                2 * numpy.pi / float(num_hydrogens), main_direction, False)

            h_pos = bond_length * (
                main_direction * numpy.cos(self.parameters.valence_angle) +
                normal * numpy.sin(self.parameters.valence_angle))

            for i in range(num_hydrogens):
                t = atom.transformation.t + h_pos
                H = Atom(name="auto H",
                         number=1,
                         transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                h_pos = rotation * h_pos
Exemple #2
0
        def add_hydrogens(atom):
            existing_bonds = list(atom.iter_bonds())
            bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE)
            num_hydrogens = self.parameters.num_hydrogens

            if len(existing_bonds) == 0:
                t = atom.transformation.t + numpy.array([0,bond_length,0])
                H = Atom(name="auto H", number=1, transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                existing_bonds.append(bond)
                num_hydrogens -= 1

            main_direction = numpy.zeros(3, float)
            for bond in existing_bonds:
                shortest_vector = bond.shortest_vector_relative_to(atom.parent)
                if bond.children[1].target == atom:
                    shortest_vector *= -1
                main_direction += shortest_vector

            main_direction /= numpy.linalg.norm(main_direction)
            normal = random_orthonormal(main_direction)

            rotation = Rotation.from_properties(2*numpy.pi / float(num_hydrogens), main_direction, False)


            h_pos = bond_length*(
                main_direction*numpy.cos(self.parameters.valence_angle) +
                normal*numpy.sin(self.parameters.valence_angle)
            )

            for i in range(num_hydrogens):
                t = atom.transformation.t + h_pos
                H = Atom(name="auto H", number=1, transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                h_pos = rotation * h_pos
Exemple #3
0
    def __init__(self, graph, unit_cell=None):
        """
           Argument:
            | ``graph``  --  the molecular graph from which the force field terms
                             are extracted. See
                             :class:molmod.molecular_graphs.MolecularGraph

           Optional argument:
            | ``unit_cell``  --  periodic boundry conditions, see
                                 :class:`molmod.unit_cells.UnitCell`
        """
        from molmod.bonds import bonds

        if unit_cell is None:
            self.matrix = None
            self.reciprocal = None
        else:
            self.matrix = unit_cell.matrix
            self.reciprocal = unit_cell.reciprocal

        self.dm = graph.distances.astype(numpy.int32)
        dm = self.dm.astype(float)
        self.dm0 = dm**2
        self.dmk = (dm+0.1)**(-3)
        self.vdw_radii = numpy.array([periodic[number].vdw_radius for number in graph.numbers], dtype=float)
        self.covalent_radii = numpy.array([periodic[number].covalent_radius for number in graph.numbers], dtype=float)

        bond_edges = []
        bond_lengths = []
        for i, j in graph.edges:
            bond_edges.append((i, j))
            bond_lengths.append(bonds.get_length(graph.numbers[i], graph.numbers[j]))
        self.bond_edges = numpy.array(bond_edges, numpy.int32)
        self.bond_lengths = numpy.array(bond_lengths, float)

        special_angles = SpecialAngles()

        span_edges = []
        span_lengths = []
        for i, neighbors in graph.neighbors.iteritems():
            number_i = graph.numbers[i]
            if (number_i >= 5 and number_i <=8):
                valence = len(neighbors) + abs(number_i-6)
            elif number_i >= 13 and number_i <= 16:
                valence = len(neighbors) + abs(number_i-14)
            else:
                valence = -1
            if valence < 2 or valence > 6:
                default_angle = numpy.pi/180.0*115.0
            elif valence == 2:
                default_angle = numpy.pi
            elif valence == 3:
                default_angle = numpy.pi/180.0*125.0
            elif valence == 4:
                default_angle = numpy.pi/180.0*109.0
            elif valence == 5:
                default_angle = numpy.pi/180.0*100.0
            elif valence == 6:
                default_angle = numpy.pi/180.0*90.0
            for j in neighbors:
                number_j = graph.numbers[j]
                for k in neighbors:
                    if j < k and not frozenset([j, k]) in graph.edges:
                        number_k = graph.numbers[k]

                        triplet = (
                            number_j, len(graph.neighbors[j]),
                            number_i, len(graph.neighbors[i]),
                            number_k, len(graph.neighbors[k]),
                        )

                        angle = special_angles.get_angle(triplet)
                        if angle is None:
                            angle = default_angle

                        dj = bonds.get_length(number_i, number_j)
                        dk = bonds.get_length(number_i, number_k)
                        d = numpy.sqrt(dj**2+dk**2-2*dj*dk*numpy.cos(angle))
                        span_edges.append((j, k))
                        span_lengths.append(d)
        self.span_edges = numpy.array(span_edges, numpy.int32)
        self.span_lengths = numpy.array(span_lengths, float)

        self.dm_quad = 0.0
        self.dm_reci = 0.0
        self.bond_quad = 0.0
        self.span_quad = 0.0
        self.bond_hyper = 0.0
        self.bond_hyper_scale = 5.0
Exemple #4
0
        def add_hydrogens(atom):
            existing_bonds = list(atom.iter_bonds())
            num_bonds = len(existing_bonds)
            bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE)

            if num_bonds == 0:
                t = atom.transformation.t + numpy.array([0, bond_length, 0])
                H = Atom(name="auto H",
                         number=1,
                         transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                existing_bonds.append(bond)
                num_bonds = 1

            used_valence = 0
            oposite_direction = numpy.zeros(3, float)
            for bond in existing_bonds:
                shortest_vector = bond.shortest_vector_relative_to(atom.parent)
                if bond.children[1].target == atom:
                    shortest_vector *= -1
                oposite_direction -= shortest_vector

                if bond.bond_type == BOND_SINGLE:
                    used_valence += 1
                elif bond.bond_type == BOND_DOUBLE:
                    used_valence += 2
                elif bond.bond_type == BOND_TRIPLE:
                    used_valence += 3

            oposite_direction /= numpy.linalg.norm(oposite_direction)

            num_hydrogens = valence_el(
                atom.number) - 2 * lone_pairs(atom.number) - used_valence
            if num_hydrogens <= 0:
                return

            hybride_count = num_hydrogens + lone_pairs(
                atom.number) + num_bonds - (used_valence - num_bonds)
            num_sites = num_hydrogens + lone_pairs(atom.number)
            rotation = Rotation.from_properties(
                2 * numpy.pi / float(num_sites), oposite_direction, False)
            opening_key = (hybride_count, num_sites)
            opening_angle = self.opening_angles.get(opening_key)
            if opening_angle is None:
                return

            if num_bonds == 1:
                first_bond = existing_bonds[0]
                other_atom = first_bond.children[0].target
                if other_atom == atom:
                    other_atom = first_bond.children[1].target
                other_bonds = [
                    bond for bond in other_atom.iter_bonds()
                    if bond != first_bond
                ]
                if len(other_bonds) > 0:
                    normal = other_bonds[0].shortest_vector_relative_to(
                        atom.parent)
                    normal -= numpy.dot(normal,
                                        oposite_direction) * oposite_direction
                    normal /= numpy.linalg.norm(normal)
                    if other_bonds[0].children[0].target == other_atom:
                        normal *= -1
                else:
                    normal = random_orthonormal(oposite_direction)
            elif num_bonds == 2:
                normal = numpy.cross(
                    oposite_direction,
                    existing_bonds[0].shortest_vector_relative_to(atom.parent))
                normal /= numpy.linalg.norm(normal)
            elif num_bonds == 3:
                normal = random_orthonormal(oposite_direction)
            else:
                return

            h_pos = bond_length * (oposite_direction * numpy.cos(opening_angle)
                                   + normal * numpy.sin(opening_angle))

            for i in range(num_hydrogens):
                t = atom.transformation.t + h_pos
                H = Atom(name="auto H",
                         number=1,
                         transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                h_pos = rotation * h_pos
Exemple #5
0
    def replace(self, gl_object):
        if not gl_object.get_fixed():
            new = self.get_new(gl_object.transformation.t)

            # select a target object, i.e. the one the will be connected with
            # the bonds/vectors/... of the replaced object
            if (self.current_object == "Fragment"):
                # fragments are inserted as frames
                # take atom with index 1 as target
                target_object = new.children[1]
            else:
                target_object = new
            # check if all connections to the replaced object are applicable
            # to the new object. if not, then do not perform the replacement
            # and return early.
            for reference in gl_object.references[::-1]:
                if not reference.check_target(target_object):
                    return
            # add the new object
            parent = gl_object.parent
            primitive.Add(new, parent)

            if (self.current_object == "Fragment"):
                # Fix the rotation and translation of the molecular fragment.
                # Rotation
                Bond = context.application.plugins.get_node("Bond")
                if len(gl_object.references) == 1 and isinstance(
                        gl_object.references[0].parent, Bond):
                    bond1 = gl_object.references[0].parent
                    direction1 = bond1.shortest_vector_relative_to(parent)
                    if bond1.children[0].target != gl_object:
                        direction1 *= -1
                    bond2 = new.children[0].references[0].parent
                    direction2 = bond2.shortest_vector_relative_to(parent)
                    if bond2.children[0].target != target_object:
                        direction2 *= -1
                    axis = numpy.cross(direction2, direction1)
                    if numpy.linalg.norm(axis) < 1e-8:
                        axis = random_orthonormal(direction1)
                    angle = compute_angle(direction1, direction2)
                    rotation = Rotation.from_properties(angle, axis, False)
                    primitive.Transform(new, rotation)
                else:
                    bond1 = None
                # Tranlsation
                pos_old = new.children[1].get_frame_relative_to(parent).t
                pos_new = gl_object.transformation.t
                translation = Translation(pos_new - pos_old)
                primitive.Transform(new, translation)
                if bond1 != None:
                    # bond length
                    old_length = numpy.linalg.norm(direction1)
                    new_length = bonds.get_length(
                        new.children[1].number,
                        bond1.get_neighbor(gl_object).number)
                    translation = Translation(-direction1 / old_length *
                                              (new_length - old_length))
                    primitive.Transform(new, translation)

            # let the references to the replaced object point to the new object
            for reference in gl_object.references[::-1]:
                try:
                    primitive.SetTarget(reference, target_object)
                except primitive.PrimitiveError:
                    primitive.Delete(reference.parent)
            # delete the replaced object
            primitive.Delete(gl_object)
            if (self.current_object == "Fragment"):
                # Delete the first atom in the fragment
                primitive.Delete(new.children[0])
                # Unframe the fragment
                UnframeAbsolute = context.application.plugins.get_action(
                    "UnframeAbsolute")
                UnframeAbsolute([new])
Exemple #6
0
    def replace(self, gl_object):
        if not gl_object.get_fixed():
            new = self.get_new(gl_object.transformation.t)

            # select a target object, i.e. the one the will be connected with
            # the bonds/vectors/... of the replaced object
            if(self.current_object == "Fragment"):
                # fragments are inserted as frames
                # take atom with index 1 as target
                target_object = new.children[1]
            else:
                target_object = new
            # check if all connections to the replaced object are applicable
            # to the new object. if not, then do not perform the replacement
            # and return early.
            for reference in gl_object.references[::-1]:
                if not reference.check_target(target_object):
                    return
            # add the new object
            parent = gl_object.parent
            primitive.Add(new, parent)

            if(self.current_object == "Fragment"):
                # Fix the rotation and translation of the molecular fragment.
                # Rotation
                Bond = context.application.plugins.get_node("Bond")
                if len(gl_object.references) == 1 and isinstance(gl_object.references[0].parent, Bond):
                    bond1 = gl_object.references[0].parent
                    direction1 = bond1.shortest_vector_relative_to(parent)
                    if bond1.children[0].target != gl_object:
                        direction1 *= -1
                    bond2 = new.children[0].references[0].parent
                    direction2 = bond2.shortest_vector_relative_to(parent)
                    if bond2.children[0].target != target_object:
                        direction2 *= -1
                    axis = numpy.cross(direction2, direction1)
                    if numpy.linalg.norm(axis) < 1e-8:
                        axis = random_orthonormal(direction1)
                    angle = compute_angle(direction1, direction2)
                    rotation = Rotation.from_properties(angle, axis, False)
                    primitive.Transform(new, rotation)
                else:
                    bond1 = None
                # Tranlsation
                pos_old = new.children[1].get_frame_relative_to(parent).t
                pos_new = gl_object.transformation.t
                translation = Translation(pos_new - pos_old)
                primitive.Transform(new, translation)
                if bond1 != None:
                    # bond length
                    old_length = numpy.linalg.norm(direction1)
                    new_length = bonds.get_length(new.children[1].number, bond1.get_neighbor(gl_object).number)
                    translation = Translation(-direction1/old_length*(new_length-old_length))
                    primitive.Transform(new, translation)

            # let the references to the replaced object point to the new object
            for reference in gl_object.references[::-1]:
                try:
                    primitive.SetTarget(reference, target_object)
                except primitive.PrimitiveError:
                    primitive.Delete(reference.parent)
            # delete the replaced object
            primitive.Delete(gl_object)
            if(self.current_object == "Fragment"):
                # Delete the first atom in the fragment
                primitive.Delete(new.children[0])
                # Unframe the fragment
                UnframeAbsolute = context.application.plugins.get_action("UnframeAbsolute")
                UnframeAbsolute([new])
Exemple #7
0
    def __init__(self, graph, unit_cell=None):
        """
           Argument:
            | ``graph``  --  the molecular graph from which the force field terms
                             are extracted. See
                             :class:molmod.molecular_graphs.MolecularGraph

           Optional argument:
            | ``unit_cell``  --  periodic boundry conditions, see
                                 :class:`molmod.unit_cells.UnitCell`
        """
        from molmod.bonds import bonds

        if unit_cell is None:
            self.matrix = None
            self.reciprocal = None
        else:
            self.matrix = unit_cell.matrix
            self.reciprocal = unit_cell.reciprocal

        self.dm = graph.distances.astype(int)
        dm = self.dm.astype(float)
        self.dm0 = dm**2
        self.dmk = (dm + 0.1)**(-3)
        self.vdw_radii = np.array(
            [periodic[number].vdw_radius for number in graph.numbers],
            dtype=float)
        self.covalent_radii = np.array(
            [periodic[number].covalent_radius for number in graph.numbers],
            dtype=float)

        bond_edges = []
        bond_lengths = []
        for i, j in graph.edges:
            bond_edges.append((i, j))
            bond_lengths.append(
                bonds.get_length(graph.numbers[i], graph.numbers[j]))
        self.bond_edges = np.array(bond_edges, int)
        self.bond_lengths = np.array(bond_lengths, float)

        special_angles = SpecialAngles()

        span_edges = []
        span_lengths = []
        for i, neighbors in graph.neighbors.items():
            number_i = graph.numbers[i]
            if (number_i >= 5 and number_i <= 8):
                valence = len(neighbors) + abs(number_i - 6)
            elif number_i >= 13 and number_i <= 16:
                valence = len(neighbors) + abs(number_i - 14)
            else:
                valence = -1
            if valence < 2 or valence > 6:
                default_angle = np.pi / 180.0 * 115.0
            elif valence == 2:
                default_angle = np.pi
            elif valence == 3:
                default_angle = np.pi / 180.0 * 125.0
            elif valence == 4:
                default_angle = np.pi / 180.0 * 109.0
            elif valence == 5:
                default_angle = np.pi / 180.0 * 100.0
            elif valence == 6:
                default_angle = np.pi / 180.0 * 90.0
            for j in neighbors:
                number_j = graph.numbers[j]
                for k in neighbors:
                    if j < k and not frozenset([j, k]) in graph.edges:
                        number_k = graph.numbers[k]

                        triplet = (
                            number_j,
                            len(graph.neighbors[j]),
                            number_i,
                            len(graph.neighbors[i]),
                            number_k,
                            len(graph.neighbors[k]),
                        )

                        angle = special_angles.get_angle(triplet)
                        if angle is None:
                            angle = default_angle

                        dj = bonds.get_length(number_i, number_j)
                        dk = bonds.get_length(number_i, number_k)
                        d = np.sqrt(dj**2 + dk**2 -
                                    2 * dj * dk * np.cos(angle))
                        span_edges.append((j, k))
                        span_lengths.append(d)
        self.span_edges = np.array(span_edges, int)
        self.span_lengths = np.array(span_lengths, float)

        self.dm_quad = 0.0
        self.dm_reci = 0.0
        self.bond_quad = 0.0
        self.span_quad = 0.0
        self.bond_hyper = 0.0
        self.bond_hyper_scale = 5.0
Exemple #8
0
        def add_hydrogens(atom):
            existing_bonds = list(atom.iter_bonds())
            num_bonds = len(existing_bonds)
            bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE)

            if num_bonds == 0:
                t = atom.transformation.t + numpy.array([0,bond_length,0])
                H = Atom(name="auto H", number=1, transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                existing_bonds.append(bond)
                num_bonds = 1

            used_valence = 0
            oposite_direction = numpy.zeros(3, float)
            for bond in existing_bonds:
                shortest_vector = bond.shortest_vector_relative_to(atom.parent)
                if bond.children[1].target == atom:
                    shortest_vector *= -1
                oposite_direction -= shortest_vector

                if bond.bond_type == BOND_SINGLE:
                    used_valence += 1
                elif bond.bond_type == BOND_DOUBLE:
                    used_valence += 2
                elif bond.bond_type == BOND_TRIPLE:
                    used_valence += 3

            oposite_direction /= numpy.linalg.norm(oposite_direction)

            num_hydrogens = valence_el(atom.number) - 2*lone_pairs(atom.number) - used_valence
            if num_hydrogens <= 0:
                return

            hybride_count = num_hydrogens + lone_pairs(atom.number) + num_bonds - (used_valence - num_bonds)
            num_sites = num_hydrogens + lone_pairs(atom.number)
            rotation = Rotation.from_properties(2*numpy.pi / float(num_sites), oposite_direction, False)
            opening_key = (hybride_count, num_sites)
            opening_angle = self.opening_angles.get(opening_key)
            if opening_angle is None:
                return

            if num_bonds == 1:
                first_bond = existing_bonds[0]
                other_atom = first_bond.children[0].target
                if other_atom == atom:
                    other_atom = first_bond.children[1].target
                other_bonds = [bond for bond in other_atom.iter_bonds() if bond != first_bond]
                if len(other_bonds) > 0:
                    normal = other_bonds[0].shortest_vector_relative_to(atom.parent)
                    normal -= numpy.dot(normal, oposite_direction) * oposite_direction
                    normal /= numpy.linalg.norm(normal)
                    if other_bonds[0].children[0].target == other_atom:
                        normal *= -1
                else:
                    normal = random_orthonormal(oposite_direction)
            elif num_bonds == 2:
                normal = numpy.cross(oposite_direction, existing_bonds[0].shortest_vector_relative_to(atom.parent))
                normal /= numpy.linalg.norm(normal)
            elif num_bonds == 3:
                normal = random_orthonormal(oposite_direction)
            else:
                return

            h_pos = bond_length*(oposite_direction*numpy.cos(opening_angle) + normal*numpy.sin(opening_angle))

            for i in range(num_hydrogens):
                t = atom.transformation.t + h_pos
                H = Atom(name="auto H", number=1, transformation=Translation(t))
                primitive.Add(H, atom.parent)
                bond = Bond(name="aut H bond", targets=[atom, H])
                primitive.Add(bond, atom.parent)
                h_pos = rotation * h_pos