Пример #1
0
class BondEditor(ToolInstance):

    help = "https://github.com/QChASM/SEQCROW/wiki/Bond-Editor-Tool"
    SESSION_ENDURING = False
    SESSION_SAVE = False

    def __init__(self, session, name):
        super().__init__(session, name)

        self.tool_window = MainToolWindow(self)

        self.settings = _BondEditorSettings(session, name)

        self._build_ui()

    def _build_ui(self):
        layout = QGridLayout()

        tabs = QTabWidget()
        layout.addWidget(tabs)

        ts_bond_tab = QWidget()
        ts_options = QFormLayout(ts_bond_tab)

        self.tsbond_color = ColorButton(has_alpha_channel=False,
                                        max_size=(16, 16))
        self.tsbond_color.set_color(self.settings.tsbond_color)
        ts_options.addRow("color:", self.tsbond_color)

        self.tsbond_transparency = QSpinBox()
        self.tsbond_transparency.setRange(1, 99)
        self.tsbond_transparency.setValue(self.settings.tsbond_transparency)
        self.tsbond_transparency.setSuffix("%")
        ts_options.addRow("transparency:", self.tsbond_transparency)

        self.tsbond_radius = QDoubleSpinBox()
        self.tsbond_radius.setRange(0.01, 1)
        self.tsbond_radius.setDecimals(3)
        self.tsbond_radius.setSingleStep(0.005)
        self.tsbond_radius.setSuffix(" \u212B")
        self.tsbond_radius.setValue(self.settings.tsbond_radius)
        ts_options.addRow("radius:", self.tsbond_radius)

        draw_tsbonds = QPushButton("draw TS bonds on selected atoms/bonds")
        draw_tsbonds.clicked.connect(self.run_tsbond)
        ts_options.addRow(draw_tsbonds)
        self.draw_tsbonds = draw_tsbonds

        erase_tsbonds = QPushButton("erase selected TS bonds")
        erase_tsbonds.clicked.connect(self.run_erase_tsbond)
        ts_options.addRow(erase_tsbonds)
        self.erase_tsbonds = erase_tsbonds

        bond_tab = QWidget()
        bond_options = QFormLayout(bond_tab)

        self.bond_halfbond = QCheckBox()
        self.bond_halfbond.setChecked(self.settings.bond_halfbond)
        self.bond_halfbond.setToolTip(
            "each half of the bond will be colored according to the atom's color"
        )
        bond_options.addRow("half-bond:", self.bond_halfbond)

        self.bond_color = ColorButton(has_alpha_channel=True,
                                      max_size=(16, 16))
        self.bond_color.set_color(self.settings.bond_color)
        self.bond_color.setEnabled(
            self.bond_halfbond.checkState() != Qt.Checked)
        self.bond_halfbond.stateChanged.connect(
            lambda state, widget=self.bond_color: self.bond_color.setEnabled(
                state != Qt.Checked))
        bond_options.addRow("color:", self.bond_color)

        self.bond_radius = QDoubleSpinBox()
        self.bond_radius.setRange(0.01, 1)
        self.bond_radius.setDecimals(3)
        self.bond_radius.setSingleStep(0.005)
        self.bond_radius.setSuffix(" \u212B")
        self.bond_radius.setValue(self.settings.bond_radius)
        bond_options.addRow("radius:", self.bond_radius)

        draw_tsbonds = QPushButton("draw bond between selected atoms")
        draw_tsbonds.clicked.connect(self.run_bond)
        bond_options.addRow(draw_tsbonds)
        self.draw_tsbonds = draw_tsbonds

        erase_bonds = QPushButton("erase selected bonds")
        erase_bonds.clicked.connect(
            lambda *, ses=self.session: run(ses, "delete bonds sel"))
        bond_options.addRow(erase_bonds)
        self.erase_bonds = erase_bonds

        hbond_tab = QWidget()
        hbond_options = QFormLayout(hbond_tab)

        self.hbond_color = ColorButton(has_alpha_channel=True,
                                       max_size=(16, 16))
        self.hbond_color.set_color(self.settings.hbond_color)
        hbond_options.addRow("color:", self.hbond_color)

        self.hbond_radius = QDoubleSpinBox()
        self.hbond_radius.setDecimals(3)
        self.hbond_radius.setSuffix(" \u212B")
        self.hbond_radius.setValue(self.settings.hbond_radius)
        hbond_options.addRow("radius:", self.hbond_radius)

        self.hbond_dashes = QSpinBox()
        self.hbond_dashes.setRange(0, 28)
        self.hbond_dashes.setSingleStep(2)
        self.hbond_radius.setSingleStep(0.005)
        self.hbond_dashes.setValue(self.settings.hbond_dashes)
        hbond_options.addRow("dashes:", self.hbond_dashes)

        draw_hbonds = QPushButton("draw H-bonds")
        draw_hbonds.clicked.connect(self.run_hbond)
        hbond_options.addRow(draw_hbonds)
        self.draw_hbonds = draw_hbonds

        erase_hbonds = QPushButton("erase all H-bonds")
        erase_hbonds.clicked.connect(
            lambda *, ses=self.session: run(ses, "~hbonds"))
        hbond_options.addRow(erase_hbonds)
        self.erase_hbonds = erase_hbonds

        tm_bond_tab = QWidget()
        tm_bond_options = QFormLayout(tm_bond_tab)

        self.tm_bond_color = ColorButton(has_alpha_channel=True,
                                         max_size=(16, 16))
        self.tm_bond_color.set_color(self.settings.tm_bond_color)
        tm_bond_options.addRow("color:", self.tm_bond_color)

        self.tm_bond_radius = QDoubleSpinBox()
        self.tm_bond_radius.setDecimals(3)
        self.tm_bond_radius.setSuffix(" \u212B")
        self.tm_bond_radius.setValue(self.settings.tm_bond_radius)
        tm_bond_options.addRow("radius:", self.tm_bond_radius)

        self.tm_bond_dashes = QSpinBox()
        self.tm_bond_dashes.setRange(0, 28)
        self.tm_bond_dashes.setSingleStep(2)
        self.tm_bond_radius.setSingleStep(0.005)
        self.tm_bond_dashes.setValue(self.settings.tm_bond_dashes)
        tm_bond_options.addRow("dashes:", self.tm_bond_dashes)

        draw_tm_bonds = QPushButton("draw metal coordination bonds")
        draw_tm_bonds.clicked.connect(self.run_tm_bond)
        tm_bond_options.addRow(draw_tm_bonds)
        self.draw_tm_bonds = draw_tm_bonds

        erase_tm_bonds = QPushButton("erase all metal coordination bonds")
        erase_tm_bonds.clicked.connect(self.del_tm_bond)
        tm_bond_options.addRow(erase_tm_bonds)
        self.erase_tm_bonds = erase_tm_bonds

        bond_length_tab = QWidget()
        bond_length_layout = QFormLayout(bond_length_tab)

        self.bond_distance = QDoubleSpinBox()
        self.bond_distance.setRange(0.5, 10.0)
        self.bond_distance.setSingleStep(0.05)
        self.bond_distance.setValue(1.51)
        self.bond_distance.setSuffix(" \u212B")
        bond_length_layout.addRow("bond length:", self.bond_distance)

        self.move_fragment = QComboBox()
        self.move_fragment.addItems(["both", "smaller", "larger"])
        bond_length_layout.addRow("move side:", self.move_fragment)

        bond_lookup = QGroupBox("bond length lookup:")
        bond_lookup_layout = QGridLayout(bond_lookup)

        bond_lookup_layout.addWidget(
            QLabel("elements:"),
            0,
            0,
        )

        self.ele1 = ElementButton("C", single_state=True)
        self.ele1.clicked.connect(
            lambda *args, button=self.ele1: self.open_ptable(button))
        bond_lookup_layout.addWidget(self.ele1, 0, 1,
                                     Qt.AlignRight | Qt.AlignTop)

        bond_lookup_layout.addWidget(QLabel("-"), 0, 2,
                                     Qt.AlignHCenter | Qt.AlignVCenter)

        self.ele2 = ElementButton("C", single_state=True)
        self.ele2.clicked.connect(
            lambda *args, button=self.ele2: self.open_ptable(button))
        bond_lookup_layout.addWidget(self.ele2, 0, 3,
                                     Qt.AlignLeft | Qt.AlignTop)

        bond_lookup_layout.addWidget(QLabel("bond order:"), 1, 0)

        self.bond_order = BondOrderSpinBox()
        self.bond_order.setRange(1., 3.)
        self.bond_order.setValue(1)
        self.bond_order.setSingleStep(0.5)
        self.bond_order.setDecimals(1)
        self.bond_order.valueChanged.connect(self.check_bond_lengths)
        bond_lookup_layout.addWidget(self.bond_order, 1, 1, 1, 3)

        bond_lookup_layout.setColumnStretch(0, 0)
        bond_lookup_layout.setColumnStretch(1, 0)
        bond_lookup_layout.setColumnStretch(2, 0)
        bond_lookup_layout.setColumnStretch(3, 1)

        bond_length_layout.addRow(bond_lookup)

        self.status = QStatusBar()
        self.status.setSizeGripEnabled(False)
        bond_lookup_layout.addWidget(self.status, 2, 0, 1, 4)

        self.do_bond_change = QPushButton("change selected bond lengths")
        self.do_bond_change.clicked.connect(self.change_bond_length)
        bond_length_layout.addRow(self.do_bond_change)

        tabs.addTab(bond_tab, "covalent bonds")
        tabs.addTab(ts_bond_tab, "TS bonds")
        tabs.addTab(hbond_tab, "H-bonds")
        tabs.addTab(tm_bond_tab, "coordination bonds")
        tabs.addTab(bond_length_tab, "bond length")

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)

    def run_tsbond(self, *args):
        args = ["tsbond", "sel"]

        color = self.tsbond_color.get_color()
        args.extend(["color", "rgb(%i, %i, %i)" % tuple(color[:-1])])
        self.settings.tsbond_color = tuple([c / 255. for c in color])

        radius = self.tsbond_radius.value()
        args.extend(["radius", "%.3f" % radius])
        self.settings.tsbond_radius = radius

        transparency = self.tsbond_transparency.value()
        args.extend(["transparency", "%i" % transparency])
        self.settings.tsbond_transparency = transparency

        run(self.session, " ".join(args))

    def run_erase_tsbond(self, *args):
        run(self.session, "~tsbond sel")

    def run_bond(self, *args):
        # TODO: switch to `bond sel` in 1.2
        sel = selected_atoms(self.session)
        halfbond = self.bond_halfbond.checkState() == Qt.Checked
        self.settings.bond_halfbond = halfbond

        if not halfbond:
            color = self.bond_color.get_color()
            color = tuple(x / 255. for x in color)
            self.settings.bond_color = color

        radius = self.bond_radius.value()
        self.settings.bond_radius = radius

        for b in selected_bonds(self.session):
            b.halfbond = halfbond
            if not halfbond:
                b.color = np.array([int(x * 255) for x in color])

            b.radius = radius

        for i, a1 in enumerate(sel):
            for a2 in sel[:i]:
                if a1.structure is a2.structure and a2 not in a1.neighbors:
                    new_bond = a1.structure.new_bond(a1, a2)
                    new_bond.halfbond = halfbond

                    if not halfbond:
                        new_bond.color = np.array(
                            [int(x * 255) for x in color])

                    new_bond.radius = radius

    def run_hbond(self, *args):
        args = ["hbonds", "reveal", "true"]

        color = self.hbond_color.get_color()
        args.extend(["color", "rgb(%i, %i, %i)" % tuple(color[:-1])])
        self.settings.hbond_color = tuple([c / 255. for c in color])

        radius = self.hbond_radius.value()
        args.extend(["radius", "%.3f" % radius])
        self.settings.hbond_radius = radius

        dashes = self.hbond_dashes.value()
        args.extend(["dashes", "%i" % dashes])
        self.settings.hbond_dashes = dashes

        run(self.session, " ".join(args))

    def run_tm_bond(self, *args):
        color = self.tm_bond_color.get_color()
        self.settings.tm_bond_color = tuple([c / 255. for c in color])

        radius = self.tm_bond_radius.value()
        self.settings.tm_bond_radius = radius

        dashes = self.tm_bond_dashes.value()
        self.settings.tm_bond_dashes = dashes

        models = self.session.models.list(type=AtomicStructure)
        for model in models:
            rescol = ResidueCollection(model, bonds_matter=False)
            try:
                tm_list = rescol.find([
                    AnyTransitionMetal(), "Na", "K", "Rb", "Cs", "Fr", "Mg",
                    "Ca", "Sr", "Ba", "Ra"
                ])
                for tm in tm_list:
                    for atom in rescol.atoms:
                        if atom is tm:
                            continue

                        if atom.is_connected(tm):
                            pbg = model.pseudobond_group(
                                model.PBG_METAL_COORDINATION,
                                create_type="normal")
                            pbg.new_pseudobond(tm.chix_atom, atom.chix_atom)
                            pbg.dashes = dashes
                            pbg.color = color
                            pbg.radius = radius

            except LookupError:
                pass

    def del_tm_bond(self, *args):
        models = self.session.models.list(type=AtomicStructure)
        for model in models:
            pbg = model.pseudobond_group(model.PBG_METAL_COORDINATION,
                                         create_type=None)
            if pbg is not None:
                pbg.delete()

    def open_ptable(self, button):
        self.tool_window.create_child_window("select element",
                                             window_class=PTable2,
                                             button=button,
                                             callback=self.check_bond_lengths)

    def check_bond_lengths(self, *args):
        ele1 = self.ele1.text()
        ele2 = self.ele2.text()
        key = ORDER_BOND_ORDER.key(ele1, ele2)

        order = "%.1f" % self.bond_order.value()
        if key in ORDER_BOND_ORDER.bonds and order in ORDER_BOND_ORDER.bonds[
                key]:
            self.bond_distance.setValue(ORDER_BOND_ORDER.bonds[key][order])
            self.status.showMessage("")
        else:
            self.status.showMessage("no bond data for %s-%s %sx bonds" %
                                    (ele1, ele2, order))

    def change_bond_length(self, *args):
        dist = self.bond_distance.value()

        atom_pairs = []

        sel = selected_atoms(self.session)
        if len(sel) == 2 and sel[0].structure is sel[1].structure:
            atom_pairs.append(sel)

        for bond in selected_bonds(self.session):
            if not all(atom in sel for atom in bond.atoms):
                atom_pairs.append(bond.atoms)

        for bond in selected_pseudobonds(self.session):
            if not all(atom in sel for atom in bond.atoms):
                atom_pairs.append(bond.atoms)

        for pair in atom_pairs:
            atom1, atom2 = pair
            frag1 = get_fragment(atom1,
                                 stop=atom2,
                                 max_len=atom1.structure.num_atoms)
            frag2 = get_fragment(atom2,
                                 stop=atom1,
                                 max_len=atom1.structure.num_atoms)

            v = atom2.coord - atom1.coord

            cur_dist = np.linalg.norm(v)
            change = dist - cur_dist

            if self.move_fragment.currentText() == "both":
                change = 0.5 * change
                frag1.coords -= change * v / cur_dist
                frag2.coords += change * v / cur_dist
            elif self.move_fragment.currentText() == "smaller":
                if len(frag1) < len(frag2) or (len(frag1) == len(frag2)
                                               and sum(frag1.elements.masses) <
                                               sum(frag2.elements.masses)):
                    frag1.coords -= change * v / cur_dist
                else:
                    frag2.coords += change * v / cur_dist
            elif self.move_fragment.currentText() == "larger":
                if len(frag1) > len(frag2) or (len(frag1) == len(frag2)
                                               and sum(frag1.elements.masses) >
                                               sum(frag2.elements.masses)):
                    frag1.coords -= change * v / cur_dist
                else:
                    frag2.coords += change * v / cur_dist
Пример #2
0
    def _build_ui(self):
        layout = QGridLayout()

        tabs = QTabWidget()
        layout.addWidget(tabs)

        ts_bond_tab = QWidget()
        ts_options = QFormLayout(ts_bond_tab)

        self.tsbond_color = ColorButton(has_alpha_channel=False,
                                        max_size=(16, 16))
        self.tsbond_color.set_color(self.settings.tsbond_color)
        ts_options.addRow("color:", self.tsbond_color)

        self.tsbond_transparency = QSpinBox()
        self.tsbond_transparency.setRange(1, 99)
        self.tsbond_transparency.setValue(self.settings.tsbond_transparency)
        self.tsbond_transparency.setSuffix("%")
        ts_options.addRow("transparency:", self.tsbond_transparency)

        self.tsbond_radius = QDoubleSpinBox()
        self.tsbond_radius.setRange(0.01, 1)
        self.tsbond_radius.setDecimals(3)
        self.tsbond_radius.setSingleStep(0.005)
        self.tsbond_radius.setSuffix(" \u212B")
        self.tsbond_radius.setValue(self.settings.tsbond_radius)
        ts_options.addRow("radius:", self.tsbond_radius)

        draw_tsbonds = QPushButton("draw TS bonds on selected atoms/bonds")
        draw_tsbonds.clicked.connect(self.run_tsbond)
        ts_options.addRow(draw_tsbonds)
        self.draw_tsbonds = draw_tsbonds

        erase_tsbonds = QPushButton("erase selected TS bonds")
        erase_tsbonds.clicked.connect(self.run_erase_tsbond)
        ts_options.addRow(erase_tsbonds)
        self.erase_tsbonds = erase_tsbonds

        bond_tab = QWidget()
        bond_options = QFormLayout(bond_tab)

        self.bond_halfbond = QCheckBox()
        self.bond_halfbond.setChecked(self.settings.bond_halfbond)
        self.bond_halfbond.setToolTip(
            "each half of the bond will be colored according to the atom's color"
        )
        bond_options.addRow("half-bond:", self.bond_halfbond)

        self.bond_color = ColorButton(has_alpha_channel=True,
                                      max_size=(16, 16))
        self.bond_color.set_color(self.settings.bond_color)
        self.bond_color.setEnabled(
            self.bond_halfbond.checkState() != Qt.Checked)
        self.bond_halfbond.stateChanged.connect(
            lambda state, widget=self.bond_color: self.bond_color.setEnabled(
                state != Qt.Checked))
        bond_options.addRow("color:", self.bond_color)

        self.bond_radius = QDoubleSpinBox()
        self.bond_radius.setRange(0.01, 1)
        self.bond_radius.setDecimals(3)
        self.bond_radius.setSingleStep(0.005)
        self.bond_radius.setSuffix(" \u212B")
        self.bond_radius.setValue(self.settings.bond_radius)
        bond_options.addRow("radius:", self.bond_radius)

        draw_tsbonds = QPushButton("draw bond between selected atoms")
        draw_tsbonds.clicked.connect(self.run_bond)
        bond_options.addRow(draw_tsbonds)
        self.draw_tsbonds = draw_tsbonds

        erase_bonds = QPushButton("erase selected bonds")
        erase_bonds.clicked.connect(
            lambda *, ses=self.session: run(ses, "delete bonds sel"))
        bond_options.addRow(erase_bonds)
        self.erase_bonds = erase_bonds

        hbond_tab = QWidget()
        hbond_options = QFormLayout(hbond_tab)

        self.hbond_color = ColorButton(has_alpha_channel=True,
                                       max_size=(16, 16))
        self.hbond_color.set_color(self.settings.hbond_color)
        hbond_options.addRow("color:", self.hbond_color)

        self.hbond_radius = QDoubleSpinBox()
        self.hbond_radius.setDecimals(3)
        self.hbond_radius.setSuffix(" \u212B")
        self.hbond_radius.setValue(self.settings.hbond_radius)
        hbond_options.addRow("radius:", self.hbond_radius)

        self.hbond_dashes = QSpinBox()
        self.hbond_dashes.setRange(0, 28)
        self.hbond_dashes.setSingleStep(2)
        self.hbond_radius.setSingleStep(0.005)
        self.hbond_dashes.setValue(self.settings.hbond_dashes)
        hbond_options.addRow("dashes:", self.hbond_dashes)

        draw_hbonds = QPushButton("draw H-bonds")
        draw_hbonds.clicked.connect(self.run_hbond)
        hbond_options.addRow(draw_hbonds)
        self.draw_hbonds = draw_hbonds

        erase_hbonds = QPushButton("erase all H-bonds")
        erase_hbonds.clicked.connect(
            lambda *, ses=self.session: run(ses, "~hbonds"))
        hbond_options.addRow(erase_hbonds)
        self.erase_hbonds = erase_hbonds

        tm_bond_tab = QWidget()
        tm_bond_options = QFormLayout(tm_bond_tab)

        self.tm_bond_color = ColorButton(has_alpha_channel=True,
                                         max_size=(16, 16))
        self.tm_bond_color.set_color(self.settings.tm_bond_color)
        tm_bond_options.addRow("color:", self.tm_bond_color)

        self.tm_bond_radius = QDoubleSpinBox()
        self.tm_bond_radius.setDecimals(3)
        self.tm_bond_radius.setSuffix(" \u212B")
        self.tm_bond_radius.setValue(self.settings.tm_bond_radius)
        tm_bond_options.addRow("radius:", self.tm_bond_radius)

        self.tm_bond_dashes = QSpinBox()
        self.tm_bond_dashes.setRange(0, 28)
        self.tm_bond_dashes.setSingleStep(2)
        self.tm_bond_radius.setSingleStep(0.005)
        self.tm_bond_dashes.setValue(self.settings.tm_bond_dashes)
        tm_bond_options.addRow("dashes:", self.tm_bond_dashes)

        draw_tm_bonds = QPushButton("draw metal coordination bonds")
        draw_tm_bonds.clicked.connect(self.run_tm_bond)
        tm_bond_options.addRow(draw_tm_bonds)
        self.draw_tm_bonds = draw_tm_bonds

        erase_tm_bonds = QPushButton("erase all metal coordination bonds")
        erase_tm_bonds.clicked.connect(self.del_tm_bond)
        tm_bond_options.addRow(erase_tm_bonds)
        self.erase_tm_bonds = erase_tm_bonds

        bond_length_tab = QWidget()
        bond_length_layout = QFormLayout(bond_length_tab)

        self.bond_distance = QDoubleSpinBox()
        self.bond_distance.setRange(0.5, 10.0)
        self.bond_distance.setSingleStep(0.05)
        self.bond_distance.setValue(1.51)
        self.bond_distance.setSuffix(" \u212B")
        bond_length_layout.addRow("bond length:", self.bond_distance)

        self.move_fragment = QComboBox()
        self.move_fragment.addItems(["both", "smaller", "larger"])
        bond_length_layout.addRow("move side:", self.move_fragment)

        bond_lookup = QGroupBox("bond length lookup:")
        bond_lookup_layout = QGridLayout(bond_lookup)

        bond_lookup_layout.addWidget(
            QLabel("elements:"),
            0,
            0,
        )

        self.ele1 = ElementButton("C", single_state=True)
        self.ele1.clicked.connect(
            lambda *args, button=self.ele1: self.open_ptable(button))
        bond_lookup_layout.addWidget(self.ele1, 0, 1,
                                     Qt.AlignRight | Qt.AlignTop)

        bond_lookup_layout.addWidget(QLabel("-"), 0, 2,
                                     Qt.AlignHCenter | Qt.AlignVCenter)

        self.ele2 = ElementButton("C", single_state=True)
        self.ele2.clicked.connect(
            lambda *args, button=self.ele2: self.open_ptable(button))
        bond_lookup_layout.addWidget(self.ele2, 0, 3,
                                     Qt.AlignLeft | Qt.AlignTop)

        bond_lookup_layout.addWidget(QLabel("bond order:"), 1, 0)

        self.bond_order = BondOrderSpinBox()
        self.bond_order.setRange(1., 3.)
        self.bond_order.setValue(1)
        self.bond_order.setSingleStep(0.5)
        self.bond_order.setDecimals(1)
        self.bond_order.valueChanged.connect(self.check_bond_lengths)
        bond_lookup_layout.addWidget(self.bond_order, 1, 1, 1, 3)

        bond_lookup_layout.setColumnStretch(0, 0)
        bond_lookup_layout.setColumnStretch(1, 0)
        bond_lookup_layout.setColumnStretch(2, 0)
        bond_lookup_layout.setColumnStretch(3, 1)

        bond_length_layout.addRow(bond_lookup)

        self.status = QStatusBar()
        self.status.setSizeGripEnabled(False)
        bond_lookup_layout.addWidget(self.status, 2, 0, 1, 4)

        self.do_bond_change = QPushButton("change selected bond lengths")
        self.do_bond_change.clicked.connect(self.change_bond_length)
        bond_length_layout.addRow(self.do_bond_change)

        tabs.addTab(bond_tab, "covalent bonds")
        tabs.addTab(ts_bond_tab, "TS bonds")
        tabs.addTab(hbond_tab, "H-bonds")
        tabs.addTab(tm_bond_tab, "coordination bonds")
        tabs.addTab(bond_length_tab, "bond length")

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Пример #3
0
    def _build_ui(self):
        layout = QGridLayout()

        self.library_tabs = QTabWidget()

        #add a tab for ligands
        self.ligand_tab = QWidget()
        self.ligand_layout = QVBoxLayout(self.ligand_tab)
        self.lig_table = LigandTable()
        self.ligand_layout.addWidget(self.lig_table)

        showKeyAtomsCheck = QCheckBox('show key atoms')
        showKeyAtomsCheck.setToolTip(
            "ligand's coordinating atoms will be highlighted")
        showKeyAtomsCheck.toggle()
        showKeyAtomsCheck.stateChanged.connect(self.showKeyAtoms)
        self.ligand_layout.addWidget(showKeyAtomsCheck)

        self.lig_color = ColorButton('key atom color', has_alpha_channel=True)
        self.lig_color.setToolTip("highlight color for ligand's key atoms")
        self.lig_color.set_color(self.settings.key_atom_color)
        self.ligand_layout.addWidget(self.lig_color)

        openLigButton = QPushButton("open selected ligands")
        openLigButton.setToolTip(
            "ligands selected in the table will be loaded into ChimeraX")
        openLigButton.clicked.connect(self.open_ligands)
        self.ligand_layout.addWidget(openLigButton)
        self.openLigButton = openLigButton

        #add a tab for substituents
        self.substituent_tab = QWidget()
        self.substituent_layout = QVBoxLayout(self.substituent_tab)
        self.sub_table = SubstituentTable()
        self.substituent_layout.addWidget(self.sub_table)

        showGhostConnectionCheck = QCheckBox('show ghost connection')
        showGhostConnectionCheck.setToolTip(
            "ligand's coordinating atoms will be highlighted")
        showGhostConnectionCheck.toggle()
        showGhostConnectionCheck.stateChanged.connect(self.showGhostConnection)
        self.substituent_layout.addWidget(showGhostConnectionCheck)

        self.sub_color = ColorButton('ghost connection color',
                                     has_alpha_channel=True)
        self.sub_color.setToolTip("color of ghost connection")
        self.sub_color.set_color(self.settings.ghost_connection_color)
        self.substituent_layout.addWidget(self.sub_color)

        openSubButton = QPushButton("open selected substituents")
        openSubButton.setToolTip(
            "substituents selected in the table will be loaded into ChimeraX")
        openSubButton.clicked.connect(self.open_substituents)
        self.substituent_layout.addWidget(openSubButton)
        self.openSubButton = openSubButton

        #add a tab for rings
        self.ring_tab = QWidget()
        self.ring_layout = QVBoxLayout(self.ring_tab)
        self.ring_table = RingTable()
        self.ring_layout.addWidget(self.ring_table)

        showRingWalkCheck = QCheckBox('show ring walk')
        showRingWalkCheck.setToolTip(
            "arrows will show the way AaronTools traverses the ring")
        showRingWalkCheck.toggle()
        showRingWalkCheck.stateChanged.connect(self.showRingWalk)
        self.ring_layout.addWidget(showRingWalkCheck)

        self.ring_color = ColorButton('walk arrow color',
                                      has_alpha_channel=True)
        self.ring_color.setToolTip("color of walk arrows")
        self.ring_color.set_color(self.settings.ring_walk_color)
        self.ring_layout.addWidget(self.ring_color)

        openRingButton = QPushButton("open selected rings")
        openRingButton.setToolTip(
            "rings selected in the table will be loaded into ChimeraX")
        openRingButton.clicked.connect(self.open_rings)
        self.ring_layout.addWidget(openRingButton)
        self.openRingButton = openRingButton

        self.library_tabs.resize(300, 200)

        self.library_tabs.addTab(self.ligand_tab, "ligands")
        self.library_tabs.addTab(self.substituent_tab, "substituents")
        self.library_tabs.addTab(self.ring_tab, "rings")

        layout.addWidget(self.library_tabs)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Пример #4
0
class AaronTools_Library(ToolInstance):

    help = "https://github.com/QChASM/SEQCROW/wiki/Browse-AaronTools-Libraries-Tool"
    SESSION_ENDURING = True
    SESSION_SAVE = True

    def __init__(self, session, name):
        super().__init__(session, name)

        from chimerax.ui import MainToolWindow
        self.tool_window = MainToolWindow(self)

        self.settings = _BrowseLibSettings(self.session, name)

        self.showLigKeyBool = True
        self.showSubGhostBool = True
        self.showRingWalkBool = True

        self._build_ui()

    def _build_ui(self):
        layout = QGridLayout()

        self.library_tabs = QTabWidget()

        #add a tab for ligands
        self.ligand_tab = QWidget()
        self.ligand_layout = QVBoxLayout(self.ligand_tab)
        self.lig_table = LigandTable()
        self.ligand_layout.addWidget(self.lig_table)

        showKeyAtomsCheck = QCheckBox('show key atoms')
        showKeyAtomsCheck.setToolTip(
            "ligand's coordinating atoms will be highlighted")
        showKeyAtomsCheck.toggle()
        showKeyAtomsCheck.stateChanged.connect(self.showKeyAtoms)
        self.ligand_layout.addWidget(showKeyAtomsCheck)

        self.lig_color = ColorButton('key atom color', has_alpha_channel=True)
        self.lig_color.setToolTip("highlight color for ligand's key atoms")
        self.lig_color.set_color(self.settings.key_atom_color)
        self.ligand_layout.addWidget(self.lig_color)

        openLigButton = QPushButton("open selected ligands")
        openLigButton.setToolTip(
            "ligands selected in the table will be loaded into ChimeraX")
        openLigButton.clicked.connect(self.open_ligands)
        self.ligand_layout.addWidget(openLigButton)
        self.openLigButton = openLigButton

        #add a tab for substituents
        self.substituent_tab = QWidget()
        self.substituent_layout = QVBoxLayout(self.substituent_tab)
        self.sub_table = SubstituentTable()
        self.substituent_layout.addWidget(self.sub_table)

        showGhostConnectionCheck = QCheckBox('show ghost connection')
        showGhostConnectionCheck.setToolTip(
            "ligand's coordinating atoms will be highlighted")
        showGhostConnectionCheck.toggle()
        showGhostConnectionCheck.stateChanged.connect(self.showGhostConnection)
        self.substituent_layout.addWidget(showGhostConnectionCheck)

        self.sub_color = ColorButton('ghost connection color',
                                     has_alpha_channel=True)
        self.sub_color.setToolTip("color of ghost connection")
        self.sub_color.set_color(self.settings.ghost_connection_color)
        self.substituent_layout.addWidget(self.sub_color)

        openSubButton = QPushButton("open selected substituents")
        openSubButton.setToolTip(
            "substituents selected in the table will be loaded into ChimeraX")
        openSubButton.clicked.connect(self.open_substituents)
        self.substituent_layout.addWidget(openSubButton)
        self.openSubButton = openSubButton

        #add a tab for rings
        self.ring_tab = QWidget()
        self.ring_layout = QVBoxLayout(self.ring_tab)
        self.ring_table = RingTable()
        self.ring_layout.addWidget(self.ring_table)

        showRingWalkCheck = QCheckBox('show ring walk')
        showRingWalkCheck.setToolTip(
            "arrows will show the way AaronTools traverses the ring")
        showRingWalkCheck.toggle()
        showRingWalkCheck.stateChanged.connect(self.showRingWalk)
        self.ring_layout.addWidget(showRingWalkCheck)

        self.ring_color = ColorButton('walk arrow color',
                                      has_alpha_channel=True)
        self.ring_color.setToolTip("color of walk arrows")
        self.ring_color.set_color(self.settings.ring_walk_color)
        self.ring_layout.addWidget(self.ring_color)

        openRingButton = QPushButton("open selected rings")
        openRingButton.setToolTip(
            "rings selected in the table will be loaded into ChimeraX")
        openRingButton.clicked.connect(self.open_rings)
        self.ring_layout.addWidget(openRingButton)
        self.openRingButton = openRingButton

        self.library_tabs.resize(300, 200)

        self.library_tabs.addTab(self.ligand_tab, "ligands")
        self.library_tabs.addTab(self.substituent_tab, "substituents")
        self.library_tabs.addTab(self.ring_tab, "rings")

        layout.addWidget(self.library_tabs)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)

    def showKeyAtoms(self, state):
        if state == QtCore.Qt.Checked:
            self.showLigKeyBool = True
        else:
            self.showLigKeyBool = False

    def open_ligands(self):
        for row in self.lig_table.table.selectionModel().selectedRows():
            if self.lig_table.table.isRowHidden(row.row()):
                continue

            lig_name = row.data()
            ligand = Component(lig_name)
            chimera_ligand = ResidueCollection(
                ligand, name=lig_name).get_chimera(self.session)

            self.session.models.add([chimera_ligand])
            apply_seqcrow_preset(chimera_ligand, fallback="Ball-Stick-Endcap")

            if self.showLigKeyBool:
                color = self.lig_color.get_color()

                color = [c / 255. for c in color]

                self.settings.key_atom_color = tuple(color)

                bild_obj = key_atom_highlight(ligand, color, self.session)

                self.session.models.add(bild_obj, parent=chimera_ligand)

    def showGhostConnection(self, state):
        if state == QtCore.Qt.Checked:
            self.showSubGhostBool = True
        else:
            self.showSubGhostBool = False

    def open_substituents(self):
        for row in self.sub_table.table.selectionModel().selectedRows():
            if self.sub_table.table.isRowHidden(row.row()):
                continue

            sub_name = row.data()
            substituent = Substituent(sub_name, name=sub_name)
            chimera_substituent = ResidueCollection(substituent).get_chimera(
                self.session)

            self.session.models.add([chimera_substituent])
            apply_seqcrow_preset(chimera_substituent,
                                 fallback="Ball-Stick-Endcap")

            if self.showSubGhostBool:
                color = self.sub_color.get_color()

                color = [c / 255. for c in color]

                self.settings.ghost_connection_color = tuple(color)

                bild_obj = ghost_connection_highlight(substituent, color,
                                                      self.session)

                self.session.models.add(bild_obj, parent=chimera_substituent)

    def showRingWalk(self, state):
        if state == QtCore.Qt.Checked:
            self.showRingWalkBool = True
        else:
            self.showRingWalkBool = False

    def open_rings(self):
        for row in self.ring_table.table.selectionModel().selectedRows():
            if self.ring_table.table.isRowHidden(row.row()):
                continue

            ring_name = row.data()
            ring = Ring(ring_name, name=ring_name)
            chimera_ring = ResidueCollection(ring.copy()).get_chimera(
                self.session)

            self.session.models.add([chimera_ring])
            apply_seqcrow_preset(chimera_ring, fallback="Ball-Stick-Endcap")

            if self.showRingWalkBool:
                color = self.ring_color.get_color()

                color = [c / 255. for c in color]

                self.ring_walk_color = tuple(color)

                bild_obj = show_walk_highlight(ring, chimera_ring, color,
                                               self.session)

                self.session.models.add(bild_obj, parent=chimera_ring)

    def display_help(self):
        """Show the help for this tool in the help viewer."""
        from chimerax.core.commands import run
        run(self.session,
            'open %s' % self.help if self.help is not None else "")
Пример #5
0
    def __init__(self, session, tool_name):

        self._default_color = (255, 153, 204, 128)  # Transparent pink
        self._max_slider_value = 1000  # QSlider only handles integer values
        self._max_slider_radius = 100.0  # Float maximum radius value, scene units
        self._block_text_update = False  # Avoid radius slider and text continuous updating each other.
        self._block_slider_update = False  # Avoid radius slider and text continuous updating each other.

        b = session.main_view.drawing_bounds()
        vradius = 100 if b is None else b.radius()
        self._max_slider_radius = vradius
        center = b.center() if b else (0, 0, 0)
        self._sphere_model = SphereModel('eraser sphere', session,
                                         self._default_color, center,
                                         0.2 * vradius)

        ToolInstance.__init__(self, session, tool_name)

        self.display_name = 'Map Eraser'

        from chimerax.ui import MainToolWindow
        tw = MainToolWindow(self)
        self.tool_window = tw
        parent = tw.ui_area

        from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QFrame, QCheckBox, QLabel, QPushButton, QLineEdit, QSlider
        from PyQt5.QtCore import Qt

        layout = QVBoxLayout(parent)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        parent.setLayout(layout)

        sf = QFrame(parent)
        layout.addWidget(sf)

        slayout = QHBoxLayout(sf)
        slayout.setContentsMargins(0, 0, 0, 0)
        slayout.setSpacing(10)

        self._show_eraser = se = QCheckBox('Show map eraser sphere', sf)
        se.setCheckState(Qt.Checked)
        se.stateChanged.connect(self._show_eraser_cb)
        slayout.addWidget(se)
        from chimerax.ui.widgets import ColorButton
        self._sphere_color = sc = ColorButton(sf,
                                              max_size=(16, 16),
                                              has_alpha_channel=True)
        sc.color = self._default_color
        sc.color_changed.connect(self._change_color_cb)
        slayout.addWidget(sc)
        slayout.addStretch(1)  # Extra space at end

        rf = QFrame(parent)
        layout.addWidget(rf)
        rlayout = QHBoxLayout(rf)
        rlayout.setContentsMargins(0, 0, 0, 0)
        rlayout.setSpacing(4)

        rl = QLabel('Radius', rf)
        rlayout.addWidget(rl)
        self._radius_entry = rv = QLineEdit('', rf)
        rv.setMaximumWidth(40)
        rv.returnPressed.connect(self._radius_changed_cb)
        rlayout.addWidget(rv)
        self._radius_slider = rs = QSlider(Qt.Horizontal, rf)
        smax = self._max_slider_value
        rs.setRange(0, smax)
        rs.valueChanged.connect(self._radius_slider_moved_cb)
        rlayout.addWidget(rs)

        rv.setText('%.4g' % self._sphere_model.radius)
        self._radius_changed_cb()

        ef = QFrame(parent)
        layout.addWidget(ef)
        elayout = QHBoxLayout(ef)
        elayout.setContentsMargins(0, 0, 0, 0)
        elayout.setSpacing(30)
        eb = QPushButton('Erase inside sphere', ef)
        eb.clicked.connect(self._erase_in_sphere)
        elayout.addWidget(eb)
        eo = QPushButton('Erase outside sphere', ef)
        eo.clicked.connect(self._erase_outside_sphere)
        elayout.addWidget(eo)
        rb = QPushButton('Reduce map bounds', ef)
        rb.clicked.connect(self._crop_map)
        elayout.addWidget(rb)
        elayout.addStretch(1)  # Extra space at end

        layout.addStretch(1)  # Extra space at end

        tw.manage(placement="side")

        # When displayed models change update radius slider range.
        from chimerax.core.models import MODEL_DISPLAY_CHANGED
        h = session.triggers.add_handler(MODEL_DISPLAY_CHANGED,
                                         self._model_display_change)
        self._model_display_change_handler = h
Пример #6
0
    def __init__(self, session, tool_name):
        ToolInstance.__init__(self, session, tool_name)

        self.display_name = 'Marker Placement'

        from chimerax.ui import MainToolWindow
        tw = MainToolWindow(self, close_destroys=False)
        self.tool_window = tw
        parent = tw.ui_area
        
        from PyQt5.QtWidgets import QFrame, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QLineEdit, QSizePolicy, QCheckBox

        playout = QVBoxLayout(parent)
        playout.setContentsMargins(0,0,0,0)
        playout.setSpacing(0)
        parent.setLayout(playout)

        f = QFrame(parent)
        f.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        playout.addWidget(f)
        layout = QVBoxLayout(f)
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)
        f.setLayout(layout)
        
        # Marker and link color and radius
        mf = QFrame(f)
        mf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout.addWidget(mf)
        mm_layout = QHBoxLayout(mf)
        mm_layout.setContentsMargins(0,0,0,0)
        mm_layout.setSpacing(5)
        mf.setLayout(mm_layout)

        ml = QLabel('Marker color', mf)
        mm_layout.addWidget(ml)
        from chimerax.ui.widgets import ColorButton
        self._marker_color = mc = ColorButton(mf, max_size = (16,16))
        mc.color_changed.connect(self._marker_color_changed)
        mm_layout.addWidget(mc)
        rl = QLabel(' radius', mf)
        mm_layout.addWidget(rl)
        self._marker_radius = mr = QLineEdit('', mf)
        mr.setMaximumWidth(40)
        mr.returnPressed.connect(self._marker_radius_changed)
        mm_layout.addWidget(mr)

        mm_layout.addSpacing(20)
        ml = QLabel('Link color', mf)
        mm_layout.addWidget(ml)
        from chimerax.ui.widgets import ColorButton
        self._link_color = lc = ColorButton(mf, max_size = (16,16))
        lc.color_changed.connect(self._link_color_changed)
        mm_layout.addWidget(lc)
        rl = QLabel(' radius', mf)
        mm_layout.addWidget(rl)
        self._link_radius = lr = QLineEdit('', mf)
        lr.setMaximumWidth(40)
        lr.returnPressed.connect(self._link_radius_changed)
        mm_layout.addWidget(lr)

        mm_layout.addStretch(1)    # Extra space at end

        # Link consecutive markers checkbutton
        self.link_new_button = lm = QCheckBox('Link new marker to selected marker', f)
        lm.stateChanged.connect(self.link_new_cb)
        layout.addWidget(lm)

        layout.addSpacing(5)
        hl = QLabel('Place markers using mouse modes in the Markers toolbar')
        layout.addWidget(hl)

        self.update_settings()
        
        tw.manage(placement="side")
Пример #7
0
    def __init__(self, session, tool_name):

        self._default_color = (0, 0, 204, 255)
        self._default_box_color = (0, 255, 0, 255)

        ToolInstance.__init__(self, session, tool_name)

        self.display_name = 'Measure and Color Blobs'

        from chimerax.ui import MainToolWindow
        tw = MainToolWindow(self)
        self.tool_window = tw
        parent = tw.ui_area

        from PyQt5.QtWidgets import QVBoxLayout, QHBoxLayout, QFrame, QCheckBox, QLabel, QPushButton, QSizePolicy
        from PyQt5.QtCore import Qt

        layout = QVBoxLayout(parent)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        parent.setLayout(layout)

        cf = QFrame(parent)
        #        cf.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout.addWidget(cf)

        clayout = QHBoxLayout(cf)
        clayout.setContentsMargins(0, 0, 0, 0)
        clayout.setSpacing(10)

        self._color_blob = cb = QCheckBox('Color blob', cf)
        cb.setCheckState(Qt.Checked)
        clayout.addWidget(cb)
        from chimerax.ui.widgets import ColorButton
        self._blob_color = cbut = ColorButton(cf, max_size=(16, 16))
        cbut.color = self._default_color
        clayout.addWidget(cbut)
        clayout.addSpacing(10)

        self._change_color = cc = QCheckBox('Change color automatically', cf)
        cc.setCheckState(Qt.Checked)
        clayout.addWidget(cc)
        clayout.addStretch(1)  # Extra space at end

        af = QFrame(parent)
        #        af.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout.addWidget(af)

        aflayout = QHBoxLayout(af)
        aflayout.setContentsMargins(0, 0, 0, 0)
        aflayout.setSpacing(10)

        self._show_box = bb = QCheckBox('Show principal axes box', af)
        bb.setCheckState(Qt.Checked)
        aflayout.addWidget(bb)
        self._box_color = bc = ColorButton(af, max_size=(16, 16))
        bc.color = self._default_box_color
        aflayout.addWidget(bc)
        aflayout.addSpacing(10)

        eb = QPushButton('Erase boxes', af)
        eb.clicked.connect(self._erase_boxes)
        aflayout.addWidget(eb)
        aflayout.addStretch(1)  # Extra space at end

        self._message_label = ml = QLabel(parent)
        layout.addWidget(ml)
        layout.addStretch(1)  # Extra space at end

        tw.manage(placement="side")