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
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 _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)
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 "")
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
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")
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")