Пример #1
0
    def do(self):
        Atom = context.application.plugins.get_node("Atom")

        def iter_all_tetra(nodes):
            for node in nodes:
                if isinstance(node, Atom) and node.number > 12:
                    yield node
                elif isinstance(node, ContainerMixin):
                    for tetra in iter_all_tetra(node.children):
                        yield tetra

        coordinated_tetra = [[] for i in xrange(5)]
        for tetra in iter_all_tetra(
                context.application.cache.nodes_without_children):
            coordination = 0
            for bridging in tetra.iter_neighbors():
                if bridging.number > 6:
                    num_t = len([
                        t for t in bridging.iter_neighbors() if t.number > 12
                    ])
                    if num_t > 2:
                        raise UserError("Invalid zeolite structure.")
                    if num_t == 2:
                        coordination += 1
            if coordination > 4:
                raise UserError("Invalid zeolite structure.")
            coordinated_tetra[coordination].append(tetra)

        result_dialog = CoordinationDialog(coordinated_tetra)
        response = result_dialog.run()

        if response != gtk.RESPONSE_CLOSE:
            main = context.application.main
            main.select_nodes(coordinated_tetra[response])
Пример #2
0
    def do(self):
        for key, val in self.parameters.__dict__.iteritems():
            if isinstance(val, Expression):
                val.compile_as("<%s>" % key)
                val.variables = (key[7:11], )

        parent = context.application.cache.common_parent
        if parent is None:
            parent = context.application.model.universe
        angles = []
        graph = create_molecular_graph(context.application.cache.nodes)

        match_definition = BendingAnglePattern(criteria_sets=[
            CriteriaSet(
                thing_criteria={
                    0: IndexToAtoms(self.parameters.filter_atom1),
                    1: IndexToAtoms(self.parameters.filter_atom2),
                    2: IndexToAtoms(self.parameters.filter_atom3),
                },
                relation_criteria={
                    0: IndexToBonds(self.parameters.filter_bond12),
                    1: IndexToBonds(self.parameters.filter_bond23),
                },
            )
        ], )
        try:
            atoms = graph.molecule.atoms
            match_generator = GraphSearch(match_definition)
            for match in match_generator(graph):
                point1 = atoms[match.forward[0]].get_absolute_frame().t
                point2 = atoms[match.forward[1]].get_absolute_frame().t
                point3 = atoms[match.forward[2]].get_absolute_frame().t
                delta1 = parent.shortest_vector(point2 - point1)
                delta2 = parent.shortest_vector(point2 - point3)
                if numpy.linalg.norm(delta1) > 1e-8 and \
                    numpy.linalg.norm(delta2) > 1e-8:
                    angles.append(angle(delta1, delta2))
        except:
            raise UserError(
                "An error occured while sampling the bending angles.",
                "If this is an error in one of the filter expressions,\n" +
                "one should see the expression mentioned below as <filter_...>.\n\n"
            )

        comments = [
            "atom 1 filter expression: %s" % self.parameters.filter_atom1.code,
            "bond 1-2 filter expression: %s" %
            self.parameters.filter_bond12.code,
            "atom 2 filter expression: %s" % self.parameters.filter_atom2.code,
            "bond 2-3 filter expression: %s" %
            self.parameters.filter_bond23.code,
            "atom 3 filter expression: %s" % self.parameters.filter_atom3.code,
        ]

        if len(angles) > 0:
            distribution_dialog = DistributionDialog()
            distribution_dialog.run(numpy.array(angles), "Angle",
                                    "Bending angle", comments)
        else:
            raise UserError("No bending angles match the given criteria.")
Пример #3
0
    def read_mopac_output(self, filename, num_atoms):
        if not os.path.isfile(filename):
            raise UserError("Could not find Mopac output file.",
                            "Expected location of output file: %s" % filename)
        f = open(filename, 'r')
        coordinates = numpy.zeros((num_atoms, 3), float)
        success = False
        for line in f:
            if line == "          CARTESIAN COORDINATES \n":
                break
        for line in f:
            if line == "          CARTESIAN COORDINATES \n":
                success = True
                break
        if success:
            for i in xrange(3):
                f.next()
            i = 0
            for line in f:
                if i < num_atoms:
                    words = line.split()
                    coordinates[i, 0] = float(words[2])
                    coordinates[i, 1] = float(words[3])
                    coordinates[i, 2] = float(words[4])
                    i += 1
                else:
                    break
        else:
            raise UserError("Could not find optimal coordinates.",
                            "Check the file %s for more details." % filename)

        f.close()
        return coordinates * angstrom
Пример #4
0
        def define_big_periodic():
            "Based on (n,m) calculate the size of the periodic sheet (that will be folded into a tube)."
            big_a = n * flat_a - m * flat_b
            norm_a = numpy.linalg.norm(big_a)
            radius = norm_a / (2 * numpy.pi)
            big_x = big_a / norm_a
            big_y = numpy.array([-big_x[1], big_x[0]], float)

            big_b = None
            stack_vector = flat_b - flat_a * numpy.dot(
                big_x, flat_b) / numpy.dot(big_x, flat_a)
            stack_length = numpy.linalg.norm(stack_vector)
            nominator = numpy.linalg.norm(stack_vector - flat_b)
            denominator = numpy.linalg.norm(flat_a)
            fraction = nominator / denominator
            stack_size = 1
            while True:
                repeat = fraction * stack_size
                if stack_length * stack_size > self.parameters.max_length:
                    break
                if abs(repeat - round(repeat)
                       ) * denominator < self.parameters.max_error:
                    big_b = stack_vector * stack_size
                    break
                stack_size += 1
            if big_b is None:
                raise UserError(
                    "Could not create a periodic tube shorter than the given maximum length."
                )
            rotation = numpy.array([big_x, big_y], float)
            return big_a, big_b, rotation, stack_vector, stack_size, radius
Пример #5
0
    def do(self):
        cache = context.application.cache
        parents = cache.nodes
        containers = cache.containers_with_children

        main = context.application.main

        def toggle_children(parent):
            for node in parent.children:
                match = self.parameters.expression(node)
                if match:
                    main.toggle_selection(node, on=True)
                if ((self.parameters.recursive == self.SELECT_RECURSIVE_IF_MATCH) and match) or (self.parameters.recursive == self.SELECT_RECURSIVE):
                    if isinstance(node, ParentMixin):
                        toggle_children(node)


        for parent in parents:
            main.toggle_selection(parent, on=False)
        try:
            for container in containers:
                toggle_children(container)
        except Exception:
            main.tree_selection.unselect_all()
            for parent in parents:
                main.toggle_selection(parent, on=True)
            raise UserError("An exception occured while evaluating the filter expression.")
Пример #6
0
 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
Пример #7
0
 def do(self):
     frame_ref = context.application.cache.nodes[0]
     graph_ref = create_molecular_graph([frame_ref])
     try:
         match_generator = GraphSearch(EqualPattern(graph_ref))
     except GraphError, e:
         raise UserError(
             "Could not setup a graph match definition to clone the order.")
Пример #8
0
 def do(self):
     vectors = context.application.cache.nodes
     universe = context.application.model.root[0]
     new_cell = universe.cell
     try:
         for vector in vectors:
             new_cell = new_cell.add_cell_vector(
                 vector.shortest_vector_relative_to(universe))
     except ValueError:
         if len(vectors) == 1:
             raise UserError(
                 "Failed to add the selected vector as cell vector since it would make the unit cell singular."
             )
         else:
             raise UserError(
                 "Failed to add the selected vectors as cell vectors since they would make the unit cell singular."
             )
     primitive.SetProperty(universe, "cell", new_cell)
Пример #9
0
    def do(self):
        parent = context.application.cache.node
        org_mol = create_molecule([parent], parent)
        org_coords = org_mol.coordinates

        if org_mol.size == 0:
            raise UserError(
                "Could not get molecule.",
                "Make sure that the selected frame contains a molecule.")
        if org_mol.size == 3:
            raise UserError("For the moment three atoms are not supported.")

        # Make temp directory
        work = tempfile.mkdtemp("_zeobuilder_mopac")

        # Create mopac input file
        self.write_mopac_input(org_mol, os.path.join(work, 'mopac'))

        # Run input file through mopac and capture output in file object
        retcode = os.system('cd %s; run_mopac7 mopac > mopac.stdout' % work)
        if retcode != 0:
            raise UserError(
                "Failed to run Mopac.",
                "Check that the run_mopac7 binary is in the path. The input file can be found here: %s."
                % work)
        opt_coords = self.read_mopac_output(os.path.join(work, 'mopac.OUT'),
                                            org_mol.size)

        # clean up
        def safe_remove(filename):
            filename = os.path.join(work, filename)
            if os.path.isfile(filename):
                os.remove(filename)

        safe_remove("mopac.dat")
        safe_remove("mopac.log")
        safe_remove("mopac.stdout")
        safe_remove("mopac.OUT")
        safe_remove("mopac.arc")
        os.rmdir(work)

        coords_to_zeobuilder(org_coords, opt_coords, org_mol.atoms, parent)
Пример #10
0
 def iter_hits(self, selection_box):
     if not self.get_gl_drawable().gl_begin(self.get_gl_context()): return
     vb = context.application.vis_backend
     try:
         for selection in vb.draw(self.allocation.width, self.allocation.height, selection_box):
             yield vb.names.get(selection[2][-1])
     except GLerror, e:
         self.get_gl_drawable().gl_end()
         if e.errno[0] == 1283:
             raise UserError("Too many objects in selection. Increase selection buffer size.")
         else:
             raise
Пример #11
0
class CloneOrder(Immediate):
    description = "Apply the order of the first selection to all the other."
    menu_info = MenuInfo("default/_Object:tools/_Molecular:rearrange",
                         "_Clone order",
                         order=(0, 4, 1, 5, 0, 3))
    authors = [authors.toon_verstraelen]

    @staticmethod
    def analyze_selection():
        if not Immediate.analyze_selection(): return False
        cache = context.application.cache
        if len(cache.nodes) < 2: return False
        Frame = context.application.plugins.get_node("Frame")
        for cls in cache.classes:
            if not issubclass(cls, Frame): return False
        return True

    def do(self):
        frame_ref = context.application.cache.nodes[0]
        graph_ref = create_molecular_graph([frame_ref])
        try:
            match_generator = GraphSearch(EqualPattern(graph_ref))
        except GraphError, e:
            raise UserError(
                "Could not setup a graph match definition to clone the order.")

        some_failed = False
        all_failed = True
        for frame_other in context.application.cache.nodes[1:]:
            graph_other = create_molecular_graph([frame_other])

            try:
                match = match_generator(graph_other).next()
                all_failed = False
            except (StopIteration, GraphError):
                some_failed = True
                continue

            moves = [(index1, graph_other.molecule.atoms[index2])
                     for index1, index2 in match.forward.iteritems()]
            moves.sort()

            for new_index, atom2 in moves:
                primitive.Move(atom2, frame_other, new_index)
        if all_failed:
            raise UserError("None of the atom orders could be cloned.")
        elif some_failed:
            ok_error(
                "Some molecules/frames did not match the first frame, so they are not reordered."
            )
Пример #12
0
 def erase_at(self, p, parent):
     for node in context.application.main.drawing_area.iter_hits(
         (p[0] - 2, p[1] - 2, p[0] + 2, p[1] + 2)):
         try:
             match = (node is not None and node != parent
                      and node.is_indirect_child_of(parent)
                      and node.model == context.application.model
                      and (not self.cb_erase_filter.get_active()
                           or self.erase_filter(node)))
         except Exception:
             raise UserError(
                 "An exception occured while evaluating the erase filter expression."
             )
         if match:
             primitive.Delete(node)
Пример #13
0
    def do(self):
        # Get the molecular graph of the molecule in the selection
        parent = context.application.cache.node
        graph = create_molecular_graph([parent], parent)
        if graph.molecule.size == 0:
            raise UserError(
                "Could not get molecular graph.",
                "Make sure that the selected frame contains a molecule.")

        # Guessed and original geometry
        opt_coords = tune_geometry(graph, graph.molecule).coordinates
        org_coords = graph.molecule.coordinates

        coords_to_zeobuilder(org_coords, opt_coords, graph.molecule.atoms,
                             parent, graph)
Пример #14
0
    def do(self):
        cache = context.application.cache
        parent = cache.parent
        involved_frames = cache.spring_problem.frames
        springs = cache.spring_problem.springs
        max_step = []

        old_transformations = [(frame, frame.transformation)
                               for frame in involved_frames
                               if frame is not None]

        variable_indices = dict((frame, index) for index, frame in enumerate(
            frame for frame in involved_frames if frame is not None))

        cost_function = iterative.expr.Root(1, 10, True)
        for frame in involved_frames:
            if frame is None:
                pass
            elif self.parameters.allow_rotation and isinstance(
                    frame.transformation, Complete):
                variable = iterative.var.Frame(
                    frame.transformation.r,
                    frame.transformation.t,
                )
                cost_function.register_state_variable(variable)
                constraint = iterative.expr.Orthonormality(1e-10)
                constraint.register_input_variable(variable)
                max_step.extend([
                    0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 1.0, 1.0, 1.0
                ])
            elif isinstance(frame.transformation, Translation):
                variable = iterative.var.Translation(
                    frame.transformation.r,
                    frame.transformation.t,
                )
                cost_function.register_state_variable(variable)
                max_step.extend([1.0, 1.0, 1.0])
            else:
                raise UserError(
                    "The involved frames shoud be at least capable of being translated."
                )

        for spring, frames in springs.iteritems():
            spring_term = iterative.expr.Spring(spring.rest_length)
            for target, frame in frames.iteritems():
                if frame is None:
                    spring_term.register_input_variable(
                        iterative.expressions.NoFrame(),
                        target.get_frame_up_to(parent).t)
                else:
                    spring_term.register_input_variable(
                        cost_function.state_variables[variable_indices[frame]],
                        target.get_frame_up_to(frame).t)

        max_step = numpy.array(max_step, float)
        minimize = iterative.alg.DefaultMinimize(
            cost_function,
            max_step,
            max_step * 1e-8,
        )

        result = self.report_dialog.run(
            minimize,
            involved_frames,
            self.parameters.update_interval,
            self.parameters.update_steps,
            len(springs),
        )
        if result != gtk.RESPONSE_OK:
            for frame, transformation in old_transformations:
                frame.transformation = transformation
                frame.invalidate_transformation_list()
            raise CancelException

        for frame, transformation in old_transformations:
            primitive.SetProperty(
                frame,
                "transformation",
                transformation,
                done=True,
            )
Пример #15
0
    def do(self):
        class Record(object):
            def __init__(self, name, quaternion):
                self.name = name
                self.quaternion = quaternion
                self.cost_function = 0.0

        rounded_quaternions = []

        cache = context.application.cache
        if len(cache.nodes) == 1:
            victim = cache.last
            master = None
            factor, selected_quaternion = rotation_matrix_to_quaternion(
                victim.transformation.r)
        elif len(cache.nodes) == 2:
            master = cache.last
            victim = cache.next_to_last
            factor, selected_quaternion = rotation_matrix_to_quaternion(
                victim.get_frame_relative_to(master).r)

        step = 15
        for axis_name, axis in self.axes.iteritems():
            for angle_index in xrange(1, 360 / step):
                angle = angle_index * step
                name = "%s (%s)" % (axis_name, angle)
                rad = angle * numpy.pi / 360
                quaternion = numpy.concatenate(
                    ([numpy.cos(rad)], numpy.sin(rad) * axis), 1)
                rounded_quaternions.append(Record(name, quaternion))

        new_quaternions = [
            Record("Identity", numpy.array([1.0, 0.0, 0.0, 0.0]))
        ]
        for record1 in rounded_quaternions:
            for record2 in rounded_quaternions:
                if record1.name[0] != record2.name[0]:
                    new_quaternions.append(
                        Record(
                            "%s after %s" % (record1.name, record2.name),
                            quaternion_product(record1.quaternion,
                                               record2.quaternion)))

        def filter_out_high_cost(records):
            for record in records:
                #print selected_quaternion, record.quaternion
                cosine = numpy.dot(selected_quaternion, record.quaternion)
                if cosine > 1: cosine = 1
                elif cosine < -1: cosine = -1
                cost_function = int(numpy.arccos(cosine) * 180.0 / numpy.pi)
                if cost_function < 10:
                    record.cost_function = cost_function
                else:
                    record.quaternion = None

            return filter(lambda record: record.quaternion is not None,
                          records)

        new_quaternions = filter_out_high_cost(new_quaternions)

        for index1, record1 in enumerate(new_quaternions):
            if record1.quaternion is not None:
                for record2 in new_quaternions[:index1]:
                    if record2.quaternion is not None:
                        if 1 - numpy.dot(record1.quaternion,
                                         record2.quaternion) < 1e-3:
                            record2.quaternion = None
                for record2 in rounded_quaternions:
                    if 1 - numpy.dot(record1.quaternion,
                                     record2.quaternion) < 1e-3:
                        record1.quaternion = None
                        break

        new_quaternions = filter(lambda record: record.quaternion is not None,
                                 new_quaternions)

        rounded_quaternions = filter_out_high_cost(rounded_quaternions)

        rounded_quaternions.extend(new_quaternions)

        if len(rounded_quaternions) == 0:
            raise UserError("No similar rounded rotations found.")

        rounded_quaternions.sort(key=(lambda x: x.cost_function))

        self.select_quaternion.main_field.records = rounded_quaternions
        user_record = Record("", rounded_quaternions[0].quaternion)
        if self.select_quaternion.run(user_record) != gtk.RESPONSE_OK:
            raise CancelException

        if user_record.quaternion is not None:
            if len(cache.nodes) == 1:
                r = factor * quaternion_to_rotation_matrix(
                    user_record.quaternion)
                new_transformation = victim.transformation.copy_with(r=r)
                primitive.SetProperty(victim, "transformation",
                                      new_transformation)
            elif len(cache.nodes) == 2:
                r = numpy.dot(
                    master.get_frame_relative_to(victim).r,
                    factor *
                    quaternion_to_rotation_matrix(user_record.quaternion),
                )
                old_transformation = victim.transformation.copy_with(r=r)
                primitive.SetProperty(victim,
                                      "transformation",
                                      old_transformation,
                                      done=True)