예제 #1
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()
예제 #2
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
예제 #3
0
 def calc_vector_dimensions(self):
     relative_translation = self.shortest_vector_relative_to(self.parent)
     if relative_translation is None:
         self.length = 0
     else:
         self.length = numpy.sqrt(
             numpy.dot(relative_translation, relative_translation))
         if self.length > 0:
             t = self.children[0].translation_relative_to(self.parent)
             c = relative_translation[2] / self.length
             if c >= 1.0:
                 self.orientation = Translation(t)
             elif c <= -1.0:
                 alpha = numpy.pi
                 axis = numpy.array([1.0, 0.0, 0.0])
                 self.orientation = Complete.from_properties(
                     alpha, axis, False, t)
             else:
                 x, y = relative_translation[0], relative_translation[1]
                 if abs(x) < abs(y):
                     signy = {True: 1, False: -1}[y >= 0]
                     a = -signy
                     b = signy * x / y
                 else:
                     signx = {True: 1, False: -1}[x >= 0]
                     a = -signx * y / x
                     b = signx
                 alpha = numpy.arccos(c)
                 axis = numpy.array([a, b, 0.0])
                 self.orientation = Complete.from_properties(
                     alpha, axis, False, t)
예제 #4
0
    def do(self):
        cache = context.application.cache

        graph = create_molecular_graph(cache.nodes)
        parent = cache.node

        Frame = context.application.plugins.get_node("Frame")
        for group in graph.independent_vertices:
            atoms = [graph.molecule.atoms[i] for i in group]
            new_positions = self.calc_new_positions(group, atoms, graph,
                                                    parent)
            if new_positions is None:
                # this happens for groups of atoms that are inherently periodic.
                continue
            frame = Frame(name=chemical_formula(atoms)[1])
            primitive.Add(frame, parent, index=0)
            for node, atom in zip(group, atoms):
                primitive.Move(atom, frame)
                new_position = new_positions[node]
                translation = Translation(
                    atom.get_parentframe_up_to(parent).inv * new_position)
                primitive.SetProperty(atom, "transformation", translation)
            for atom in atoms:
                # take a copy of the references since they are going to be
                # refreshed (changed and reverted) during the loop.
                for reference in list(atom.references):
                    referent = reference.parent
                    if referent.parent != frame:
                        has_to_move = True
                        for child in referent.children:
                            if child.target.parent != frame:
                                has_to_move = False
                                break
                        if has_to_move:
                            primitive.Move(referent, frame)
예제 #5
0
파일: glmixin.py 프로젝트: mszep/zeobuilder
 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()
예제 #6
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.translation = Translation([2.0, 4.1, -1.0])
     TranslateDialog = context.application.plugins.get_action("TranslateDialog")
     assert TranslateDialog.analyze_selection(parameters)
     TranslateDialog(parameters)
예제 #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())
예제 #8
0
파일: camera.py 프로젝트: molmod/zeobuilder
 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
예제 #9
0
 def do_translation(self, vector, drawing_area):
     camera = context.application.camera
     tmp = vector.copy()
     tmp[2] = 0
     transformed_vector = numpy.dot(self.eye_rotation, tmp)
     new_eye_t = camera.eye.t.copy()
     new_eye_t[:2] -= vector[:2]
     camera.rotation_center = Translation(camera.rotation_center.t +
                                          transformed_vector)
     if (camera.opening_angle > 0):
         new_eye_t[2] -= vector[2]
     else:
         window_size = camera.window_size * (1 + 0.01 * vector[-1])
         if window_size < 0.001: window_size = 0.001
         elif window_size > 1000: window_size = 1000
         camera.window_size = window_size
     camera.eye = Translation(new_eye_t)
     drawing_area.queue_draw()
예제 #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.center = Translation([2.0, 4.1, -1.0])
     parameters.rotation = Rotation.from_properties(1.0, numpy.array([0.1, 1.4, 0.3]), False)
     RotateAboutAxisDialog = context.application.plugins.get_action("RotateAboutAxisDialog")
     assert RotateAboutAxisDialog.analyze_selection(parameters)
     RotateAboutAxisDialog(parameters)
예제 #11
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))
예제 #12
0
    def do(self):
        cache = context.application.cache
        parent = cache.node

        unit_cell = None
        if isinstance(parent, UnitCell):
            unit_cell = parent

        Atom = context.application.plugins.get_node("Atom")
        atoms = []
        coordinates = []
        for child in parent.children:
            if isinstance(child, Atom):
                atoms.append(child)
                coordinates.append(child.transformation.t)
        coordinates = numpy.array(coordinates)

        cf = ClusterFactory()
        for i0, i1, delta, distance in PairSearchIntra(
                coordinates, periodic.max_radius * 0.4, unit_cell):
            atom0 = atoms[i0]
            atom1 = atoms[i1]
            if atom0.number == atom1.number:
                if distance < periodic[atom0.number].vdw_radius * 0.4:
                    cf.add_related(atom0, atom1)
        clusters = cf.get_clusters()
        del cf

        # define the new singles
        singles = []
        for cluster in clusters:
            number = iter(cluster.items).next().number
            single = Atom(name="Single " + periodic[number].symbol)
            single.set_number(number)
            singles.append((single, list(cluster.items)))

        # calculate their positions
        for single, overlappers in singles:
            # in the following algorithm, we suppose that the cluster of
            # atoms is small compared to the parent's periodic sizes
            # (if the parent is a periodic system)
            first_pos = overlappers[0].transformation.t
            delta_to_mean = numpy.zeros(3, float)
            for atom in overlappers[1:]:
                delta_to_mean += parent.shortest_vector(atom.transformation.t -
                                                        first_pos)
            delta_to_mean /= float(len(overlappers))
            single.set_transformation(Translation(first_pos + delta_to_mean))

        # modify the model
        for single, overlappers in singles:
            lowest_index = min([atom.get_index() for atom in overlappers])
            primitive.Add(single, parent, index=lowest_index)
            for atom in overlappers:
                while len(atom.references) > 0:
                    primitive.SetTarget(atom.references[0], single)
                primitive.Delete(atom)
예제 #13
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
예제 #14
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()
예제 #15
0
 def ask_parameters(self):
     cache = context.application.cache
     last = cache.last
     parent = cache.parent_of_translated_nodes
     if isinstance(last, Vector):
         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.translation = Translation(e - b)
     else:
         self.parameters = self.last_parameters()
     if self.parameters_dialog.run(self.parameters) != gtk.RESPONSE_OK:
         self.parameters.clear()
예제 #16
0
    def fn():
        FileNew = context.application.plugins.get_action("FileNew")
        FileNew()

        for index in xrange(4):
            context.application.main.select_nodes([context.application.model.universe])
            Point = context.application.plugins.get_node("Point")
            point = Point(transformation=Translation(numpy.random.uniform(-5, 5, 3)))
            context.application.model.universe.add(point)

        context.application.main.select_nodes(context.application.model.universe.children)
        AddTetraeder = context.application.plugins.get_action("AddTetraeder")
        assert AddTetraeder.analyze_selection()
        AddTetraeder()
예제 #17
0
    def __call__(self, f):
        Universe = context.application.plugins.get_node("Universe")
        universe = Universe()
        Folder = context.application.plugins.get_node("Folder")
        folder = Folder()

        Atom = context.application.plugins.get_node("Atom")
        counter = 1
        atom_index = 0
        for line in f:
            #if len(line) != 81:
            #    raise FilterError("Each line in a PDB file must count 80 characters, error at line %i, len=%i" % (counter, len(line)-1))
            if line.startswith("ATOM"):
                extra = {"index": atom_index}
                atom_info = periodic[line[76:78].strip()]
                try:
                    t = numpy.array([
                        float(line[30:38].strip()),
                        float(line[38:46].strip()),
                        float(line[46:54].strip())
                    ]) * angstrom
                except ValueError:
                    raise FilterError(
                        "Error while reading PDB file: could not read coordinates at line %i."
                        % counter)
                atom = Atom(name=line[12:16].strip(),
                            number=atom_info.number,
                            transformation=Translation(t),
                            extra=extra)
                universe.add(atom)
                atom_index += 1
            elif line.startswith("CRYST1"):
                space_group = line[55:66].strip().upper()
                if space_group != "P 1":
                    raise FilterError(
                        "Error while reading PDB file: only unit cells with space group P 1 are supported."
                    )
                a = float(line[6:15].strip()) * angstrom
                b = float(line[15:24].strip()) * angstrom
                c = float(line[24:33].strip()) * angstrom
                alpha = float(line[33:40].strip()) * numpy.pi / 180
                beta = float(line[40:47].strip()) * numpy.pi / 180
                gamma = float(line[47:54].strip()) * numpy.pi / 180
                universe.set_cell(
                    UnitCell.from_parameters3([a, b, c], [alpha, beta, gamma]))
            counter += 1

        return [universe, folder]
예제 #18
0
    def fn():
        FileNew = context.application.plugins.get_action("FileNew")
        FileNew()
        import zeobuilder.actions.primitive
        from molmod import Translation

        for index in xrange(3):
            context.application.main.select_nodes([context.application.model.universe])
            Point = context.application.plugins.get_node("Point")
            point = Point(transformation=Translation(numpy.random.uniform(-1, 1, 3)))
            context.application.model.universe.add(point)

        context.application.main.select_nodes(context.application.model.universe.children)
        AddPlane = context.application.plugins.get_action("AddPlane")
        assert AddPlane.analyze_selection()
        AddPlane()
예제 #19
0
 def do(self):
     cache = context.application.cache
     for node in cache.nodes:
         child_translations = []
         translated_children = []
         for child in node.children:
             if isinstance(child, GLTransformationMixin) and isinstance(
                     child.transformation, Translation):
                 if child.get_fixed():
                     translated_children = []
                     break
                 translated_children.append(child)
                 child_translations.append(child.transformation)
         if len(translated_children) > 0:
             translation = Translation(calculate_center(child_translations))
             CenterAlignBase.do(self, node, translated_children,
                                translation)
예제 #20
0
 def fn():
     FileNew = context.application.plugins.get_action("FileNew")
     FileNew()
     Atom = context.application.plugins.get_node("Atom")
     Frame = context.application.plugins.get_node("Frame")
     frame = Frame()
     context.application.model.universe.add(frame)
     atom1 = Atom()
     atom2 = Atom(transformation=Translation([1.1, 0.1, 0.03]))
     frame.add(atom1)
     frame.add(atom2)
     CenterOfMassAndPrincipalAxes = context.application.plugins.get_action(
         "CenterOfMassAndPrincipalAxes")
     context.application.main.select_nodes(
         [context.application.model.universe.children[0]])
     assert CenterOfMassAndPrincipalAxes.analyze_selection()
     CenterOfMassAndPrincipalAxes()
예제 #21
0
    def do(self):
        cache = context.application.cache
        parent = cache.common_parent
        while not parent.check_add(Point):
            parent = parent.parent

        vector_sum = numpy.zeros(3, float)
        num_vectors = 0

        for node in cache.nodes:
            if isinstance(node, GLTransformationMixin) and \
               isinstance(node.transformation, Translation):
                vector_sum += node.get_frame_relative_to(parent).t
                num_vectors += 1

        point = Point(name="Average",
                      transformation=Translation(vector_sum / num_vectors))
        primitive.Add(point, parent)
예제 #22
0
    def do(self):
        cache = context.application.cache
        for node in cache.nodes:
            translated_children = []
            for child in node.children:
                if isinstance(child, GLTransformationMixin) and isinstance(
                        child.transformation, Translation):
                    if child.get_fixed():
                        translated_children = []
                        break
                    translated_children.append(child)
            if len(translated_children) == 0:
                continue

            mass, com = compute_center_of_mass(iter_particles(node))
            if mass == 0.0:
                continue

            CenterAlignBase.do(self, node, translated_children,
                               Translation(com))
예제 #23
0
    def __call__(self, f):
        try:
            xyz_reader = XYZReader(f)
            molecule = xyz_reader.get_first_molecule()
        except IOError:
            raise FilterError(
                "Could not read the first frame from the XYZ file. Incorrect file format."
            )

        Universe = context.application.plugins.get_node("Universe")
        universe = Universe()
        Folder = context.application.plugins.get_node("Folder")
        folder = Folder()

        title = molecule.title.strip()
        if len(title) > 0:
            universe.name = title

        Atom = context.application.plugins.get_node("Atom")
        Point = context.application.plugins.get_node("Point")

        for index, number, symbol, coordinate in zip(xrange(molecule.size),
                                                     molecule.numbers,
                                                     xyz_reader.symbols,
                                                     molecule.coordinates):
            extra = {"index": index}
            transl = Translation(coordinate)
            if number == 0:
                atom = Point(name=symbol, extra=extra, transformation=transl)
            else:
                atom = Atom(name=symbol,
                            number=number,
                            extra=extra,
                            transformation=transl)
            universe.add(atom)

        geometries = []
        for title, coordinates in xyz_reader:
            geometries.append(coordinates)

        return [universe, folder]
예제 #24
0
 def load_molecule(self, parent, molecule):
     parent.extra.update(self.load_extra(molecule.extra))
     Atom = context.application.plugins.get_node("Atom")
     for counter, number, coordinate in zip(xrange(molecule.size), molecule.numbers, molecule.coordinates):
         extra = self.load_extra(molecule.atoms_extra.get(counter, {}))
         extra["index"] = counter
         atom_record = periodic[number]
         atom = Atom(
             name=atom_record.symbol, number=number, extra=extra,
             transformation=Translation(coordinate)
         )
         parent.add(atom)
         counter += 1
     if molecule.graph is not None:
         Bond = context.application.plugins.get_node("Bond")
         for counter, edge in enumerate(molecule.graph.edges):
             extra = self.load_extra(molecule.bonds_extra.get(edge, {}))
             name = "Bond %i" % counter
             i, j = edge
             bond = Bond(name=name, targets=[parent.children[i],parent.children[j]], extra=extra)
             parent.add(bond)
예제 #25
0
    def do(self):
        Atom = context.application.plugins.get_node("Atom")

        cache = context.application.cache
        for spring in list(cache.nodes):
            atom1, atom2 = spring.get_targets()
            if isinstance(atom1, Atom) and isinstance(atom2, Atom):
                t = 0.5 * (atom1.get_frame_relative_to(spring.parent).t +
                           atom2.get_frame_relative_to(spring.parent).t)
                replacement = Atom(name="Merge of %s and %s" %
                                   (atom1.name, atom2.name),
                                   number=max([atom1.number, atom2.number]),
                                   transformation=Translation(t))
                primitive.Add(replacement, spring.parent, spring.get_index())
                atoms = set([atom1, atom2])
                for atom in atoms:
                    while len(atom.references) > 0:
                        primitive.SetTarget(atom.references[0], replacement)
                primitive.Delete(spring)
                for atom in atoms:
                    primitive.Delete(atom)
예제 #26
0
    def interactive_init(self):
        InteractiveWithMemory.interactive_init(self)
        cache = context.application.cache
        if len(cache.nodes) == 1:
            self.victim = cache.node
            helper = None
        else:
            self.victim = cache.next_to_last
            helper = cache.last
        self.rotation_axis = None
        self.changed = False
        rotation_center_object = None
        if helper is not None:
            # take the information out of the helper nodes
            if isinstance(helper, Vector):
                b = helper.children[0].translation_relative_to(
                    self.victim.parent)
                e = helper.children[1].translation_relative_to(
                    self.victim.parent)
                if not ((b is None) or (e is None)):
                    rotation_center_object = helper.children[0].target
                    self.rotation_axis = e - b
                    norm = numpy.dot(self.rotation_axis, self.rotation_axis)
                    if norm > 0.0:
                        self.rotation_axis /= norm
                    else:
                        self.rotation_axis = None
            else:
                rotation_center_object = helper
        else:
            rotation_center_object = self.victim

        self.rotation_center = Translation(
            rotation_center_object.get_frame_relative_to(self.victim.parent).t)
        drawing_area = context.application.main.drawing_area
        camera = context.application.camera
        self.screen_rotation_center = drawing_area.camera_to_screen(
            camera.object_to_camera(rotation_center_object))
        self.eye_rotation = camera.object_eye_rotation(self.victim)
        self.old_transformation = self.victim.transformation
예제 #27
0
    def get_new(self, position):
        if self.current_object == "Fragment":
            filename = context.get_share_filename('fragments/%s.cml' %
                                                  self.current_fragment)
            molecule = load_cml(filename)[0]

            Frame = context.application.plugins.get_node("Frame")
            new = Frame(name=self.current_fragment)

            load_filter = context.application.plugins.get_load_filter('cml')
            load_filter.load_molecule(new, molecule)
        else:
            NewClass = context.application.plugins.get_node(
                self.current_object)
            new = NewClass()
            if self.current_object == "Atom":
                new.set_number(self.atom_number)
                new.set_name(periodic[self.atom_number].symbol)

        translation = Translation(position)
        primitive.Transform(new, translation)
        return new
예제 #28
0
def coords_to_zeobuilder(org_coords, opt_coords, atoms, parent, graph=None):
    if graph == None:
        groups = [numpy.arange(len(atoms))]
    else:
        # if the molecular graph has disconnected islands, then each independent
        # part is treated seperately in the loop below
        groups = graph.independent_vertices

    for group in groups:
        group_org = org_coords[group]
        group_opt = opt_coords[group]
        # Transform the guessed geometry as to overlap with the original geometry
        transf = superpose(group_org, group_opt)
        group_opt = transf * group_opt

        # Put coordinates of guessed geometry back into Zeobuilder model
        for i, atomindex in enumerate(group):
            atom = atoms[atomindex]
            # Make sure atoms in subframes are treated properly
            transf = atom.parent.get_frame_relative_to(parent)
            org_pos = atom.transformation.t
            opt_pos = transf.inv * group_opt[i]

            primitive.Transform(atom, Translation(opt_pos - org_pos))
예제 #29
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)
예제 #30
0
파일: scene.py 프로젝트: molmod/zeobuilder
 def get_model_center(self):
     universe = context.application.model.universe
     if universe is None:
         return Translation.identity()
     else:
         return universe.model_center
예제 #31
0
 def initnonstate(self):
     GLPeriodicContainer.initnonstate(self)
     self.model_center = Translation.identity()
예제 #32
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
예제 #33
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])
예제 #34
0
 def default_parameters(cls):
     result = Parameters()
     result.center = Translation.identity()
     result.rotation = Rotation.identity()
     return result
예제 #35
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
예제 #36
0
 def default_parameters(cls):
     result = Parameters()
     result.translation = Translation.identity()
     return result