Ejemplo n.º 1
1
    def do_molgrid(self):
        self.molgrid = Grid.from_prefix("molecule", self.work)
        if self.molgrid is not None:
            self.molgrid.weights = self.molgrid.load("weights")
        else:
            # we have to generate a new grid. The grid is constructed taking
            # into account the following considerations:
            # 1) Grid points within the cusp region are discarded
            # 2) The rest of the molecular and surrounding volume is sampled
            #    with spherical grids centered on the atoms. Around each atom,
            #    'scale_steps' of shells are placed with lebedev grid points
            #    (num_lebedev). The lebedev weights are used in the fit to
            #    avoid preferential directions within one shell.
            # 3) The radii of the shells start from scale_min*(cusp_radius+0.2)
            #    and go up to scale_max*(cusp_radius+0.2).
            # 4) Each shell will be randomly rotated around the atom to avoid
            #    global preferential directions in the grid.
            # 5) The default parameters for the grid should be sufficient for
            #    sane ESP fitting. The ESP cost function should discard points
            #    with a density larger than a threshold, i.e. 1e-5 a.u. A
            #    gradual transition between included and discarded points around
            #    this threshold will improve the quality of the fit.

            lebedev_xyz, lebedev_weights = get_lebedev_grid(50)
            self.do_noble_radii()

            scale_min = 1.5
            scale_max = 30.0
            scale_steps = 30
            scale_factor = (scale_max/scale_min)**(1.0/(scale_steps-1))
            scales = scale_min*scale_factor**numpy.arange(scale_steps)

            points = []
            weights = []
            pb = log.pb("Constructing molecular grid", scale_steps)
            for scale in scales:
                pb()
                radii = scale*self.noble_radii
                for i in xrange(self.molecule.size):
                    rot = Rotation.random()
                    for j in xrange(len(lebedev_xyz)):
                        my_point = radii[i]*numpy.dot(rot.r, lebedev_xyz[j]) + self.molecule.coordinates[i]
                        distances = numpy.sqrt(((self.molecule.coordinates - my_point)**2).sum(axis=1))
                        if (distances < scales[0]*self.noble_radii).any():
                            continue
                        points.append(my_point)
                        weights.append(lebedev_weights[j])
            pb()
            points = numpy.array(points)
            weights = numpy.array(weights)

            self.molgrid = Grid("molecule", self.work, points)
            self.molgrid.weights = weights
            self.molgrid.dump("weights", weights)
Ejemplo n.º 2
0
    def ask_parameters(self):
        cache = context.application.cache
        nodes = cache.nodes
        last = cache.last
        next_to_last = cache.next_to_last

        if isinstance(last, Vector):
            if (len(nodes) >= 2) and isinstance(next_to_last, Vector):
                parent = nodes[-2].parent
                b1 = last.children[0].translation_relative_to(parent)
                e1 = last.children[1].translation_relative_to(parent)
                b2 = next_to_last.children[0].translation_relative_to(parent)
                e2 = next_to_last.children[1].translation_relative_to(parent)
                if (b1 is not None) and (e1 is not None) and (b2 is not None) and (e2 is not None):
                    angle = compute_angle(e1 - b1, e2 - b2)
                    axis = numpy.cross(e1 - b1, e2 - b2)
                    self.parameters.center = Translation(0.5*(b1+b2))
                    self.parameters.rotation = Rotation.from_properties(angle, axis, False)
            else:
                parent = next_to_last.parent
                b = last.children[0].translation_relative_to(parent)
                e = last.children[1].translation_relative_to(parent)
                if (b is not None) and (e is not None):
                    self.parameters.center = Translation(b)
                    self.parameters.rotation = Rotation.from_properties(numpy.pi*0.25, e - b, False)
        elif isinstance(last, GLTransformationMixin) and isinstance(last.transformation, Translation):
            parent = last.parent
            self.parameters.center = Translation(last.get_frame_relative_to(parent).t)
            self.parameters.rotation = Rotation.identity()
        else:
            self.parameters.center = Translation(calculate_center(cache.translations))

        if self.parameters_dialog.run(self.parameters) != gtk.RESPONSE_OK:
            self.parameters.clear()
Ejemplo n.º 3
0
 def set_transformation(self, transformation, init=False):
     if not transformation.__class__ == self.Transformation:
         # create an object of the proper type and take only the attributes
         # of interest.
         if isinstance(transformation, Translation):
             t = transformation.t
         else:
             t = None
         if isinstance(transformation, Rotation):
             r = transformation.r
         else:
             r = None
         if self.Transformation == Translation:
             if t is None:
                 transformation = Translation.identity()
             else:
                 transformation = Translation(t)
         elif self.Transformation == Rotation:
             if r is None:
                 transformation = Rotation.identity()
             else:
                 transformation = Rotation(r)
         else:  # self.Transformation == Complete:
             if r is None:
                 r = numpy.identity(3, float)
             if t is None:
                 t = numpy.zeros(3, float)
             transformation = Complete(r, t)
     self.transformation = transformation
     if not init:
         self.invalidate_transformation_list()
Ejemplo n.º 4
0
 def do_rotation(self, drawing_area, rotation_angle, rotation_axis):
     camera = context.application.camera
     # Note that the camera must be rotated in the opposite direction to
     # let the scene rotate in the right direction.
     rotation = Rotation.from_properties(-rotation_angle, rotation_axis, False)
     camera.rotation = camera.rotation * rotation
     drawing_area.queue_draw()
Ejemplo n.º 5
0
    def fn():
        context.application.model.file_open("test/input/precursor.zml")
        context.application.main.select_nodes(context.application.model.universe.children)

        ScanForConnections = context.application.plugins.get_action("ScanForConnections")
        rotation2 = Rotation.from_properties(1*numpy.pi, [0, 1, 0], False)

        parameters = ScanForConnections.default_parameters()
        parameters.connect_description1 = (
            Expression("isinstance(node, Atom) and node.number == 8 and node.num_bonds() == 1"),
            Expression("node.get_radius()"),
        )
        parameters.repulse_description1 = (
            Expression("isinstance(node, Atom) and (node.number == 8 or node.number == 14)"),
            Expression("node.get_radius()*1.5"),
        )
        parameters.action_radius = 4*angstrom
        parameters.hit_tolerance = 0.1*angstrom
        parameters.rotation2 = rotation2

        assert ScanForConnections.analyze_selection(parameters)
        ScanForConnections(parameters)

        # Try to save the result to file an open it again.
        context.application.model.file_save("test/output/tmp.zml")
        FileNew = context.application.plugins.get_action("FileNew")
        FileNew()
        context.application.model.file_open("test/output/tmp.zml")

        # Do some consistency tests on the connection scanner results:
        for quality, transformation, pairs, inverse_pairs in context.application.model.folder.children[0].get_connections():
            assert_arrays_almost_equal(transformation.r, rotation2.r)
            assert len(pairs) >= 2
            if len(inverse_pairs) > 0:
                assert len(pairs) == len(inverse_pairs)
Ejemplo n.º 6
0
 def set_transformation(self, transformation, init=False):
     if not transformation.__class__ == self.Transformation:
         # create an object of the proper type and take only the attributes
         # of interest.
         if isinstance(transformation, Translation):
             t = transformation.t
         else:
             t = None
         if isinstance(transformation, Rotation):
             r = transformation.r
         else:
             r = None
         if self.Transformation == Translation:
             if t is None:
                 transformation = Translation.identity()
             else:
                 transformation = Translation(t)
         elif self.Transformation == Rotation:
             if r is None:
                 transformation = Rotation.identity()
             else:
                 transformation = Rotation(r)
         else:  # self.Transformation == Complete:
             if r is None:
                 r = numpy.identity(3, float)
             if t is None:
                 t = numpy.zeros(3, float)
             transformation = Complete(r, t)
     self.transformation = transformation
     if not init:
         self.invalidate_transformation_list()
Ejemplo n.º 7
0
 def fn():
     FileNew = context.application.plugins.get_action("FileNew")
     FileNew()
     context.application.main.select_nodes([context.application.model.universe])
     Frame = context.application.plugins.get_node("Frame")
     frame = Frame(transformation=Translation(numpy.random.uniform(-5, 5, 3)))
     context.application.model.universe.add(frame)
     frame.set_transformation(Rotation.random())
Ejemplo n.º 8
0
 def reset(self):
     config = context.application.configuration
     self.rotation_center = Translation.identity()
     self.rotation = Rotation.identity()
     self.eye = Translation([0, 0, config.viewer_distance])
     self.opening_angle = config.opening_angle
     self.window_size = config.window_size
     self.window_depth = config.window_depth
Ejemplo n.º 9
0
 def do_rotation(self, drawing_area, rotation_angle, rotation_axis):
     camera = context.application.camera
     # Note that the camera must be rotated in the opposite direction to
     # let the scene rotate in the right direction.
     rotation = Rotation.from_properties(-rotation_angle, rotation_axis,
                                         False)
     camera.rotation = camera.rotation * rotation
     drawing_area.queue_draw()
Ejemplo n.º 10
0
 def fn():
     context.application.model.file_open("test/input/core_objects.zml")
     context.application.main.toggle_selection(context.application.model.universe.children[3], on=True)
     parameters = Parameters()
     parameters.rotation = Rotation.from_properties(1.0, numpy.array([0.1, 1.4, 0.3]), False)
     RotateDialog = context.application.plugins.get_action("RotateDialog")
     assert RotateDialog.analyze_selection(parameters)
     RotateDialog(parameters)
Ejemplo n.º 11
0
 def reset(self):
     config = context.application.configuration
     self.rotation_center = Translation.identity()
     self.rotation = Rotation.identity()
     self.eye = Translation([0,0,config.viewer_distance])
     self.opening_angle = config.opening_angle
     self.window_size = config.window_size
     self.window_depth = config.window_depth
Ejemplo n.º 12
0
 def do_rotation(self, rotation_angle, rotation_axis):
     rotation_axis = numpy.dot(self.eye_rotation, rotation_axis)
     if self.rotation_axis is not None:
         if numpy.dot(self.rotation_axis, rotation_axis) > 0:
             rotation_axis = self.rotation_axis
         else:
             rotation_axis = -self.rotation_axis
     rotation = Rotation.from_properties(rotation_angle, rotation_axis, False)
     self.victim.set_transformation(self.rotation_center * (rotation * (self.rotation_center.inv * self.victim.transformation)))
     context.application.main.drawing_area.queue_draw()
     self.changed = True
Ejemplo n.º 13
0
 def generate_points(self, center, rs):
     points = numpy.zeros((self.num_lebedev*len(rs),3), float)
     start = 0
     for r in rs:
         end = start + self.num_lebedev
         xyz = self.lebedev_xyz
         if self.do_random:
             rot = Rotation.random()
             xyz = numpy.dot(xyz,rot.r)
         points[start:end] = r*xyz+center
         start = end
     return points
Ejemplo n.º 14
0
 def generate_points(self, center, rs):
     points = numpy.zeros((self.num_lebedev * len(rs), 3), float)
     start = 0
     for r in rs:
         end = start + self.num_lebedev
         xyz = self.lebedev_xyz
         if self.do_random:
             rot = Rotation.random()
             xyz = numpy.dot(xyz, rot.r)
         points[start:end] = r * xyz + center
         start = end
     return points
Ejemplo n.º 15
0
    def ask_parameters(self):
        cache = context.application.cache
        nodes = cache.nodes
        last = cache.last
        next_to_last = cache.next_to_last

        if isinstance(last, Vector):
            if (len(nodes) >= 2) and isinstance(next_to_last, Vector):
                parent = nodes[-2].parent
                b1 = last.children[0].translation_relative_to(parent)
                e1 = last.children[1].translation_relative_to(parent)
                b2 = next_to_last.children[0].translation_relative_to(parent)
                e2 = next_to_last.children[1].translation_relative_to(parent)
                if (b1 is not None) and (e1 is not None) and (
                        b2 is not None) and (e2 is not None):
                    angle = compute_angle(e1 - b1, e2 - b2)
                    axis = numpy.cross(e1 - b1, e2 - b2)
                    self.parameters.center = Translation(0.5 * (b1 + b2))
                    self.parameters.rotation = Rotation.from_properties(
                        angle, axis, False)
            else:
                parent = next_to_last.parent
                b = last.children[0].translation_relative_to(parent)
                e = last.children[1].translation_relative_to(parent)
                if (b is not None) and (e is not None):
                    self.parameters.center = Translation(b)
                    self.parameters.rotation = Rotation.from_properties(
                        numpy.pi * 0.25, e - b, False)
        elif isinstance(last, GLTransformationMixin) and isinstance(
                last.transformation, Translation):
            parent = last.parent
            self.parameters.center = Translation(
                last.get_frame_relative_to(parent).t)
            self.parameters.rotation = Rotation.identity()
        else:
            self.parameters.center = Translation(
                calculate_center(cache.translations))

        if self.parameters_dialog.run(self.parameters) != gtk.RESPONSE_OK:
            self.parameters.clear()
Ejemplo n.º 16
0
def test_pair_ego_precursor_rot():
    geometry = Geometry(*get_precursor_model())
    rot = Rotation.from_properties(-0.5*np.pi, [-1, 1, 0], False)
    sender = Sender()
    scanner = PairScanner(
        send=sender,
        geometry1=geometry,
        geometry2=None,
        action_radius=10.0,
        hit_tolerance=0.1,
        rotation2=rot,
    )
    scanner.run()
Ejemplo n.º 17
0
 def do_rotation(self, rotation_angle, rotation_axis):
     rotation_axis = numpy.dot(self.eye_rotation, rotation_axis)
     if self.rotation_axis is not None:
         if numpy.dot(self.rotation_axis, rotation_axis) > 0:
             rotation_axis = self.rotation_axis
         else:
             rotation_axis = -self.rotation_axis
     rotation = Rotation.from_properties(rotation_angle, rotation_axis,
                                         False)
     self.victim.set_transformation(
         self.rotation_center *
         (rotation *
          (self.rotation_center.inv * self.victim.transformation)))
     context.application.main.drawing_area.queue_draw()
     self.changed = True
Ejemplo n.º 18
0
def test_pair_simple_rot():
    geometry1 = Geometry(*get_simple_model1())
    geometry2 = Geometry(*get_simple_model2())
    rot = Rotation.from_properties(-0.5*np.pi, [0, 1, 0], False)
    sender = Sender()
    scanner = PairScanner(
        send=sender,
        geometry1=geometry1,
        geometry2=geometry2,
        action_radius=10.0,
        hit_tolerance=0.1,
        rotation2=rot,
    )
    scanner.run()
    assert len(sender.connections) == 2
Ejemplo n.º 19
0
    def default_parameters(cls):
        rotation2 = Rotation.from_properties(0.0, [1, 0, 0], False)

        result = Parameters()
        result.connect_description1 = (Expression("True"), Expression("node.get_radius()"))
        result.repulse_description1 = (Expression("True"), Expression("node.get_radius()"))
        result.connect_description2 = (Expression("True"), Expression("node.get_radius()"))
        result.repulse_description2 = (Expression("True"), Expression("node.get_radius()"))
        result.action_radius = 7*angstrom
        result.distance_tolerance = 0.1*angstrom
        result.hit_tolerance = 0.1*angstrom
        result.allow_inversions = True
        result.minimum_triangle_size = 0.1*angstrom
        result.rotation_tolerance = 0.05
        result.rotation2 = Undefined(rotation2)
        return result
Ejemplo n.º 20
0
 def compute_transformations(self):
     Scanner.compute_transformations(self)
     if self.allow_inversions:
         # derive the connections with inversion rotations, based on those
         # without inversion rotations
         new_connections = []
         maximum = len(self.connections)
         for progress, connection in enumerate(self.connections):
             self.send(ProgressMessage("mirror", progress, maximum))
             new = copy.deepcopy(connection)
             mirror = (Translation(connection.triangle1.center) *
                       Rotation.from_properties(
                           numpy.pi, connection.triangle1.normal, True) *
                       Translation(-connection.triangle1.center))
             new.set_transformation(mirror * new.transformation)
             new_connections.append(new)
         self.connections.extend(new_connections)
         self.send(ProgressMessage("mirror", maximum, maximum))
Ejemplo n.º 21
0
 def compute_transformations(self):
     Scanner.compute_transformations(self)
     if self.allow_inversions:
         # derive the connections with inversion rotations, based on those
         # without inversion rotations
         new_connections = []
         maximum = len(self.connections)
         for progress, connection in enumerate(self.connections):
             self.send(ProgressMessage("mirror", progress, maximum))
             new = copy.deepcopy(connection)
             mirror = (
                 Translation(connection.triangle1.center)
                 * Rotation.from_properties(numpy.pi, connection.triangle1.normal, True)
                 * Translation(-connection.triangle1.center)
             )
             new.set_transformation(mirror * new.transformation)
             new_connections.append(new)
         self.connections.extend(new_connections)
         self.send(ProgressMessage("mirror", maximum, maximum))
Ejemplo n.º 22
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
Ejemplo n.º 23
0
    def fn():
        context.application.model.file_open("test/input/precursor.zml")
        context.application.main.select_nodes(
            context.application.model.universe.children)

        ScanForConnections = context.application.plugins.get_action(
            "ScanForConnections")
        rotation2 = Rotation.from_properties(1 * numpy.pi, [0, 1, 0], False)

        parameters = ScanForConnections.default_parameters()
        parameters.connect_description1 = (
            Expression(
                "isinstance(node, Atom) and node.number == 8 and node.num_bonds() == 1"
            ),
            Expression("node.get_radius()"),
        )
        parameters.repulse_description1 = (
            Expression(
                "isinstance(node, Atom) and (node.number == 8 or node.number == 14)"
            ),
            Expression("node.get_radius()*1.5"),
        )
        parameters.action_radius = 4 * angstrom
        parameters.hit_tolerance = 0.1 * angstrom
        parameters.rotation2 = rotation2

        assert ScanForConnections.analyze_selection(parameters)
        ScanForConnections(parameters)

        # Try to save the result to file an open it again.
        context.application.model.file_save("test/output/tmp.zml")
        FileNew = context.application.plugins.get_action("FileNew")
        FileNew()
        context.application.model.file_open("test/output/tmp.zml")

        # Do some consistency tests on the connection scanner results:
        for quality, transformation, pairs, inverse_pairs in context.application.model.folder.children[
                0].get_connections():
            assert_arrays_almost_equal(transformation.r, rotation2.r)
            assert len(pairs) >= 2
            if len(inverse_pairs) > 0:
                assert len(pairs) == len(inverse_pairs)
Ejemplo n.º 24
0
    def default_parameters(cls):
        rotation2 = Rotation.from_properties(0.0, [1, 0, 0], False)

        result = Parameters()
        result.connect_description1 = (Expression("True"),
                                       Expression("node.get_radius()"))
        result.repulse_description1 = (Expression("True"),
                                       Expression("node.get_radius()"))
        result.connect_description2 = (Expression("True"),
                                       Expression("node.get_radius()"))
        result.repulse_description2 = (Expression("True"),
                                       Expression("node.get_radius()"))
        result.action_radius = 7 * angstrom
        result.distance_tolerance = 0.1 * angstrom
        result.hit_tolerance = 0.1 * angstrom
        result.allow_inversions = True
        result.minimum_triangle_size = 0.1 * angstrom
        result.rotation_tolerance = 0.05
        result.rotation2 = Undefined(rotation2)
        return result
Ejemplo n.º 25
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
Ejemplo n.º 26
0
    def do(self):
        cache = context.application.cache

        # Translate where possible, if necessary
        translated_nodes = cache.translated_nodes
        if len(translated_nodes) > 0:
            if isinstance(cache.last, GLTransformationMixin) and \
               isinstance(cache.last.transformation, Translation):
                absolute_inversion_center = cache.last.get_absolute_frame().t
            else:
                absolute_inversion_center = numpy.zeros(3, float)
            victims_by_parent = list_by_parent(cache.transformed_nodes)
            for parent, victims in victims_by_parent.iteritems():
                local_inversion_center = parent.get_absolute_frame(
                ).inv * absolute_inversion_center
                for victim in victims:
                    translation = Translation(
                        2 * (local_inversion_center - victim.transformation.t))
                    primitive.Transform(victim, translation)

        # Apply an inversion rotation where possible
        inversion = Rotation(-numpy.identity(3, float))
        for victim in cache.rotated_nodes:
            primitive.Transform(victim, inversion, after=False)
Ejemplo n.º 27
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])
Ejemplo n.º 28
0
    def do(self):
        cache = context.application.cache

        geometry_nodes = [[], []]

        def get_parameters(node, point_type, geometry_index, filter_expression, radius_expression):
            template = "An exception occured in the %%s expression\nfor the %s points of geometry %i." % (point_type, geometry_index+1)
            try:
                is_type = filter_expression(node)
            except Exception:
                raise UserError(template % "filter")
            if is_type:
                try:
                    radius = radius_expression(node)
                except Exception:
                    raise UserError(template % "radius")
                geometry_nodes[geometry_index].append(node)
                return True, radius
            else:
                return False, None

        def read_geometry(frame, geometry_index, connect_description, repulse_description):
            coordinates = []
            connect_masks = []
            radii = []
            for child in frame.children:
                if isinstance(child, GLTransformationMixin) and \
                   isinstance(child.transformation, Translation):
                    is_connect, radius = get_parameters(
                        child, "connecting", geometry_index,
                        *connect_description
                    )
                    if is_connect:
                        coordinates.append(child.transformation.t)
                        connect_masks.append(True)
                        radii.append(radius)
                    else:
                        is_repulse, radius = get_parameters(
                            child, "repulsive", geometry_index,
                            *repulse_description
                        )
                        if is_repulse:
                            coordinates.append(child.transformation.t)
                            connect_masks.append(False)
                            radii.append(radius)
            return Geometry(
                numpy.array(coordinates, float),
                numpy.array(connect_masks, bool),
                numpy.array(radii, float),
            )

        inp = {}
        inp["geometry1"] = read_geometry(cache.nodes[0], 0, self.parameters.connect_description1, self.parameters.repulse_description1)
        if len(cache.nodes) == 2:
            inp["geometry2"] = read_geometry(cache.nodes[1], 1, self.parameters.connect_description2, self.parameters.repulse_description2)
        else:
            inp["geometry2"] = None
        inp["action_radius"] = self.parameters.action_radius
        inp["hit_tolerance"] = self.parameters.hit_tolerance
        if not isinstance(self.parameters.allow_inversions, Undefined):
            inp["allow_rotations"] = True
            inp["allow_inversions"] = self.parameters.allow_inversions
            inp["minimum_triangle_area"] = self.parameters.minimum_triangle_size**2
        else:
            inp["allow_rotations"] = False
            if isinstance(self.parameters.rotation2, Undefined):
                inp["rotation2"] = Rotation.identity()
            else:
                inp["rotation2"] = self.parameters.rotation2

        if inp["allow_rotations"]:
            connections = self.triangle_report_dialog.run(inp)
        else:
            connections = self.pair_report_dialog.run(inp)

        if connections is not None and len(connections) > 0:
            if len(cache.nodes) == 1:
                frame1 = cache.nodes[0]
                Duplicate = context.application.plugins.get_action("Duplicate")
                Duplicate()
                frame2 = cache.nodes[0]
                geometry_nodes[1] = geometry_nodes[0]
            else:
                frame1, frame2 = cache.nodes

            conscan_results = ConscanResults(
                targets=[frame1, frame2],
                connections=[(
                    float(connection.quality),
                    connection.transformation,
                    [
                        (geometry_nodes[0][first].get_index(), geometry_nodes[1][second].get_index())
                        for first, second in connection.pairs
                    ],
                    [
                        (geometry_nodes[0][second].get_index(), geometry_nodes[1][first].get_index())
                        for first, second in connection.pairs if connection.invertible
                    ],
                ) for connection in connections],
            )
            primitive.Add(conscan_results, context.application.model.folder)
Ejemplo n.º 29
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
Ejemplo n.º 30
0
    def endElement(self, name):
        if name == "zml_file": return
        # now that we have gatherd all information of this tag, create an appropriate object

        # first find the tags involved in this operation
        current_tag = self.hierarchy[-1][-1]
        child_tags = []
        if not current_tag.being_processed:
            current_tag = self.hierarchy[-2][-1]
            child_tags = self.hierarchy[-1]

        # do it
        if name == "str": current_tag.value = str(current_tag.content)
        elif name == "float": current_tag.value = float(current_tag.content)
        elif name == "int": current_tag.value = int(current_tag.content)
        elif name == "bool":
            temp = current_tag.content.lower().strip()
            if temp == 'true': current_tag.value = True
            else: current_tag.value = False
        elif name == "list": current_tag.value = [tag.value for tag in child_tags]
        elif name == "dict": current_tag.value = dict((tag.label, tag.value) for tag in child_tags)
        elif name == "tuple": current_tag.value = tuple(tag.value for tag in child_tags)
        elif name == "shape":
            current_tag.value = tuple(int(item) for item in current_tag.content.split())
        elif name == "cells":
            current_tag.value = numpy.array([eval(item) for item in current_tag.content.split()])
        elif name == "array":
            child_dict = dict((tag.name, tag.value) for tag in child_tags)
            current_tag.value = numpy.reshape(child_dict["cells"], child_dict["shape"])
        elif name == "grid":
            current_tag.value = numpy.reshape(numpy.array([eval(item) for item in current_tag.content.split()]), (int(current_tag.attributes["rows"]), int(current_tag.attributes["cols"]), -1))
        elif name == "binary":
            current_tag.value = StringIO.StringIO()
            current_tag.content.seek(0)
            base64.decode(current_tag.content, current_tag.value)
        elif name == "translation":
            current_tag.value = Translation(child_tags[0].value)
        elif name == "rotation":
            current_tag.value = Rotation(child_tags[0].value)
        elif name == "transformation":
            child_dict = dict((tag.label, tag.value) for tag in child_tags)
            current_tag.value = Complete(
                child_dict["rotation_matrix"],
                child_dict["translation_vector"],
            )
        elif name == "unit_cell":
            child_dict = dict((tag.label, tag.value) for tag in child_tags)
            current_tag.value = UnitCell(
                child_dict["matrix"],
                child_dict["active"],
            )
        elif name == "expression":
            current_tag.value = Expression(current_tag.content)
        elif name == "reference":
            current_tag.value = None
            referent_tag = self.hierarchy[-3][-1]
            target_ids = self.target_ids.get(referent_tag)
            if target_ids is None:
                target_ids = []
                self.target_ids[referent_tag] = target_ids
            target_ids.append(int(current_tag.attributes["to"]))
        elif name == "model_object":
            Class = context.application.plugins.get_node(str(current_tag.attributes["class"]))
            current_tag.state = dict((tag.label, tag.value) for tag in child_tags)
            current_tag.value = Class()
            self.model_object_tags[int(current_tag.attributes["id"])] = current_tag
        else: pass

        # close the door
        current_tag.content = None
        current_tag.close()
        if len(child_tags) > 0: self.hierarchy.pop()
Ejemplo n.º 31
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])
Ejemplo n.º 32
0
    def align_cell(self, lcs=None, swap=True):
        """Align the unit cell with respect to the Cartesian Axes frame

           **Optional Arguments:**

           lcs
                The linear combinations of the unit cell that must get aligned.
                This is a 2x3 array, where each row represents a linear
                combination of cell vectors. The first row is for alignment with
                the x-axis, second for the z-axis. The default value is::

                    np.array([
                        [1, 0, 0],
                        [0, 0, 1],
                    ])

           swap
                By default, the first alignment is done with the z-axis, then
                with the x-axis. The order is reversed when swap is set to
                False.

           The alignment of the first linear combination is always perfect. The
           alignment of the second linear combination is restricted to a plane.
           The cell is always made right-handed. The coordinates are also
           rotated with respect to the origin, but never inverted.

           The attributes of the system are modified in-place. Note that this
           method only works on 3D periodic systems.
        """
        from molmod import Rotation, deg
        # define the target
        target = np.array([
            [1, 0, 0],
            [0, 0, 1],
        ])

        # default value for linear combination
        if lcs is None:
            lcs = target.copy()

        # The starting values
        pos = self.pos
        rvecs = self.cell.rvecs.copy()
        if rvecs.shape != (3,3):
            raise TypeError('The align_cell method only supports 3D periodic systems.')

        # Optionally swap a cell vector if the cell is not right-handed.
        if np.linalg.det(rvecs) < 0:
            # Find a reasonable vector to swap...
            index = rvecs.sum(axis=1).argmin()
            rvecs[index] *= -1

        # Define the source
        source = np.dot(lcs, rvecs)

        # Do the swapping
        if swap:
            target = target[::-1]
            source = source[::-1]

        # auxiliary function
        def get_angle_axis(t, s):
            cos = np.dot(s, t)/np.linalg.norm(s)/np.linalg.norm(t)
            angle = np.arccos(np.clip(cos, -1, 1))
            axis = np.cross(s, t)
            return angle, axis

        # first alignment
        angle, axis = get_angle_axis(target[0], source[0])
        if np.linalg.norm(axis) > 0:
            r1 = Rotation.from_properties(angle, axis, False)
            pos = r1*pos
            rvecs = r1*rvecs
            source = r1*source

        # second alignment
        # Make sure the source is orthogonal to target[0]
        s1p = source[1] - target[0]*np.dot(target[0], source[1])
        angle, axis = get_angle_axis(target[1], s1p)
        r2 = Rotation.from_properties(angle, axis, False)
        pos = r2*pos
        rvecs = r2*rvecs

        # assign
        self.pos = pos
        self.cell = Cell(rvecs)
Ejemplo n.º 33
0
 def do(self):
     cache = context.application.cache
     rotation = Rotation(cache.node.transformation.r)
     CenterAlignBase.do(self, cache.parent, cache.transformed_neighbors,
                        rotation)
Ejemplo n.º 34
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
Ejemplo n.º 35
0
 def convert_to_value(self, representation):
     properties = ComposedInTable.convert_to_value(self, representation)
     return MathRotation.from_properties(*properties)
Ejemplo n.º 36
0
    def do(self):
        cache = context.application.cache

        geometry_nodes = [[], []]

        def get_parameters(node, point_type, geometry_index, filter_expression,
                           radius_expression):
            template = "An exception occured in the %%s expression\nfor the %s points of geometry %i." % (
                point_type, geometry_index + 1)
            try:
                is_type = filter_expression(node)
            except Exception:
                raise UserError(template % "filter")
            if is_type:
                try:
                    radius = radius_expression(node)
                except Exception:
                    raise UserError(template % "radius")
                geometry_nodes[geometry_index].append(node)
                return True, radius
            else:
                return False, None

        def read_geometry(frame, geometry_index, connect_description,
                          repulse_description):
            coordinates = []
            connect_masks = []
            radii = []
            for child in frame.children:
                if isinstance(child, GLTransformationMixin) and \
                   isinstance(child.transformation, Translation):
                    is_connect, radius = get_parameters(
                        child, "connecting", geometry_index,
                        *connect_description)
                    if is_connect:
                        coordinates.append(child.transformation.t)
                        connect_masks.append(True)
                        radii.append(radius)
                    else:
                        is_repulse, radius = get_parameters(
                            child, "repulsive", geometry_index,
                            *repulse_description)
                        if is_repulse:
                            coordinates.append(child.transformation.t)
                            connect_masks.append(False)
                            radii.append(radius)
            return Geometry(
                numpy.array(coordinates, float),
                numpy.array(connect_masks, bool),
                numpy.array(radii, float),
            )

        inp = {}
        inp["geometry1"] = read_geometry(cache.nodes[0], 0,
                                         self.parameters.connect_description1,
                                         self.parameters.repulse_description1)
        if len(cache.nodes) == 2:
            inp["geometry2"] = read_geometry(
                cache.nodes[1], 1, self.parameters.connect_description2,
                self.parameters.repulse_description2)
        else:
            inp["geometry2"] = None
        inp["action_radius"] = self.parameters.action_radius
        inp["hit_tolerance"] = self.parameters.hit_tolerance
        if not isinstance(self.parameters.allow_inversions, Undefined):
            inp["allow_rotations"] = True
            inp["allow_inversions"] = self.parameters.allow_inversions
            inp["minimum_triangle_area"] = self.parameters.minimum_triangle_size**2
        else:
            inp["allow_rotations"] = False
            if isinstance(self.parameters.rotation2, Undefined):
                inp["rotation2"] = Rotation.identity()
            else:
                inp["rotation2"] = self.parameters.rotation2

        if inp["allow_rotations"]:
            connections = self.triangle_report_dialog.run(inp)
        else:
            connections = self.pair_report_dialog.run(inp)

        if connections is not None and len(connections) > 0:
            if len(cache.nodes) == 1:
                frame1 = cache.nodes[0]
                Duplicate = context.application.plugins.get_action("Duplicate")
                Duplicate()
                frame2 = cache.nodes[0]
                geometry_nodes[1] = geometry_nodes[0]
            else:
                frame1, frame2 = cache.nodes

            conscan_results = ConscanResults(
                targets=[frame1, frame2],
                connections=[(
                    float(connection.quality),
                    connection.transformation,
                    [(geometry_nodes[0][first].get_index(),
                      geometry_nodes[1][second].get_index())
                     for first, second in connection.pairs],
                    [(geometry_nodes[0][second].get_index(),
                      geometry_nodes[1][first].get_index())
                     for first, second in connection.pairs
                     if connection.invertible],
                ) for connection in connections],
            )
            primitive.Add(conscan_results, context.application.model.folder)
Ejemplo n.º 37
0
    def align_cell(self, lcs=None, swap=True):
        """Align the unit cell with respect to the Cartesian Axes frame

           **Optional Arguments:**

           lcs
                The linear combinations of the unit cell that must get aligned.
                This is a 2x3 array, where each row represents a linear
                combination of cell vectors. The first row is for alignment with
                the x-axis, second for the z-axis. The default value is::

                    np.array([
                        [1, 0, 0],
                        [0, 0, 1],
                    ])

           swap
                By default, the first alignment is done with the z-axis, then
                with the x-axis. The order is reversed when swap is set to
                False.

           The alignment of the first linear combination is always perfect. The
           alignment of the second linear combination is restricted to a plane.
           The cell is always made right-handed. The coordinates are also
           rotated with respect to the origin, but never inverted.

           The attributes of the system are modified in-place. Note that this
           method only works on 3D periodic systems.
        """
        from molmod import Rotation, deg
        # define the target
        target = np.array([
            [1, 0, 0],
            [0, 0, 1],
        ])

        # default value for linear combination
        if lcs is None:
            lcs = target.copy()

        # The starting values
        pos = self.pos
        rvecs = self.cell.rvecs.copy()
        if rvecs.shape != (3, 3):
            raise TypeError(
                'The align_cell method only supports 3D periodic systems.')

        # Optionally swap a cell vector if the cell is not right-handed.
        if np.linalg.det(rvecs) < 0:
            # Find a reasonable vector to swap...
            index = rvecs.sum(axis=1).argmin()
            rvecs[index] *= -1

        # Define the source
        source = np.dot(lcs, rvecs)

        # Do the swapping
        if swap:
            target = target[::-1]
            source = source[::-1]

        # auxiliary function
        def get_angle_axis(t, s):
            cos = np.dot(s, t) / np.linalg.norm(s) / np.linalg.norm(t)
            angle = np.arccos(np.clip(cos, -1, 1))
            axis = np.cross(s, t)
            return angle, axis

        # first alignment
        angle, axis = get_angle_axis(target[0], source[0])
        if np.linalg.norm(axis) > 0:
            r1 = Rotation.from_properties(angle, axis, False)
            pos = r1 * pos
            rvecs = r1 * rvecs
            source = r1 * source

        # second alignment
        # Make sure the source is orthogonal to target[0]
        s1p = source[1] - target[0] * np.dot(target[0], source[1])
        angle, axis = get_angle_axis(target[1], s1p)
        r2 = Rotation.from_properties(angle, axis, False)
        pos = r2 * pos
        rvecs = r2 * rvecs

        # assign
        self.pos = pos
        self.cell = Cell(rvecs)
Ejemplo n.º 38
0
    def compute_transformation(self, connection):
        # print connection.pairs
        triangle1 = connection.triangle1
        triangle2 = connection.triangle2

        triangles = [triangle1, triangle2]

        # print "BEFORE TRANSFORMING\n"
        # for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate
        # print "---------"

        # *** t1: translation of triangle in geometry2 to origin
        t1 = Translation(-triangle2.center)
        # print triangle2.center
        triangle2.apply_to_coordinates(t1)
        # also move triangle1 to the origin
        t_tmp = Translation(-triangle1.center)  # was t0
        triangle1.apply_to_coordinates(t_tmp)
        # print "AFTER CENTERING (T1 and T0)"
        # for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # *** r2: make the two triangles coplanar
        # print "NORMALS"
        # print triangle1.normal
        # print triangle2.normal
        rotation_axis = numpy.cross(triangle2.normal, triangle1.normal)
        if numpy.dot(rotation_axis, rotation_axis) < 1e-8:
            rotation_axis = random_orthonormal(triangle2.normal)
        rotation_angle = angle(triangle2.normal, triangle1.normal)
        # print "R2 %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis)
        r2 = Rotation.from_properties(rotation_angle, rotation_axis, False)
        triangle2.apply_to_coordinates(r2)
        # print "AFTER R2"
        # for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # bring both triangles in the x-y plane, by a rotation around an axis
        # orthogonal to the Z-axis.
        rotation_axis = numpy.array([triangle1.normal[1], -triangle1.normal[0], 0.0], float)
        if numpy.dot(rotation_axis, rotation_axis) < 1e-8:
            rotation_axis = numpy.array([1.0, 0.0, 0.0], float)
        cos_angle = triangle1.normal[2]
        if cos_angle >= 1.0:
            rotation_angle = 0
        elif cos_angle <= -1.0:
            rotation_angle = numpy.pi
        else:
            rotation_angle = numpy.arccos(cos_angle)
        # print "RT %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis)
        r_flat = Rotation.from_properties(rotation_angle, rotation_axis, False)
        triangle1.apply_to_coordinates(r_flat)
        triangle2.apply_to_coordinates(r_flat)

        # print "AFTER RT"
        # for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # *** r3: second rotation that makes both triangle coinced
        H = lambda a, b, c, d: a * c + b * d + (a + b) * (c + d)
        c = H(
            triangle1.coordinates[0][0],
            triangle1.coordinates[1][0],
            triangle2.coordinates[0][0],
            triangle2.coordinates[1][0],
        ) + H(
            triangle1.coordinates[0][1],
            triangle1.coordinates[1][1],
            triangle2.coordinates[0][1],
            triangle2.coordinates[1][1],
        )
        s = H(
            triangle1.coordinates[0][1],
            triangle1.coordinates[1][1],
            triangle2.coordinates[0][0],
            triangle2.coordinates[1][0],
        ) - H(
            triangle1.coordinates[0][0],
            triangle1.coordinates[1][0],
            triangle2.coordinates[0][1],
            triangle2.coordinates[1][1],
        )
        # if c > s: c, s = -c, -s
        # print "cos=%f sin=%f" % (c, s)
        rotation_angle = numpy.arctan2(s, c)
        # print "R3 %s, %s" % (rotation_angle/numpy.pi*180, triangle1.normal)
        r3 = Rotation.from_properties(rotation_angle, triangle1.normal, False)
        r_tmp = Rotation.from_properties(rotation_angle, numpy.array([0, 0, 1], float), False)
        triangle2.apply_to_coordinates(r_tmp)
        # print "AFTER R3"
        # for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # t4: translate the triangle to the definitive coordinate
        t4 = Translation(triangle1.center)
        # print "AFTER T4"
        # for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        return t4 * r3 * r2 * t1
Ejemplo n.º 39
0
 def default_parameters(cls):
     result = Parameters()
     result.center = Translation.identity()
     result.rotation = Rotation.identity()
     return result
Ejemplo n.º 40
0
 def default_parameters(cls):
     result = Parameters()
     result.center = Translation.identity()
     result.rotation = Rotation.identity()
     return result
Ejemplo n.º 41
0
 def convert_to_value(self, representation):
     properties = ComposedInTable.convert_to_value(self, representation)
     return MathRotation.from_properties(*properties)
Ejemplo n.º 42
0
    def compute_transformation(self, connection):
        #print connection.pairs
        triangle1 = connection.triangle1
        triangle2 = connection.triangle2

        triangles = [triangle1, triangle2]

        #print "BEFORE TRANSFORMING\n"
        #for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate
        #print "---------"

        # *** t1: translation of triangle in geometry2 to origin
        t1 = Translation(-triangle2.center)
        #print triangle2.center
        triangle2.apply_to_coordinates(t1)
        # also move triangle1 to the origin
        t_tmp = Translation(-triangle1.center)  # was t0
        triangle1.apply_to_coordinates(t_tmp)
        #print "AFTER CENTERING (T1 and T0)"
        #for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # *** r2: make the two triangles coplanar
        #print "NORMALS"
        #print triangle1.normal
        #print triangle2.normal
        rotation_axis = numpy.cross(triangle2.normal, triangle1.normal)
        if numpy.dot(rotation_axis, rotation_axis) < 1e-8:
            rotation_axis = random_orthonormal(triangle2.normal)
        rotation_angle = angle(triangle2.normal, triangle1.normal)
        #print "R2 %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis)
        r2 = Rotation.from_properties(rotation_angle, rotation_axis, False)
        triangle2.apply_to_coordinates(r2)
        #print "AFTER R2"
        #for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # bring both triangles in the x-y plane, by a rotation around an axis
        # orthogonal to the Z-axis.
        rotation_axis = numpy.array(
            [triangle1.normal[1], -triangle1.normal[0], 0.0], float)
        if numpy.dot(rotation_axis, rotation_axis) < 1e-8:
            rotation_axis = numpy.array([1.0, 0.0, 0.0], float)
        cos_angle = triangle1.normal[2]
        if cos_angle >= 1.0: rotation_angle = 0
        elif cos_angle <= -1.0: rotation_angle = numpy.pi
        else: rotation_angle = numpy.arccos(cos_angle)
        #print "RT %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis)
        r_flat = Rotation.from_properties(rotation_angle, rotation_axis, False)
        triangle1.apply_to_coordinates(r_flat)
        triangle2.apply_to_coordinates(r_flat)

        #print "AFTER RT"
        #for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # *** r3: second rotation that makes both triangle coinced
        H = lambda a, b, c, d: a * c + b * d + (a + b) * (c + d)
        c = (H(triangle1.coordinates[0][0], triangle1.coordinates[1][0],
               triangle2.coordinates[0][0], triangle2.coordinates[1][0]) +
             H(triangle1.coordinates[0][1], triangle1.coordinates[1][1],
               triangle2.coordinates[0][1], triangle2.coordinates[1][1]))
        s = (H(triangle1.coordinates[0][1], triangle1.coordinates[1][1],
               triangle2.coordinates[0][0], triangle2.coordinates[1][0]) -
             H(triangle1.coordinates[0][0], triangle1.coordinates[1][0],
               triangle2.coordinates[0][1], triangle2.coordinates[1][1]))
        #if c > s: c, s = -c, -s
        #print "cos=%f sin=%f" % (c, s)
        rotation_angle = numpy.arctan2(s, c)
        #print "R3 %s, %s" % (rotation_angle/numpy.pi*180, triangle1.normal)
        r3 = Rotation.from_properties(rotation_angle, triangle1.normal, False)
        r_tmp = Rotation.from_properties(rotation_angle,
                                         numpy.array([0, 0, 1], float), False)
        triangle2.apply_to_coordinates(r_tmp)
        #print "AFTER R3"
        #for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        # t4: translate the triangle to the definitive coordinate
        t4 = Translation(triangle1.center)
        #print "AFTER T4"
        #for triangle in triangles:
        #    #print "-------"
        #    for coordinate in triangle.coordinates:
        #        #print coordinate

        return t4 * r3 * r2 * t1