Exemplo n.º 1
0
    def do(self):
        # A) collect all extra attributes of the selected nodes
        extra_attrs = {}
        for node in context.application.cache.nodes:
            for key, value in node.extra.iteritems():
                other_value = extra_attrs.get(key)
                if other_value is None:
                    extra_attrs[key] = value
                elif isinstance(other_value, Undefined):
                    continue
                elif other_value != value:
                    extra_attrs[key] = Undefined()
        for key, value in extra_attrs.items():
            if isinstance(value, Undefined):
                continue
            for node in context.application.cache.nodes:
                other_value = node.extra.get(key)
                if other_value != value:
                    extra_attrs[key] = Undefined()
                    break

        # B) present the extra attributes in a popup window with editing features
        extra_dialog = ExtraDialog()
        modified_extra_attrs, remove_keys = extra_dialog.run(extra_attrs)
        if len(modified_extra_attrs) > 0 or len(remove_keys) > 0:
            # C) the modified extra attributes are applied to the select objects
            for node in context.application.cache.nodes:
                new_value = node.extra.copy()
                new_value.update(modified_extra_attrs)
                for remove_key in remove_keys:
                    new_value.pop(remove_key, None)
                primitive.SetProperty(node, "extra", new_value)
Exemplo n.º 2
0
 def default_parameters(cls):
     result = Parameters()
     result.n = 5
     result.m = 1
     result.flat = False
     result.max_length = 50 * angstrom
     result.max_error = 0.01 * angstrom
     result.tube_length = Undefined(50 * angstrom)
     return result
Exemplo n.º 3
0
 def write(self):
     if self.get_active() and self.changed():
         representation = self.read_from_widget()
         if self.get_sensitive():
             self.save_history(representation)
             value = self.convert_to_value(representation)
         else:
             value = Undefined(self.convert_to_value(representation))
         self.write_to_instance(value, self.instance)
Exemplo n.º 4
0
 def fn():
     context.application.model.file_open("test/input/silica_layer.zml")
     parameters = Parameters()
     parameters.n = 10
     parameters.m = 4
     parameters.flat = False
     parameters.max_length = 300 * angstrom
     parameters.max_error = 0.01 * angstrom
     parameters.tube_length = Undefined(0.01 * angstrom)
     CreateTube = context.application.plugins.get_action("CreateTube")
     assert CreateTube.analyze_selection(parameters)
     CreateTube(parameters)
Exemplo n.º 5
0
    def ask_parameters(self):
        if len(context.application.cache.nodes) == 1:
            if not isinstance(self.parameters.connect_description2, Undefined):
                self.parameters.connect_description2 = Undefined(
                    self.parameters.connect_description2)
            if not isinstance(self.parameters.repulse_description2, Undefined):
                self.parameters.repulse_description2 = Undefined(
                    self.parameters.repulse_description2)
        else:
            if isinstance(self.parameters.connect_description2, Undefined):
                self.parameters.connect_description2 = self.parameters.connect_description2.value
            if isinstance(self.parameters.repulse_description2, Undefined):
                self.parameters.repulse_description2 = self.parameters.repulse_description2.value
            node1, node2 = context.application.cache.nodes
            relative_rotation = node2.get_frame_relative_to(node1.parent)
            if isinstance(self.parameters.rotation2, Undefined):
                self.parameters.rotation2 = Undefined(relative_rotation)
            else:
                self.parameters.rotation2 = relative_rotation

        if self.parameters_dialog.run(self.parameters) != gtk.RESPONSE_OK:
            self.parameters.clear()
            return
Exemplo n.º 6
0
class UserColorMixin(gobject.GObject):

    __metaclass__ = NodeClass

    #
    # Properties
    #

    def set_user_color(self, user_color, init=False):
        self.user_color = user_color
        if not init:
            self.invalidate_draw_list()

    properties = [
        Property("user_color",
                 Undefined(numpy.array([0.7, 0.7, 0.7, 1.0])),
                 lambda self: self.user_color,
                 set_user_color,
                 signal=True)
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Markup", (1, 7),
            fields.optional.CheckOptional(
                fields.edit.Color(
                    label_text="User defined color",
                    attribute_name="user_color",
                ))),
    ])

    #
    # Draw
    #

    def get_color(self):
        if isinstance(self.user_color, Undefined):
            return self.default_color
        else:
            return self.user_color

    def draw(self):
        context.application.vis_backend.set_color(*self.get_color())
Exemplo n.º 7
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
Exemplo n.º 8
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")

        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.allow_inversions = True
        parameters.minimum_triangle_size = 0.1 * angstrom
        parameters.rotation2 = Undefined()

        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:
        scan_results = context.application.model.folder.children[0]
        for quality, transformation, pairs, inverse_pairs in scan_results.get_connections(
        ):
            assert len(pairs) >= 3
            if len(inverse_pairs) > 0:
                assert len(pairs) == len(inverse_pairs)

        # Test for the first case that the indicated atom pairs are indeed
        # overlapping.
        context.application.main.select_nodes([scan_results])
        ShowConscanResultsWindow = context.application.plugins.get_action(
            "ShowConscanResultsWindow")
        assert ShowConscanResultsWindow.analyze_selection()
        ShowConscanResultsWindow()
        csrw = ShowConscanResultsWindow.conscan_results_window
        csrw.tree_selection.select_path(0)
        action = CustomAction("Apply connection")
        csrw.apply_normal()
        action.finish()
        quality, transformation, pairs, inverse_pairs = scan_results.connections[
            0]
        for atom1, atom2 in pairs:
            f1 = atom1().get_absolute_frame()
            f2 = atom2().get_absolute_frame()
            d = numpy.linalg.norm(f1.t - f2.t)
            assert d < 1e-5
        csrw.window.hide()
Exemplo n.º 9
0
class Atom(GLGeometricBase, UserColorMixin):
    info = ModelObjectInfo("plugins/molecular/atom.svg")
    authors = [authors.toon_verstraelen]

    #
    # State
    #

    def initnonstate(self):
        GLGeometricBase.initnonstate(self, Translation)

    #
    # Properties
    #

    def set_user_radius(self, user_radius, init=False):
        self.user_radius = user_radius
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    def set_quality(self, quality, init=False):
        self.quality = quality
        if not init:
            self.invalidate_draw_list()

    def set_number(self, number, init=False):
        self.number = number
        atom_info = periodic[number]
        if atom_info.vdw_radius is not None:
            self.default_radius = atom_info.vdw_radius * 0.2
        else:
            self.default_radius = 1.0
        color = [atom_info.red, atom_info.green, atom_info.blue, 1.0]
        if None in color:
            self.default_color = numpy.array([0.7, 0.7, 0.7, 1.0], float)
        else:
            self.default_color = numpy.array(color, float)
        if not init:
            self.invalidate_draw_list()
            self.invalidate_boundingbox_list()

    properties = [
        Property("user_radius",
                 Undefined(0.5),
                 lambda self: self.user_radius,
                 set_user_radius,
                 signal=True),
        Property("quality", 15, lambda self: self.quality, set_quality),
        Property("number",
                 6,
                 lambda self: self.number,
                 set_number,
                 signal=True),
    ]

    #
    # Dialog fields (see action EditProperties)
    #

    dialog_fields = set([
        DialogFieldInfo(
            "Geometry", (2, 9),
            fields.optional.CheckOptional(
                fields.faulty.Length(
                    label_text="User defined radius",
                    attribute_name="user_radius",
                    low=0.0,
                    low_inclusive=False,
                ))),
        DialogFieldInfo(
            "Markup", (1, 3),
            fields.faulty.Int(
                label_text="Quality",
                attribute_name="quality",
                minimum=3,
            )),
        DialogFieldInfo(
            "Molecular", (6, 0),
            fields.edit.Element(
                attribute_name="number",
                show_popup=False,
            )),
    ])

    #
    # Draw
    #

    def get_radius(self):
        if isinstance(self.user_radius, Undefined):
            return self.default_radius
        else:
            return self.user_radius

    def draw(self):
        GLGeometricBase.draw(self)
        UserColorMixin.draw(self)
        vb = context.application.vis_backend
        vb.draw_sphere(self.get_radius(), self.quality)

    #
    # Revalidation
    #

    def revalidate_bounding_box(self):
        GLGeometricBase.revalidate_bounding_box(self)
        radius = self.get_radius()
        self.bounding_box.extend_with_corners(
            numpy.array([[-radius, -radius, -radius], [radius, radius,
                                                       radius]]))

    #
    # Tools
    #

    def num_bonds(self):
        Bond = context.application.plugins.get_node("Bond")
        return sum(
            isinstance(reference.parent, Bond)
            for reference in self.references)

    def iter_bonds(self):
        Bond = context.application.plugins.get_node("Bond")
        for reference in self.references:
            referent = reference.parent
            if isinstance(referent, Bond):
                yield referent

    def iter_neighbors(self):
        for bond in self.iter_bonds():
            first = bond.children[0].target
            if first == self:
                neighbor = bond.children[1].target
            else:
                neighbor = first
            if isinstance(neighbor, Atom):
                yield neighbor