def _build_ui(self):
        layout = QFormLayout()

        create_coord_items(self, layout)
        
        do_it = QPushButton("create coordination complexes")
        do_it.clicked.connect(self.create_complexes)
        layout.addRow(do_it)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
    def _build_ui(self):
        layout = QFormLayout()

        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["file", "remove"])
        self.table.horizontalHeader().setStretchLastSection(False)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Fixed)
        self.table.cellClicked.connect(self.table_clicked)
        layout.addRow(self.table)

        self.linters = QComboBox()
        self.linters.addItems([
            "pyflakes",
            "flake8",
            "mypy",
            "pydocstyle",
            "pylint",
        ])
        ndx = self.linters.findText(self.settings.linter, Qt.MatchExactly)
        self.linters.setCurrentIndex(ndx)
        layout.addRow(self.linters)

        lint = QPushButton("run linter")
        lint.clicked.connect(self.run_linter)
        layout.addRow(lint)

        self.add_files(loads(self.settings.files))

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
    def _build_ui(self):
        """
        ui should have:
            * table with a list of available tests and show results after they are done
            * way to filter tests
            * button to run tests
        """
        layout = QFormLayout()

        # table to list test classes and the results
        self.table = QTableWidget()
        self.table.setColumnCount(2)
        self.table.setHorizontalHeaderLabels(["test", "result"])
        self.table.horizontalHeader().setSectionResizeMode(
            0,
            self.table.horizontalHeader().Interactive)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.horizontalHeader().setSectionResizeMode(
            1,
            self.table.horizontalHeader().Stretch)
        self.table.setSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.MinimumExpanding)
        self.table.setSelectionBehavior(self.table.SelectRows)
        layout.addRow(self.table)

        self.filter = QLineEdit()
        self.filter.setPlaceholderText("filter test names")
        self.filter.setClearButtonEnabled(True)
        self.filter.textChanged.connect(self.apply_filter)
        layout.addRow(self.filter)

        self.profile = QCheckBox()
        self.profile.setToolTip("profile functions called during testing "
                                "using cProfile")
        layout.addRow("profile calls:", self.profile)

        self.run_button = QPushButton("run tests")
        self.run_button.clicked.connect(self.run_tests)
        self.run_button.setToolTip(
            "if no tests are selected on the table, run all tests\n" +
            "otherwise, run selected tests")
        layout.addRow(self.run_button)

        self.fill_table()
        self.table.resizeColumnToContents(0)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #4
0
    def ui(self):
        super(AutoRenameWidget, self).ui()

        top_layout = layouts.HorizontalLayout(spacing=2, margins=(0, 0, 0, 0))
        self._unique_id_cbx = checkbox.BaseCheckBox('Unique Id')
        self._last_joint_end_cbx = checkbox.BaseCheckBox('Make Last Joint End')
        top_layout.addStretch()
        top_layout.addWidget(self._unique_id_cbx)
        top_layout.addWidget(self._last_joint_end_cbx)
        self.main_layout.addLayout(top_layout)

        main_splitter = QSplitter(Qt.Horizontal)
        main_splitter.setSizePolicy(QSizePolicy.Preferred,
                                    QSizePolicy.Expanding)
        self.main_layout.addWidget(main_splitter)

        auto_widget = QWidget()
        auto_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        auto_widget.setLayout(auto_layout)
        main_splitter.addWidget(auto_widget)

        self._rules_list = QTreeWidget(self)
        self._rules_list.setHeaderHidden(True)
        self._rules_list.setSortingEnabled(True)
        self._rules_list.setRootIsDecorated(False)
        self._rules_list.setSelectionMode(QAbstractItemView.SingleSelection)
        self._rules_list.sortByColumn(0, Qt.AscendingOrder)
        self._rules_list.setUniformRowHeights(True)
        self._rules_list.setAlternatingRowColors(True)

        auto_layout.addWidget(self._rules_list)

        auto_w = QWidget()
        self.auto_l = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        auto_w.setLayout(self.auto_l)
        auto_w.setMinimumWidth(200)
        main_splitter.addWidget(auto_w)

        self.main_auto_layout = QFormLayout()
        self.auto_l.addLayout(self.main_auto_layout)

        self._rename_btn = buttons.BaseButton('Rename')
        self._rename_btn.setIcon(resources.icon('rename'))
        self.main_layout.addLayout(dividers.DividerLayout())
        self.main_layout.addWidget(self._rename_btn)
Beispiel #5
0
    def __init__(self, id_, items, parent=None):
        super().__init__(parent)

        itemLabel = QLabel(self.tr("Item: "))
        descriptionLabel = QLabel(self.tr("Description: "))
        imageFileLabel = QLabel(self.tr("Image file: "))

        self.createButtons()

        self.itemText = QLabel()
        self.descriptionEditor = QTextEdit()

        self.imageFileEditor = QComboBox()
        self.imageFileEditor.setModel(items.relationModel(1))
        self.imageFileEditor.setModelColumn(
            items.relationModel(1).fieldIndex("file"))

        self.mapper = QDataWidgetMapper(self)
        self.mapper.setModel(items)
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setItemDelegate(QSqlRelationalDelegate(self.mapper))
        self.mapper.addMapping(self.imageFileEditor, 1)
        self.mapper.addMapping(self.itemText, 2, b"text")
        self.mapper.addMapping(self.descriptionEditor, 3)
        self.mapper.setCurrentIndex(id_)

        self.descriptionEditor.textChanged.connect(self.enableButtons)
        self.imageFileEditor.currentIndexChanged.connect(self.enableButtons)

        formLayout = QFormLayout()
        formLayout.addRow(itemLabel, self.itemText)
        formLayout.addRow(imageFileLabel, self.imageFileEditor)
        formLayout.addRow(descriptionLabel, self.descriptionEditor)

        layout = QVBoxLayout()
        layout.addLayout(formLayout)
        layout.addWidget(self.buttonBox)
        self.setLayout(layout)

        self.itemId = id_
        self.displayedImage = self.imageFileEditor.currentText()

        self.setWindowFlags(Qt.Window)
        self.enableButtons(False)
        self.setWindowTitle(self.itemText.text())
Beispiel #6
0
    def _build_ui(self):
        layout = QFormLayout()

        self.model_selector = ModelComboBox(self.session, addNew=True)
        layout.addRow("model:", self.model_selector)

        do_it = QPushButton(
            "add %s %s to selected model" %
            (ChangeElementMouseMode.vsepr, ChangeElementMouseMode.element))
        do_it.clicked.connect(self.new_atom)
        layout.addRow(do_it)

        open_ele_sel = QPushButton("open element picker")
        open_ele_sel.clicked.connect(self.show_ele_sel)
        layout.addRow(open_ele_sel)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
 def _build_ui(self):
     layout = QFormLayout()
     
     self.lig_table = LigandTable(
         singleSelect=True, maxDenticity=2, include_substituents=True
     )
     self.lig_table.table.itemSelectionChanged.connect(self.refresh_selection)
     layout.addRow(self.lig_table)
     
     done = QPushButton("done selecting ligand")
     done.clicked.connect(self.destroy)
     layout.addRow(done)
     
     self.ui_area.setLayout(layout)
     
     self.manage(None)
Beispiel #8
0
    def _build_ui(self):
        #each group has an empty widget at the bottom so they resize the way I want while also having the
        #labels where I want them
        layout = QGridLayout()

        self.tab_widget = QTabWidget()
        layout.addWidget(self.tab_widget)

        #layout for absolute thermo stuff
        absolute_widget = QWidget()
        absolute_layout = QGridLayout(absolute_widget)

        #box for sp
        sp_area_widget = QGroupBox("Single-point")
        sp_layout = QFormLayout(sp_area_widget)

        self.sp_selector = FilereaderComboBox(self.session,
                                              otherItems=['energy'])
        self.sp_selector.currentIndexChanged.connect(self.set_sp)
        sp_layout.addRow(self.sp_selector)

        self.sp_table = QTableWidget()
        self.sp_table.setColumnCount(3)
        self.sp_table.setShowGrid(False)
        self.sp_table.horizontalHeader().hide()
        self.sp_table.verticalHeader().hide()
        self.sp_table.setFrameShape(QTableWidget.NoFrame)
        self.sp_table.setSelectionMode(QTableWidget.NoSelection)
        self.sp_table.insertRow(0)
        sp_layout.addRow(self.sp_table)

        #box for thermo
        therm_area_widget = QGroupBox("Thermal corrections")
        thermo_layout = QFormLayout(therm_area_widget)

        self.thermo_selector = FilereaderComboBox(self.session,
                                                  otherItems=['frequency'])
        self.thermo_selector.currentIndexChanged.connect(self.set_thermo_mdl)
        thermo_layout.addRow(self.thermo_selector)

        self.temperature_line = QDoubleSpinBox()
        self.temperature_line.setMaximum(2**31 - 1)
        self.temperature_line.setValue(298.15)
        self.temperature_line.setSingleStep(10)
        self.temperature_line.setSuffix(" K")
        self.temperature_line.setMinimum(0)
        self.temperature_line.valueChanged.connect(self.set_thermo)
        thermo_layout.addRow("T =", self.temperature_line)

        self.v0_edit = QDoubleSpinBox()
        self.v0_edit.setMaximum(4000)
        self.v0_edit.setValue(self.settings.w0)
        self.v0_edit.setSingleStep(25)
        self.v0_edit.setSuffix(" cm\u207b\u00b9")
        self.v0_edit.valueChanged.connect(self.set_thermo)
        self.v0_edit.setMinimum(0)
        self.v0_edit.setToolTip(
            "frequency parameter for quasi treatments of entropy")
        thermo_layout.addRow("𝜔<sub>0</sub> =", self.v0_edit)

        self.thermo_table = QTableWidget()
        self.thermo_table.setColumnCount(3)
        self.thermo_table.setShowGrid(False)
        self.thermo_table.horizontalHeader().hide()
        self.thermo_table.verticalHeader().hide()
        self.thermo_table.setFrameShape(QTableWidget.NoFrame)
        self.thermo_table.setSelectionMode(QTableWidget.NoSelection)
        thermo_layout.addRow(self.thermo_table)

        # for for total
        sum_area_widget = QGroupBox("Thermochemistry")
        sum_layout = QFormLayout(sum_area_widget)

        self.sum_table = QTableWidget()
        self.sum_table.setColumnCount(3)
        self.sum_table.setShowGrid(False)
        self.sum_table.horizontalHeader().hide()
        self.sum_table.verticalHeader().hide()
        self.sum_table.setFrameShape(QTableWidget.NoFrame)
        self.sum_table.setSelectionMode(QTableWidget.NoSelection)
        sum_layout.addRow(self.sum_table)

        splitter = QSplitter(Qt.Horizontal)
        splitter.setChildrenCollapsible(False)
        splitter.addWidget(sp_area_widget)
        splitter.addWidget(therm_area_widget)
        splitter.addWidget(sum_area_widget)

        absolute_layout.addWidget(splitter)

        self.status = QStatusBar()
        self.status.setSizeGripEnabled(False)
        self.status.setStyleSheet("color: red")
        absolute_layout.addWidget(self.status, 1, 0, 1, 1, Qt.AlignTop)

        self.tab_widget.addTab(absolute_widget, "absolute")

        relative_widget = QWidget()
        relative_layout = QGridLayout(relative_widget)

        size = [self.settings.ref_col_1, self.settings.ref_col_2]
        self.ref_group = ThermoGroup("reference group", self.session,
                                     self.nrg_fr, self.thermo_co, size)
        self.ref_group.changes.connect(self.calc_relative_thermo)
        relative_layout.addWidget(self.ref_group, 0, 0, 1, 3, Qt.AlignTop)

        size = [self.settings.other_col_1, self.settings.other_col_2]
        self.other_group = ThermoGroup("other group", self.session,
                                       self.nrg_fr, self.thermo_co, size)
        self.other_group.changes.connect(self.calc_relative_thermo)
        relative_layout.addWidget(self.other_group, 0, 3, 1, 3, Qt.AlignTop)

        self.relative_temperature = QDoubleSpinBox()
        self.relative_temperature.setMaximum(2**31 - 1)
        self.relative_temperature.setValue(self.settings.rel_temp)
        self.relative_temperature.setSingleStep(10)
        self.relative_temperature.setSuffix(" K")
        self.relative_temperature.setMinimum(0)
        self.relative_temperature.valueChanged.connect(
            self.calc_relative_thermo)
        relative_layout.addWidget(QLabel("T ="), 1, 0, 1, 1,
                                  Qt.AlignRight | Qt.AlignVCenter)
        relative_layout.addWidget(self.relative_temperature, 1, 1, 1, 5,
                                  Qt.AlignLeft | Qt.AlignVCenter)

        self.relative_v0 = QDoubleSpinBox()
        self.relative_v0.setMaximum(2**31 - 1)
        self.relative_v0.setValue(self.settings.w0)
        self.relative_v0.setSingleStep(25)
        self.relative_v0.setSuffix(" cm\u207b\u00b9")
        self.relative_v0.setMinimum(0)
        self.relative_v0.setToolTip(
            "frequency parameter for quasi treatments of entropy")
        self.relative_v0.valueChanged.connect(self.calc_relative_thermo)
        relative_layout.addWidget(QLabel("𝜔<sub>0</sub> ="), 2, 0, 1, 1,
                                  Qt.AlignRight | Qt.AlignVCenter)

        relative_layout.addWidget(self.relative_v0, 2, 1, 1, 5,
                                  Qt.AlignLeft | Qt.AlignVCenter)

        relative_layout.addWidget(
            QLabel("Boltzmann-weighted relative energies in kcal/mol:"), 3, 0,
            1, 6, Qt.AlignVCenter | Qt.AlignLeft)

        self.relative_table = QTextBrowser()
        self.relative_table.setMaximumHeight(
            4 * self.relative_table.fontMetrics().boundingRect("Q").height())
        relative_layout.addWidget(self.relative_table, 4, 0, 1, 6, Qt.AlignTop)

        relative_layout.setRowStretch(0, 1)
        relative_layout.setRowStretch(1, 0)
        relative_layout.setRowStretch(2, 0)
        relative_layout.setRowStretch(3, 0)
        relative_layout.setRowStretch(4, 0)

        self.tab_widget.addTab(relative_widget, "relative")

        #menu stuff
        menu = QMenuBar()

        export = menu.addMenu("&Export")
        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)
        self.copy = copy

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)
        menu.setVisible(True)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #9
0
    def addAttributeSlot(self):
        """ Adds a new attribute (column) to the table """

        dialog = QDialog(self)
        dialog.setModal(True)
        dialog.setWindowTitle('Add Attribute')

        layout = QVBoxLayout()
        dialog.setLayout(layout)

        form = QFormLayout()
        nameBox = QLineEdit()
        typeCombo = QComboBox()
        for attrType in _attrTypes:
            typeName = partio.TypeName(attrType)
            typeCombo.addItem(typeName)
        typeCombo.setCurrentIndex(partio.FLOAT)
        countBox = QLineEdit()
        countBox.setValidator(QIntValidator())
        countBox.setText('1')
        fixedCheckbox = QCheckBox()
        valueBox = QLineEdit()
        valueBox.setText('0')
        form.addRow('Name:', nameBox)
        form.addRow('Type:', typeCombo)
        form.addRow('Count:', countBox)
        form.addRow('Fixed:', fixedCheckbox)
        form.addRow('Default Value:', valueBox)
        layout.addLayout(form)

        buttons = QHBoxLayout()
        layout.addLayout(buttons)

        add = QPushButton('Add')
        add.clicked.connect(dialog.accept)
        buttons.addWidget(add)

        cancel = QPushButton('Cancel')
        cancel.clicked.connect(dialog.reject)
        buttons.addWidget(cancel)

        if not dialog.exec_():
            return

        name = str(nameBox.text())
        if not name:
            print('Please supply a name for the new attribute')  # TODO: prompt
            return

        attrType = typeCombo.currentIndex()
        count = int(countBox.text())
        fixed = fixedCheckbox.isChecked()
        values = list(str(valueBox.text()).strip().split())
        for i in range(count):
            if i < len(values):
                value = values[i]
            else:
                value = values[-1]
            if attrType == partio.INT or attrType == partio.INDEXEDSTR:
                values[i] = int(value)
            elif attrType == partio.FLOAT or attrType == partio.VECTOR:
                values[i] = float(value)  # pylint:disable=R0204
            else:
                values[i] = 0.0  # pylint:disable=R0204
        value = tuple(values)

        self.data.addAttribute(name, attrType, count, fixed, value)
Beispiel #10
0
    def _build_ui(self):
        layout = QGridLayout()
        
        self.alchemy_tabs = QTabWidget()
        
        #substitute
        substitute_tab = QWidget()
        substitute_layout = QGridLayout(substitute_tab) 

        sublabel = QLabel("substituent name:")
        substitute_layout.addWidget(sublabel, 0, 0, Qt.AlignVCenter)
        
        self.subname = QLineEdit()
        # self.subname.setText("Et")
        sub_completer = NameCompleter(Substituent.list(), self.subname)
        self.subname.setCompleter(sub_completer)
        self.subname.setToolTip("name of substituent in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures")
        substitute_layout.addWidget(self.subname, 0, 1, Qt.AlignVCenter)
        
        open_sub_lib = QPushButton("from library...")
        open_sub_lib.clicked.connect(self.open_sub_selector)
        substitute_layout.addWidget(open_sub_lib, 0, 2, Qt.AlignTop)        
        
        substitute_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter)
        
        self.close_previous_sub = QCheckBox()
        self.close_previous_sub.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure")
        self.close_previous_sub.setChecked(self.settings.modify)
        self.close_previous_sub.stateChanged.connect(self.close_previous_change)
        substitute_layout.addWidget(self.close_previous_sub, 1, 1, 1, 2, Qt.AlignTop)    
        
        substitute_layout.addWidget(QLabel("relax substituent:"), 2, 0, 1, 1, Qt.AlignVCenter)
        
        self.minimize = QCheckBox()
        self.minimize.setToolTip("spin the added substituents to try to minimize the LJ potential energy")
        self.minimize.setChecked(self.settings.minimize)
        substitute_layout.addWidget(self.minimize, 2, 1, 1, 1, Qt.AlignTop)
        
        substitute_layout.addWidget(QLabel("guess previous substituent:"), 3, 0, 1, 1, Qt.AlignVCenter)
        
        self.guess_old = QCheckBox()
        self.guess_old.setToolTip("checked: leave the longest connected fragment in the residue\nunchecked: previous substituent must be selected")
        self.guess_old.setChecked(self.settings.guess)
        self.guess_old.stateChanged.connect(lambda state, settings=self.settings: settings.__setattr__("guess", True if state == Qt.Checked else False))
        substitute_layout.addWidget(self.guess_old, 3, 1, 1, 2, Qt.AlignTop)
        
        substitute_layout.addWidget(QLabel("new residue:"), 5, 0, 1, 1, Qt.AlignVCenter)

        self.new_residue = QCheckBox()
        self.new_residue.setToolTip("put the new substituent in its own residue instead\nof adding it to the residue of the old substituent")
        self.new_residue.setChecked(self.settings.new_residue)
        self.new_residue.stateChanged.connect(lambda state, settings=self.settings: settings.__setattr__("new_residue", True if state == Qt.Checked else False))
        substitute_layout.addWidget(self.new_residue, 5, 1, 1, 2, Qt.AlignTop)
        
        substitute_layout.addWidget(QLabel("use distance names:"), 4, 0, 1, 1, Qt.AlignVCenter)
        
        self.use_greek = QCheckBox()
        self.use_greek.setChecked(self.settings.use_greek)
        self.use_greek.setToolTip("indicate distance from point of attachment with atom name")
        substitute_layout.addWidget(self.use_greek, 4, 1, 1, 1, Qt.AlignTop)

        substitute_layout.addWidget(QLabel("change residue name:"), 6, 0, 1, 1, Qt.AlignVCenter)
        
        self.new_sub_name = QLineEdit()
        self.new_sub_name.setToolTip("change name of modified residues")
        self.new_sub_name.setPlaceholderText("leave blank to keep current")
        substitute_layout.addWidget(self.new_sub_name, 6, 1, 1, 2, Qt.AlignTop)

        substitute_button = QPushButton("substitute current selection")
        substitute_button.clicked.connect(self.do_substitute)
        substitute_layout.addWidget(substitute_button, 7, 0, 1, 3, Qt.AlignTop)
        self.substitute_button = substitute_button
        
        substitute_layout.setRowStretch(0, 0)
        substitute_layout.setRowStretch(1, 0)
        substitute_layout.setRowStretch(2, 0)
        substitute_layout.setRowStretch(3, 0)
        substitute_layout.setRowStretch(4, 0)
        substitute_layout.setRowStretch(5, 0)
        substitute_layout.setRowStretch(6, 0)
        substitute_layout.setRowStretch(7, 1)
        
        
        #map ligand
        maplig_tab = QWidget()
        maplig_layout = QGridLayout(maplig_tab)
        
        liglabel = QLabel("ligand name:")
        maplig_layout.addWidget(liglabel, 0, 0, Qt.AlignVCenter)
        
        self.ligname = QLineEdit()
        lig_completer = NameCompleter(Component.list(), self.ligname)
        self.ligname.setCompleter(lig_completer)
        self.ligname.setToolTip("name of ligand in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures")
        maplig_layout.addWidget(self.ligname, 0, 1, Qt.AlignVCenter)
        
        open_lig_lib = QPushButton("from library...")
        open_lig_lib.clicked.connect(self.open_lig_selector)
        maplig_layout.addWidget(open_lig_lib, 0, 2, Qt.AlignTop)        
        
        maplig_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter)
        
        self.close_previous_lig = QCheckBox()
        self.close_previous_lig.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure")
        self.close_previous_lig.setChecked(self.settings.modify)
        self.close_previous_lig.stateChanged.connect(self.close_previous_change)
        maplig_layout.addWidget(self.close_previous_lig, 1, 1, 1, 2, Qt.AlignTop)

        maplig_button = QPushButton("swap ligand with selected coordinating atoms")
        maplig_button.clicked.connect(self.do_maplig)
        maplig_layout.addWidget(maplig_button, 2, 0, 1, 3, Qt.AlignTop)
        self.maplig_button = maplig_button

        start_structure_button = QPushButton("place in:")
        self.lig_model_selector = ModelComboBox(self.session, addNew=True)
        start_structure_button.clicked.connect(self.do_new_lig)
        maplig_layout.addWidget(start_structure_button, 3, 0, 1, 1, Qt.AlignTop)
        maplig_layout.addWidget(self.lig_model_selector, 3, 1, 1, 2, Qt.AlignTop)

        maplig_layout.setRowStretch(0, 0)
        maplig_layout.setRowStretch(1, 0)
        maplig_layout.setRowStretch(2, 0)
        maplig_layout.setRowStretch(3, 1)
        
        
        #close ring
        closering_tab = QWidget()
        closering_layout = QGridLayout(closering_tab)
        
        ringlabel = QLabel("ring name:")
        closering_layout.addWidget(ringlabel, 0, 0, Qt.AlignVCenter)
        
        self.ringname = QLineEdit()
        ring_completer = NameCompleter(Ring.list(), self.ringname)
        self.ringname.setCompleter(ring_completer)
        self.ringname.setToolTip("name of ring in the AaronTools library or your personal library\nseparate names with commas and uncheck 'modify selected structure' to create several structures")
        closering_layout.addWidget(self.ringname, 0, 1, Qt.AlignVCenter)
        
        open_ring_lib = QPushButton("from library...")
        open_ring_lib.clicked.connect(self.open_ring_selector)
        closering_layout.addWidget(open_ring_lib, 0, 2, Qt.AlignTop)        
        
        closering_layout.addWidget(QLabel("modify selected structure:"), 1, 0, 1, 1, Qt.AlignVCenter) 
        
        self.close_previous_ring = QCheckBox()
        self.close_previous_ring.setToolTip("checked: selected structure will be modified\nunchecked: new model will be created for the modified structure")
        self.close_previous_ring.setChecked(self.settings.modify)
        self.close_previous_ring.stateChanged.connect(self.close_previous_change)
        closering_layout.addWidget(self.close_previous_ring, 1, 1, 1, 2, Qt.AlignTop)

        closering_layout.addWidget(QLabel("try multiple:"), 2, 0, 1, 1, Qt.AlignVCenter)

        self.minimize_ring = QCheckBox()
        self.minimize_ring.setToolTip("try to use other versions of this ring in the library to find the one that fits best")
        self.minimize_ring.setChecked(self.settings.minimize_ring)
        closering_layout.addWidget(self.minimize_ring, 2, 1, 1, 2, Qt.AlignTop)

        closering_layout.addWidget(QLabel("new residue name:"), 3, 0, 1, 1, Qt.AlignVCenter)
        
        self.new_ring_name = QLineEdit()
        self.new_ring_name.setToolTip("change name of modified residues")
        self.new_ring_name.setPlaceholderText("leave blank to keep current")
        closering_layout.addWidget(self.new_ring_name, 3, 1, 1, 2, Qt.AlignTop)

        closering_button = QPushButton("put a ring on current selection")
        closering_button.clicked.connect(self.do_fusering)

        closering_layout.addWidget(closering_button, 4, 0, 1, 3, Qt.AlignTop)
        self.closering_button = closering_button

        start_structure_button = QPushButton("place in:")
        self.ring_model_selector = ModelComboBox(self.session, addNew=True)
        start_structure_button.clicked.connect(self.do_new_ring)
        closering_layout.addWidget(start_structure_button, 5, 0, 1, 1, Qt.AlignTop)
        closering_layout.addWidget(self.ring_model_selector, 5, 1, 1, 2, Qt.AlignTop)

        closering_layout.setRowStretch(0, 0)
        closering_layout.setRowStretch(1, 0)
        closering_layout.setRowStretch(2, 0)
        closering_layout.setRowStretch(3, 0)
        closering_layout.setRowStretch(4, 0)
        closering_layout.setRowStretch(5, 1)


        #change element
        changeelement_tab = QWidget()
        changeelement_layout = QFormLayout(changeelement_tab)
        
        self.element = ElementButton("C", single_state=True)
        self.element.clicked.connect(self.open_ptable)
        changeelement_layout.addRow("element:", self.element)
        
        self.vsepr = QComboBox()
        self.vsepr.addItems([
            "do not change",                  # 0
            
            "linear (1 bond)",                # 1
            
            "linear (2 bonds)",               # 2 
            "trigonal planar (2 bonds)",      # 3
            "tetrahedral (2 bonds)",          # 4 
            
            "trigonal planar",                # 5
            "tetrahedral (3 bonds)",          # 6
            "T-shaped",                       # 7
            
            "trigonal pyramidal",             # 8
            "tetrahedral",                    # 9
            "sawhorse",                       #10
            "seesaw",                         #11
            "square planar",                  #12
            
            "trigonal bipyramidal",           #13
            "square pyramidal",               #14
            "pentagonal",                     #15
            
            "octahedral",                     #16
            "hexagonal",                      #17
            "trigonal prismatic",             #18
            "pentagonal pyramidal",           #19
            
            "capped octahedral",              #20
            "capped trigonal prismatic",      #21
            "heptagonal",                     #22
            "hexagonal pyramidal",            #23
            "pentagonal bipyramidal",         #24
            
            "biaugmented trigonal prismatic", #25
            "cubic",                          #26
            "elongated trigonal bipyramidal", #27
            "hexagonal bipyramidal",          #28
            "heptagonal pyramidal",           #29
            "octagonal",                      #30
            "square antiprismatic",           #31
            "trigonal dodecahedral",          #32
            
            "capped cube",                    #33
            "capped square antiprismatic",    #34
            "enneagonal",                     #35
            "heptagonal bipyramidal",         #36
            "hula-hoop",                      #37
            "triangular cupola",              #38
            "tridiminished icosahedral",      #39
            "muffin",                         #40
            "octagonal pyramidal",            #41
            "tricapped trigonal prismatic",   #42
        ])
        
        self.vsepr.setCurrentIndex(9)
        
        self.vsepr.insertSeparator(33)
        self.vsepr.insertSeparator(25)
        self.vsepr.insertSeparator(20)
        self.vsepr.insertSeparator(16)
        self.vsepr.insertSeparator(13)
        self.vsepr.insertSeparator(8)
        self.vsepr.insertSeparator(5)
        self.vsepr.insertSeparator(2)
        self.vsepr.insertSeparator(1)
        self.vsepr.insertSeparator(0)
        changeelement_layout.addRow("geometry:", self.vsepr)
        
        self.change_bonds = QCheckBox()
        self.change_bonds.setChecked(self.settings.change_bonds)
        changeelement_layout.addRow("adjust bond lengths:", self.change_bonds)
        
        change_element_button = QPushButton("change selected elements")
        change_element_button.clicked.connect(self.do_change_element)
        changeelement_layout.addRow(change_element_button)
        self.change_element_button = change_element_button

        start_structure_button = QPushButton("place in:")
        self.model_selector = ModelComboBox(self.session, addNew=True)
        start_structure_button.clicked.connect(self.do_new_atom)
        changeelement_layout.addRow(start_structure_button, self.model_selector)
        
        delete_atoms_button = QPushButton("delete selected atoms")
        delete_atoms_button.clicked.connect(self.delete_atoms)
        changeelement_layout.addRow(delete_atoms_button)

        self.alchemy_tabs.addTab(substitute_tab, "substitute")
        self.alchemy_tabs.addTab(maplig_tab, "swap ligand")
        self.alchemy_tabs.addTab(closering_tab, "fuse ring")
        self.alchemy_tabs.addTab(changeelement_tab, "change element")

        layout.addWidget(self.alchemy_tabs)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #11
0
    def _build_ui(self):
        layout = QFormLayout()

        self.substituent_table = SubstituentTable(singleSelect=True)
        layout.addRow(self.substituent_table)

        self.new_residue = QCheckBox()
        self.new_residue.setCheckState(
            Qt.Checked if SubstituteMouseMode.newRes else Qt.Unchecked)
        layout.addRow("new residue:", self.new_residue)

        self.res_name = QLineEdit()
        self.res_name.setPlaceholderText("leave blank to keep current")
        layout.addRow("set residue name:", self.res_name)

        self.distance_names = QCheckBox()
        self.distance_names.setCheckState(
            Qt.Checked if SubstituteMouseMode.useRemoteness else Qt.Unchecked)
        layout.addRow("distance atom names:", self.distance_names)

        self.keep_open = QCheckBox()
        layout.addRow("keep list open:", self.keep_open)

        do_it = QPushButton("set substituent")
        do_it.clicked.connect(self.set_sub)
        layout.addRow(do_it)

        self.keep_open.stateChanged.connect(
            lambda state: do_it.setVisible(state != Qt.Checked))
        self.keep_open.stateChanged.connect(self.sub_changed)

        self.substituent_table.table.itemSelectionChanged.connect(
            self.sub_changed)
        self.new_residue.stateChanged.connect(self.sub_changed)
        self.res_name.textChanged.connect(self.sub_changed)
        self.distance_names.stateChanged.connect(self.sub_changed)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #12
0
    def addAttributeSlot(self):
        """ Adds a new attribute (column) to the table """

        dialog = QDialog(self)
        dialog.setModal(True)
        dialog.setWindowTitle('Add Attribute')

        layout = QVBoxLayout()
        dialog.setLayout(layout)

        form = QFormLayout()
        nameBox = QLineEdit()
        typeCombo = QComboBox()
        for attrType in _attrTypes:
            typeName = partio.TypeName(attrType)
            typeCombo.addItem(typeName)
        typeCombo.setCurrentIndex(partio.FLOAT)
        countBox = QLineEdit()
        countBox.setValidator(QIntValidator())
        countBox.setText('1')
        fixedCheckbox = QCheckBox()
        valueBox = QLineEdit()
        valueBox.setText('0')
        form.addRow('Name:', nameBox)
        form.addRow('Type:', typeCombo)
        form.addRow('Count:', countBox)
        form.addRow('Fixed:', fixedCheckbox)
        form.addRow('Default Value:', valueBox)
        layout.addLayout(form)

        buttons = QHBoxLayout()
        layout.addLayout(buttons)

        add = QPushButton('Add')
        add.clicked.connect(dialog.accept)
        buttons.addWidget(add)

        cancel = QPushButton('Cancel')
        cancel.clicked.connect(dialog.reject)
        buttons.addWidget(cancel)

        if not dialog.exec_():
            return

        name = str(nameBox.text())
        if not name:
            print 'Please supply a name for the new attribute' # TODO: prompt
            return

        attrType = typeCombo.currentIndex()
        count = int(countBox.text())
        fixed = fixedCheckbox.isChecked()
        values = list(str(valueBox.text()).strip().split())
        for i in range(count):
            if i < len(values):
                value = values[i]
            else:
                value = values[-1]
            if attrType == partio.INT or attrType == partio.INDEXEDSTR:
                values[i] = int(value)
            elif attrType == partio.FLOAT or attrType == partio.VECTOR:
                values[i] = float(value) # pylint:disable=R0204
            else:
                values[i] = 0.0 # pylint:disable=R0204
        value = tuple(values)

        self.data.addAttribute(name, attrType, count, fixed, value)
Beispiel #13
0
    def _build_ui(self):
        layout = QFormLayout()

        self.radii_option = QComboBox()
        self.radii_option.addItems(["Bondi", "UMN"])
        ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly)
        self.radii_option.setCurrentIndex(ndx)
        layout.addRow("radii:", self.radii_option)

        self.L_option = QComboBox()
        self.L_option.addItems([
            "to centroid of coordinating atoms",
            "bisect angle between coordinating atoms"
        ])
        ndx = self.L_option.findText(self.settings.L_option, Qt.MatchExactly)
        self.L_option.setCurrentIndex(ndx)
        layout.addRow("L axis:", self.L_option)

        self.sterimol2vec = QGroupBox("Sterimol2Vec")
        sterimol2vec_layout = QFormLayout(self.sterimol2vec)

        self.at_L = QDoubleSpinBox()
        self.at_L.setRange(-10, 30)
        self.at_L.setDecimals(2)
        self.at_L.setSingleStep(0.25)
        self.at_L.setValue(self.settings.at_L)
        sterimol2vec_layout.addRow("L value:", self.at_L)

        layout.addRow(self.sterimol2vec)

        self.sterimol2vec.setCheckable(True)
        self.sterimol2vec.toggled.connect(lambda x: self.at_L.setEnabled(x))
        self.sterimol2vec.setChecked(self.settings.sterimol2vec)

        self.display_vectors = QCheckBox()
        self.display_vectors.setChecked(self.settings.display_vectors)
        layout.addRow("show vectors:", self.display_vectors)

        self.display_radii = QCheckBox()
        self.display_radii.setChecked(self.settings.display_radii)
        layout.addRow("show radii:", self.display_radii)

        calc_sterimol_button = QPushButton(
            "calculate parameters for selected ligands")
        calc_sterimol_button.clicked.connect(self.calc_sterimol)
        layout.addRow(calc_sterimol_button)
        self.calc_sterimol_button = calc_sterimol_button

        remove_sterimol_button = QPushButton("remove Sterimol visualizations")
        remove_sterimol_button.clicked.connect(self.del_sterimol)
        layout.addRow(remove_sterimol_button)
        self.remove_sterimol_button = remove_sterimol_button

        self.table = QTableWidget()
        self.table.setColumnCount(8)
        self.table.setHorizontalHeaderLabels([
            'model',
            'coord. atoms',
            'B\u2081',
            'B\u2082',
            'B\u2083',
            'B\u2084',
            'B\u2085',
            'L',
        ])
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.resizeColumnToContents(0)
        self.table.resizeColumnToContents(1)
        self.table.resizeColumnToContents(2)
        self.table.resizeColumnToContents(3)
        self.table.resizeColumnToContents(4)
        self.table.resizeColumnToContents(5)
        self.table.resizeColumnToContents(6)
        self.table.resizeColumnToContents(7)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            3, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            4, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            5, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            6, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            7, QHeaderView.Stretch)
        layout.addRow(self.table)

        menu = QMenuBar()

        export = menu.addMenu("&Export")

        clear = QAction("Clear data table", self.tool_window.ui_area)
        clear.triggered.connect(self.clear_table)
        export.addAction(clear)

        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)
        menu.setVisible(True)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #14
0
    def _build_ui(self):
        layout = QGridLayout()

        tab_widget = QTabWidget()
        layout.addWidget(tab_widget)

        structure_widget = QWidget()
        structure_layout = QGridLayout(structure_widget)
        tab_widget.addTab(structure_widget, "structure")

        self.structure_source = QComboBox()
        self.structure_source.addItems(
            ["AARON template", "file", "coordination complexes", "SMILES"])

        structure_layout.addWidget(QLabel("structure source:"), 0, 0, 1, 1,
                                   Qt.AlignLeft | Qt.AlignVCenter)

        structure_layout.addWidget(
            self.structure_source,
            0,
            1,
            1,
            1,
        )

        open_button = QPushButton("open")
        open_button.clicked.connect(self.open_template)
        structure_layout.addWidget(
            open_button,
            0,
            2,
            1,
            1,
        )

        # SMILES options
        self.smiles_options = QGroupBox("SMILES options")
        smiles_layout = QFormLayout(self.smiles_options)
        structure_layout.addWidget(self.smiles_options, 1, 0, 1, 3,
                                   Qt.AlignTop | Qt.AlignHCenter)

        self.smiles_line = QLineEdit()
        smiles_layout.addRow("SMILES string:", self.smiles_line)

        self.smiles_options.setVisible(
            self.structure_source.currentText() == "SMILES")
        self.structure_source.currentTextChanged.connect(
            lambda text: self.smiles_options.setVisible(text == "SMILES"))

        # coordination complexes options
        self.coord_comp_options = QGroupBox("Coordination Complex Options")
        coord_layout = QFormLayout(self.coord_comp_options)
        structure_layout.addWidget(self.coord_comp_options, 1, 0, 1, 3,
                                   Qt.AlignTop | Qt.AlignHCenter)

        create_coord_items(self,
                           coord_layout,
                           allow_minimization=False,
                           default_ele="Pd")

        self.coord_comp_options.setVisible(
            self.structure_source.currentText() == "coordination complexes")
        self.structure_source.currentTextChanged.connect(
            lambda text: self.coord_comp_options.setVisible(
                text == "coordination complexes"))

        # aaron template options
        self.aaron_options = QGroupBox("AARON template structures")
        aaron_layout = QFormLayout(self.aaron_options)
        structure_layout.addWidget(self.aaron_options, 1, 0, 1, 3,
                                   Qt.AlignTop | Qt.AlignHCenter)

        self.aaron_options.setVisible(
            self.structure_source.currentText() == "AARON template")
        self.structure_source.currentTextChanged.connect(
            lambda text: self.aaron_options.setVisible(text == "AARON template"
                                                       ))

        # file options
        self.file_options = QGroupBox("single file options")
        file_layout = QFormLayout(self.file_options)
        structure_layout.addWidget(self.file_options, 1, 0, 1, 3,
                                   Qt.AlignTop | Qt.AlignHCenter)

        file_widget = QWidget()
        file_browse_layout = QGridLayout(file_widget)

        self.template_file = QLineEdit()
        file_browse_layout.addWidget(self.template_file, 0, 0, 1, 1,
                                     Qt.AlignCenter)
        browse_button = QPushButton("browse...")
        # browse_button.clicked.connect(self.browse_file_template)
        file_browse_layout.addWidget(browse_button, 0, 1, 1, 1, Qt.AlignCenter)

        file_browse_layout.setColumnStretch(0, 1)
        file_browse_layout.setColumnStretch(1, 0)
        margins = file_browse_layout.contentsMargins()
        file_browse_layout.setContentsMargins(margins.left(), 0,
                                              margins.right(), 0)

        file_layout.addRow("file:", file_widget)

        self.file_options.setVisible(
            self.structure_source.currentText() == "file")
        self.structure_source.currentTextChanged.connect(
            lambda text: self.file_options.setVisible(text == "file"))

        self.optimize_template = QCheckBox()
        self.optimize_template.setCheckState(Qt.Checked)
        structure_layout.addWidget(
            QLabel("optimize template:"),
            2,
            0,
            1,
            1,
            Qt.AlignLeft | Qt.AlignVCenter,
        )
        structure_layout.addWidget(
            self.optimize_template,
            2,
            1,
            1,
            2,
            Qt.AlignLeft | Qt.AlignVCenter,
        )

        structure_layout.setColumnStretch(0, 0)
        structure_layout.setColumnStretch(1, 1)
        structure_layout.setColumnStretch(2, 0)

        # structure changes
        changes_widget = QWidget()
        changes_layout = QGridLayout(changes_widget)
        tab_widget.addTab(changes_widget, "changes")

        # HPC settings
        hpc_widget = QWidget()
        hpc_layout = QGridLayout(hpc_widget)
        tab_widget.addTab(hpc_widget, "HPC")

        # theory settings
        theory_widget = QWidget()
        theory_layout = QGridLayout(theory_widget)
        tab_widget.addTab(theory_widget, "theory")

        # results
        results_widget = QWidget()
        results_layout = QGridLayout(results_widget)
        tab_widget.addTab(results_widget, "results")

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #15
0
class AutoRenameWidget(base.BaseWidget, object):
    def __init__(self, model, controller, parent=None):

        self._model = model
        self._controller = controller
        self._token_widgets = OrderedDict()

        super(AutoRenameWidget, self).__init__(parent=parent)

        self.refresh()

    def ui(self):
        super(AutoRenameWidget, self).ui()

        top_layout = layouts.HorizontalLayout(spacing=2, margins=(0, 0, 0, 0))
        self._unique_id_cbx = checkbox.BaseCheckBox('Unique Id')
        self._last_joint_end_cbx = checkbox.BaseCheckBox('Make Last Joint End')
        top_layout.addStretch()
        top_layout.addWidget(self._unique_id_cbx)
        top_layout.addWidget(self._last_joint_end_cbx)
        self.main_layout.addLayout(top_layout)

        main_splitter = QSplitter(Qt.Horizontal)
        main_splitter.setSizePolicy(QSizePolicy.Preferred,
                                    QSizePolicy.Expanding)
        self.main_layout.addWidget(main_splitter)

        auto_widget = QWidget()
        auto_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        auto_widget.setLayout(auto_layout)
        main_splitter.addWidget(auto_widget)

        self._rules_list = QTreeWidget(self)
        self._rules_list.setHeaderHidden(True)
        self._rules_list.setSortingEnabled(True)
        self._rules_list.setRootIsDecorated(False)
        self._rules_list.setSelectionMode(QAbstractItemView.SingleSelection)
        self._rules_list.sortByColumn(0, Qt.AscendingOrder)
        self._rules_list.setUniformRowHeights(True)
        self._rules_list.setAlternatingRowColors(True)

        auto_layout.addWidget(self._rules_list)

        auto_w = QWidget()
        self.auto_l = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        auto_w.setLayout(self.auto_l)
        auto_w.setMinimumWidth(200)
        main_splitter.addWidget(auto_w)

        self.main_auto_layout = QFormLayout()
        self.auto_l.addLayout(self.main_auto_layout)

        self._rename_btn = buttons.BaseButton('Rename')
        self._rename_btn.setIcon(resources.icon('rename'))
        self.main_layout.addLayout(dividers.DividerLayout())
        self.main_layout.addWidget(self._rename_btn)

    def setup_signals(self):
        self._unique_id_cbx.toggled.connect(
            self._controller.change_unique_id_auto)
        self._last_joint_end_cbx.toggled.connect(
            self._controller.change_last_joint_end_auto)
        self._rules_list.currentItemChanged.connect(
            self._controller.change_selected_rule)
        self._model.globalAttributeChanged.connect(
            self._on_updated_global_attribute)
        self._rename_btn.clicked.connect(self._on_rename)

        self._model.rulesChanged.connect(self._on_update_rules)
        self._model.activeRuleChanged.connect(self._on_update_active_rule)
        self._model.uniqueIdAutoChanged.connect(self._unique_id_cbx.setChecked)
        self._model.lastJointEndAutoChanged.connect(
            self._last_joint_end_cbx.setChecked)

    def refresh(self):
        self._unique_id_cbx.setChecked(self._model.unique_id_auto)
        self._last_joint_end_cbx.setChecked(self._model.last_joint_end_auto)
        self._update_global_attribute()

    def _add_token(self, token_name, line_layout):
        self.main_auto_layout.addRow(token_name, line_layout)

    def _update_global_attribute(self):
        self._global_attributes_dict = {
            'selection_type': self._model.selection_type,
            'filter_type': self._model.filter_type,
            'hierarchy_check': self._model.hierarchy_check,
            'rename_shape': self._model.rename_shape,
            'only_selection':
            True if self._model.selection_type == 0 else False
        }

    def _on_update_rules(self, new_rules):

        active_rule = self._model.active_rule
        item_to_select = None

        self._rules_list.clear()

        self._rules_list.blockSignals(True)
        try:
            for rule in new_rules:
                item = QTreeWidgetItem(self._rules_list, [rule.name])
                item.rule = rule
                self._rules_list.addTopLevelItem(item)
                self._rules_list.setCurrentItem(item)
                if active_rule and active_rule == rule.name:
                    item_to_select = item
                self._rules_list.setItemSelected(item, False)

            if item_to_select:
                self._rules_list.setItemSelected(item_to_select, True)
        except Exception as exc:
            LOGGER.error('{} | {}'.format(exc, traceback.format_exc()))
        finally:
            self._rules_list.blockSignals(False)

        self._on_update_active_rule(active_rule=self._model.active_rule)

    def _on_update_active_rule(self, active_rule):
        if not active_rule:
            return

        qtutils.clear_layout(self.main_auto_layout)

        if not active_rule:
            return

        tokens = self._model.tokens

        active_tokens = list()
        for field in active_rule.fields():
            for token in tokens:
                if token.name == field:
                    active_tokens.append(token)

        self._token_widgets.clear()

        for token in reversed(active_tokens):
            token_name = token.name
            token_value = token.get_items()
            token_default = token.default

            if token_name == 'id':
                continue

            if token_value:
                w = combobox.BaseComboBox(parent=self)
                w_l = label.BaseLabel(parent=self)
                w.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                w_l.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                self._add_token(
                    token_name,
                    qtutils.get_line_layout('', self, w, QLabel(u'\u25ba'),
                                            w_l))
                for key, value in token_value.items():
                    if key == 'default':
                        continue
                    w.addItem(key)
                try:
                    if token_default > 0:
                        w.setCurrentIndex(token_default - 1)
                except Exception:
                    w.setCurrentIndex(0)
                current_text = w.currentText()
                try:
                    current_value = token.solve(self._naming_lib.active_rule(),
                                                current_text)
                    w_l.setText(str(current_value))
                except Exception:
                    pass
                w.currentTextChanged.connect(
                    partial(self._on_combo_changed, token))
                self._token_widgets[token_name] = {
                    'widget': [w, w_l],
                    'fn': w.currentText
                }
            else:
                w = lineedit.BaseLineEdit(parent=self)
                # w.textChanged.connect(self._on_text_changed)
                w.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                self._token_widgets[token_name] = {'widget': [w], 'fn': w.text}
                self._add_token(token_name,
                                qtutils.get_line_layout('', self, w))

    def _on_combo_changed(self, token, text):
        active_rule = self._model.active_rule
        if not active_rule:
            return

        token_name = token.name
        if token_name not in self._token_widgets:
            return
        token_widgets = self._token_widgets[token_name]['widget']
        try:
            current_value = token.solve(active_rule, text)
            token_widgets[1].setText(str(current_value))
        except Exception:
            pass
        # self.renameUpdated.emit()

#     def _on_text_changed(self, text):
#         self.renameUpdated.emit()

    def _on_updated_global_attribute(self):
        self._update_global_attribute()

    def _on_rename(self):

        tokens_dict = dict()
        for token_name, token_data in self._token_widgets.items():
            token_value_fn = token_data['fn']
            token_value = token_value_fn()
            tokens_dict[token_name] = token_value

        unique_id = self._model.unique_id_auto
        last_joint_end = self._model.last_joint_end_auto

        return self._controller.auto_rename(tokens_dict,
                                            unique_id=unique_id,
                                            last_joint_end=last_joint_end)
Beispiel #16
0
    def _build_ui(self):
        layout = QGridLayout()

        tabs = QTabWidget()
        calc_widget = QWidget()
        calc_layout = QFormLayout(calc_widget)
        settings_widget = QWidget()
        settings_layout = QFormLayout(settings_widget)
        steric_map_widget = QWidget()
        steric_layout = QFormLayout(steric_map_widget)
        cutout_widget = QWidget()
        vol_cutout_layout = QFormLayout(cutout_widget)
        layout.addWidget(tabs)

        tabs.addTab(calc_widget, "calculation")
        tabs.addTab(settings_widget, "settings")
        tabs.addTab(steric_map_widget, "steric map")
        tabs.addTab(cutout_widget, "volume cutout")

        self.radii_option = QComboBox()
        self.radii_option.addItems(["Bondi", "UMN"])
        ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly)
        self.radii_option.setCurrentIndex(ndx)
        settings_layout.addRow("radii:", self.radii_option)

        self.scale = QDoubleSpinBox()
        self.scale.setValue(self.settings.vdw_scale)
        self.scale.setSingleStep(0.01)
        self.scale.setRange(1., 1.5)
        settings_layout.addRow("VDW scale:", self.scale)

        set_ligand_atoms = QPushButton("set ligands to current selection")
        set_ligand_atoms.clicked.connect(self.set_ligand_atoms)
        set_ligand_atoms.setToolTip(
            "specify atoms to use in calculation\n" +
            "by default, all atoms will be used unless a single center is specified\n"
            +
            "in the case of a single center, all atoms except the center is used"
        )
        calc_layout.addRow(set_ligand_atoms)
        self.set_ligand_atoms = set_ligand_atoms

        self.radius = QDoubleSpinBox()
        self.radius.setValue(self.settings.center_radius)
        self.radius.setSuffix(" \u212B")
        self.radius.setDecimals(1)
        self.radius.setSingleStep(0.1)
        self.radius.setRange(1., 15.)
        settings_layout.addRow("radius around center:", self.radius)

        self.method = QComboBox()
        self.method.addItems(["Lebedev", "Monte-Carlo"])
        self.method.setToolTip("Lebedev: deterministic method\n" +
                               "Monte-Carlo: non-deterministic method")
        ndx = self.method.findText(self.settings.method, Qt.MatchExactly)
        self.method.setCurrentIndex(ndx)
        settings_layout.addRow("integration method:", self.method)

        leb_widget = QWidget()
        leb_layout = QFormLayout(leb_widget)
        leb_layout.setContentsMargins(0, 0, 0, 0)

        self.radial_points = QComboBox()
        self.radial_points.addItems(["20", "32", "64", "75", "99", "127"])
        self.radial_points.setToolTip(
            "more radial points will give more accurate results, but integration will take longer"
        )
        ndx = self.radial_points.findText(self.settings.radial_points,
                                          Qt.MatchExactly)
        self.radial_points.setCurrentIndex(ndx)
        leb_layout.addRow("radial points:", self.radial_points)

        self.angular_points = QComboBox()
        self.angular_points.addItems([
            "110", "194", "302", "590", "974", "1454", "2030", "2702", "5810"
        ])
        self.angular_points.setToolTip(
            "more angular points will give more accurate results, but integration will take longer"
        )
        ndx = self.angular_points.findText(self.settings.angular_points,
                                           Qt.MatchExactly)
        self.angular_points.setCurrentIndex(ndx)
        leb_layout.addRow("angular points:", self.angular_points)

        settings_layout.addRow(leb_widget)

        mc_widget = QWidget()
        mc_layout = QFormLayout(mc_widget)
        mc_layout.setContentsMargins(0, 0, 0, 0)

        self.min_iter = QSpinBox()
        self.min_iter.setValue(self.settings.minimum_iterations)
        self.min_iter.setRange(0, 10000)
        self.min_iter.setToolTip(
            "each iteration is 3000 points\n" +
            "iterations continue until convergence criteria are met")
        mc_layout.addRow("minimum interations:", self.min_iter)

        settings_layout.addRow(mc_widget)

        if self.settings.method == "Lebedev":
            mc_widget.setVisible(False)
        elif self.settings.method == "Monte-Carlo":
            leb_widget.setVisible(False)

        self.report_component = QComboBox()
        self.report_component.addItems(["total", "quadrants", "octants"])
        ndx = self.report_component.findText(self.settings.report_component,
                                             Qt.MatchExactly)
        self.report_component.setCurrentIndex(ndx)
        settings_layout.addRow("report volume:", self.report_component)

        self.use_scene = QCheckBox()
        self.use_scene.setChecked(self.settings.use_scene)
        self.use_scene.setToolTip(
            "quadrants/octants will use the orientation the molecule is displayed in"
        )
        settings_layout.addRow("use display orientation:", self.use_scene)

        self.method.currentTextChanged.connect(
            lambda text, widget=leb_widget: widget.setVisible(text == "Lebedev"
                                                              ))
        self.method.currentTextChanged.connect(
            lambda text, widget=mc_widget: widget.setVisible(text ==
                                                             "Monte-Carlo"))

        self.use_centroid = QCheckBox()
        self.use_centroid.setChecked(self.settings.use_centroid)
        self.use_centroid.setToolTip(
            "place the center between selected atoms\n" +
            "might be useful for polydentate ligands")
        calc_layout.addRow("use centroid of centers:", self.use_centroid)

        self.steric_map = QCheckBox()
        self.steric_map.setChecked(self.settings.steric_map)
        self.steric_map.setToolTip(
            "produce a 2D projection of steric bulk\ncauses buried volume to be reported for individual quadrants"
        )
        steric_layout.addRow("create steric map:", self.steric_map)

        self.num_pts = QSpinBox()
        self.num_pts.setRange(25, 250)
        self.num_pts.setValue(self.settings.num_pts)
        self.num_pts.setToolTip("number of points along x and y axes")
        steric_layout.addRow("number of points:", self.num_pts)

        self.include_vbur = QCheckBox()
        self.include_vbur.setChecked(self.settings.include_vbur)
        steric_layout.addRow("label quadrants with %V<sub>bur</sub>",
                             self.include_vbur)

        self.map_shape = QComboBox()
        self.map_shape.addItems(["circle", "square"])
        ndx = self.map_shape.findText(self.settings.map_shape, Qt.MatchExactly)
        self.map_shape.setCurrentIndex(ndx)
        steric_layout.addRow("map shape:", self.map_shape)

        self.auto_minmax = QCheckBox()
        self.auto_minmax.setChecked(self.settings.auto_minmax)
        steric_layout.addRow("automatic min. and max.:", self.auto_minmax)

        self.map_min = QDoubleSpinBox()
        self.map_min.setRange(-15., 0.)
        self.map_min.setSuffix(" \u212B")
        self.map_min.setSingleStep(0.1)
        self.map_min.setValue(self.settings.map_min)
        steric_layout.addRow("minimum value:", self.map_min)

        self.map_max = QDoubleSpinBox()
        self.map_max.setRange(0., 15.)
        self.map_max.setSuffix(" \u212B")
        self.map_max.setSingleStep(0.1)
        self.map_max.setValue(self.settings.map_max)
        steric_layout.addRow("maximum value:", self.map_max)

        self.num_pts.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.num_pts: widget.setEnabled(state == Qt.
                                                                 Checked))

        self.include_vbur.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.include_vbur: widget.setEnabled(
                state == Qt.Checked))

        self.map_shape.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.map_shape: widget.setEnabled(state == Qt.
                                                                   Checked))

        self.auto_minmax.setEnabled(self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.auto_minmax: widget.setEnabled(
                state == Qt.Checked))

        self.map_min.setEnabled(not self.settings.auto_minmax
                                and self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.map_min, widget2=self.auto_minmax: widget
            .setEnabled(state == Qt.Checked and not widget2.isChecked()))
        self.auto_minmax.stateChanged.connect(
            lambda state, widget=self.map_min, widget2=self.steric_map: widget.
            setEnabled(not state == Qt.Checked and widget2.isChecked()))

        self.map_max.setEnabled(not self.settings.auto_minmax
                                and self.settings.steric_map)
        self.steric_map.stateChanged.connect(
            lambda state, widget=self.map_max, widget2=self.auto_minmax: widget
            .setEnabled(state == Qt.Checked and not widget2.isChecked()))
        self.auto_minmax.stateChanged.connect(
            lambda state, widget=self.map_max, widget2=self.steric_map: widget.
            setEnabled(not state == Qt.Checked and widget2.isChecked()))

        self.display_cutout = QComboBox()
        self.display_cutout.addItems(["no", "free", "buried"])
        ndx = self.display_cutout.findText(self.settings.display_cutout,
                                           Qt.MatchExactly)
        self.display_cutout.setCurrentIndex(ndx)
        self.display_cutout.setToolTip("show free or buried volume")
        vol_cutout_layout.addRow("display volume:", self.display_cutout)

        self.point_spacing = QDoubleSpinBox()
        self.point_spacing.setDecimals(3)
        self.point_spacing.setRange(0.01, 0.5)
        self.point_spacing.setSingleStep(0.005)
        self.point_spacing.setSuffix(" \u212B")
        self.point_spacing.setValue(self.settings.point_spacing)
        self.point_spacing.setToolTip(
            "distance between points on cutout\n" +
            "smaller spacing will narrow gaps, but increase time to create the cutout"
        )
        vol_cutout_layout.addRow("point spacing:", self.point_spacing)

        self.intersection_scale = QDoubleSpinBox()
        self.intersection_scale.setDecimals(2)
        self.intersection_scale.setRange(1., 10.)
        self.intersection_scale.setSingleStep(0.5)
        self.intersection_scale.setSuffix("x")
        self.intersection_scale.setToolTip(
            "relative density of points where VDW radii intersect\n" +
            "higher density will narrow gaps, but increase time to create cutout"
        )
        self.intersection_scale.setValue(self.settings.intersection_scale)
        vol_cutout_layout.addRow("intersection density:",
                                 self.intersection_scale)

        self.cutout_labels = QComboBox()
        self.cutout_labels.addItems(["none", "quadrants", "octants"])
        ndx = self.cutout_labels.findText(self.settings.cutout_labels,
                                          Qt.MatchExactly)
        self.cutout_labels.setCurrentIndex(ndx)
        vol_cutout_layout.addRow("label sections:", self.cutout_labels)

        self.point_spacing.setEnabled(self.settings.display_cutout != "no")
        self.intersection_scale.setEnabled(
            self.settings.display_cutout != "no")
        self.cutout_labels.setEnabled(self.settings.display_cutout != "no")

        self.display_cutout.currentTextChanged.connect(
            lambda text, widget=self.point_spacing: widget.setEnabled(text !=
                                                                      "no"))
        self.display_cutout.currentTextChanged.connect(
            lambda text, widget=self.intersection_scale: widget.setEnabled(
                text != "no"))
        self.display_cutout.currentTextChanged.connect(
            lambda text, widget=self.cutout_labels: widget.setEnabled(text !=
                                                                      "no"))

        calc_vbur_button = QPushButton(
            "calculate % buried volume for selected centers")
        calc_vbur_button.clicked.connect(self.calc_vbur)
        calc_layout.addRow(calc_vbur_button)
        self.calc_vbur_button = calc_vbur_button

        remove_vbur_button = QPushButton(
            "remove % buried volume visualizations")
        remove_vbur_button.clicked.connect(self.del_vbur)
        vol_cutout_layout.addRow(remove_vbur_button)

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(['model', 'center', '%Vbur'])
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.resizeColumnToContents(0)
        self.table.resizeColumnToContents(1)
        self.table.resizeColumnToContents(2)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Interactive)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Interactive)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Stretch)
        calc_layout.addRow(self.table)

        menu = QMenuBar()

        export = menu.addMenu("&Export")

        clear = QAction("Clear data table", self.tool_window.ui_area)
        clear.triggered.connect(self.clear_table)
        export.addAction(clear)

        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)
        self.copy = copy

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)
        menu.setVisible(True)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #17
0
    def _build_ui(self):
        layout = QGridLayout()

        library_tabs = QTabWidget()

        #ligand tab
        ligand_tab = QWidget()
        ligand_layout = QFormLayout(ligand_tab)

        self.ligand_name = QLineEdit()
        self.ligand_name.setText("")
        self.ligand_name.setPlaceholderText("leave blank to preview")
        self.ligand_name.setToolTip(
            "name of ligand you are adding to your ligand library\nleave blank to open a new model with just the ligand"
        )
        ligand_layout.addRow("ligand name:", self.ligand_name)

        ligand_key_atoms = QPushButton("set key atoms to current selection")
        ligand_key_atoms.clicked.connect(self.update_key_atoms)
        ligand_key_atoms.setToolTip(
            "the current selection will be the key atoms for the ligand\nleave blank to automatically determine key atoms"
        )
        ligand_layout.addRow(ligand_key_atoms)

        libadd_ligand = QPushButton("add current selection to library")
        libadd_ligand.clicked.connect(self.libadd_ligand)
        ligand_layout.addRow(libadd_ligand)

        #substituent tab
        sub_tab = QWidget()
        sub_layout = QFormLayout(sub_tab)

        self.sub_name = QLineEdit()
        self.sub_name.setText("")
        self.sub_name.setPlaceholderText("leave blank to preview")
        self.sub_name.setToolTip(
            "name of substituent you are adding to your substituent library\nleave blank to open a new model with just the substituent"
        )
        sub_layout.addRow("substituent name:", self.sub_name)

        self.sub_confs = QSpinBox()
        self.sub_confs.setMinimum(1)
        sub_layout.addRow("number of conformers:", self.sub_confs)

        self.sub_angle = QSpinBox()
        self.sub_angle.setRange(0, 180)
        self.sub_angle.setSingleStep(30)
        sub_layout.addRow("angle between conformers:", self.sub_angle)

        libadd_sub = QPushButton("add current selection to library")
        libadd_sub.clicked.connect(self.libadd_substituent)
        sub_layout.addRow(libadd_sub)

        #ring tab
        ring_tab = QWidget()
        ring_layout = QFormLayout(ring_tab)

        self.ring_name = QLineEdit()
        self.ring_name.setText("")
        self.ring_name.setPlaceholderText("leave blank to preview")
        self.ring_name.setToolTip(
            "name of ring you are adding to your ring library\nleave blank to open a new model with just the ring"
        )
        ring_layout.addRow("ring name:", self.ring_name)

        libadd_ring = QPushButton("add ring with selected walk to library")
        libadd_ring.clicked.connect(self.libadd_ring)
        ring_layout.addRow(libadd_ring)

        library_tabs.addTab(sub_tab, "substituent")
        library_tabs.addTab(ring_tab, "ring")
        library_tabs.addTab(ligand_tab, "ligand")
        self.library_tabs = library_tabs

        layout.addWidget(library_tabs)

        whats_this = QLabel()
        whats_this.setText(
            "<a href=\"req\" style=\"text-decoration: none;\">what's this?</a>"
        )
        whats_this.setTextFormat(Qt.RichText)
        whats_this.setTextInteractionFlags(Qt.TextBrowserInteraction)
        whats_this.linkActivated.connect(self.open_link)
        whats_this.setToolTip(
            "click for more information about AaronTools libraries")
        layout.addWidget(whats_this)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
def create_coord_items(tool, layout, allow_minimization=True, default_ele="Ca"):
    """
    add widgets to the layout and set appropriate attributes for tool
    this is used by this tool and the AaronJr input builder
    """
    tool.element = ElementButton(default_ele, single_state=True)
    tool.element.clicked.connect(lambda *args, t=tool: open_ptable(t))
    layout.addRow("element:", tool.element)

    tool.vsepr = QComboBox()
    tool.vsepr.addItems([
        "trigonal pyramidal",             # 1
        "tetrahedral",                    # 2
        "seesaw",                         # 3
        "square planar",                  # 4
        
        "trigonal bipyramidal",           # 5
        "square pyramidal",               # 6
        "pentagonal",                     # 7
        
        "octahedral",                     # 8
        "hexagonal",                      # 9
        "trigonal prismatic",             #10
        "pentagonal pyramidal",           #11
        
        "capped octahedral",              #12
        "capped trigonal prismatic",      #13
        "heptagonal",                     #14
        "hexagonal pyramidal",            #15
        "pentagonal bipyramidal",         #16
    ])
    
    tool.vsepr.setCurrentIndex(7)
    
    tool.vsepr.insertSeparator(11)
    tool.vsepr.insertSeparator(7)
    tool.vsepr.insertSeparator(4)
    layout.addRow("geometry:", tool.vsepr)
    
    if allow_minimization:
        tool.minimize = QCheckBox()
        tool.minimize.setCheckState(Qt.Checked)
        tool.minimize.setToolTip("rotate substituents on ligands to mitigate steric clashing")
        layout.addRow("relax ligands:", tool.minimize)
    
    ligand_box = QGroupBox("ligands")
    ligand_layout = QFormLayout(ligand_box)
    layout.addRow(ligand_box)
    
    tool.ligand_table = QTableWidget()
    tool.ligand_table.setColumnCount(3)
    tool.ligand_table.setHorizontalHeaderLabels(["name", "C\u2082-symmetric", "remove"])
    tool.ligand_table.cellClicked.connect(
        lambda row, column, t=tool:ligand_table_clicked(t, row, column)
    )
    tool.ligand_table.setEditTriggers(QTableWidget.NoEditTriggers)
    add_ligand(tool)
    tool.ligand_table.resizeColumnToContents(0)
    tool.ligand_table.resizeColumnToContents(1)
    tool.ligand_table.resizeColumnToContents(2)
    tool.ligand_table.horizontalHeader().setStretchLastSection(False)
    tool.ligand_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
    tool.ligand_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Fixed)
    tool.ligand_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.Fixed)
    ligand_layout.addRow(tool.ligand_table)
Beispiel #19
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)
Beispiel #20
0
    def _build_ui(self):
        layout = QFormLayout()

        initial_elements = []
        if ChangeElementMouseMode.element:
            initial_elements = [ChangeElementMouseMode.element]
        else:
            initial_elements = ["C"]

        self.periodic_table = PeriodicTable(select_multiple=False,
                                            initial_elements=initial_elements)
        self.periodic_table.elementSelectionChanged.connect(
            self.element_changed)
        layout.addRow(self.periodic_table)

        self.vsepr = QComboBox()
        self.vsepr.addItems([
            "do not change",  # 0
            "linear (1 bond)",  # 1
            "linear (2 bonds)",  # 2 
            "trigonal planar (2 bonds)",  # 3
            "tetrahedral (2 bonds)",  # 4 
            "trigonal planar",  # 5
            "tetrahedral (3 bonds)",  # 6
            "T-shaped",  # 7
            "trigonal pyramidal",  # 8
            "tetrahedral",  # 9
            "sawhorse",  #10
            "seesaw",  #11
            "square planar",  #12
            "trigonal bipyramidal",  #13
            "square pyramidal",  #14
            "pentagonal",  #15
            "octahedral",  #16
            "hexagonal",  #17
            "trigonal prismatic",  #18
            "pentagonal pyramidal",  #19
            "capped octahedral",  #20
            "capped trigonal prismatic",  #21
            "heptagonal",  #22
            "hexagonal pyramidal",  #23
            "pentagonal bipyramidal",  #24
            "biaugmented trigonal prismatic",  #25
            "cubic",  #26
            "elongated trigonal bipyramidal",  #27
            "hexagonal bipyramidal",  #28
            "heptagonal pyramidal",  #29
            "octagonal",  #30
            "square antiprismatic",  #31
            "trigonal dodecahedral",  #32
            "capped cube",  #33
            "capped square antiprismatic",  #34
            "enneagonal",  #35
            "heptagonal bipyramidal",  #36
            "hula-hoop",  #37
            "triangular cupola",  #38
            "tridiminished icosahedral",  #39
            "muffin",  #40
            "octagonal pyramidal",  #41
            "tricapped trigonal prismatic",  #42
        ])
        self.vsepr.setCurrentIndex(9)

        self.vsepr.insertSeparator(33)
        self.vsepr.insertSeparator(25)
        self.vsepr.insertSeparator(20)
        self.vsepr.insertSeparator(16)
        self.vsepr.insertSeparator(13)
        self.vsepr.insertSeparator(8)
        self.vsepr.insertSeparator(5)
        self.vsepr.insertSeparator(2)
        self.vsepr.insertSeparator(1)
        self.vsepr.insertSeparator(0)
        self.vsepr.currentTextChanged.connect(self.element_changed)
        layout.addRow("shape:", self.vsepr)

        self.keep_open = QCheckBox()
        layout.addRow("keep table open:", self.keep_open)

        if ChangeElementMouseMode.vsepr:
            ndx = self.vsepr.findText(ChangeElementMouseMode.vsepr,
                                      Qt.MatchExactly)
            if ndx != -1:
                self.vsepr.setCurrentIndex(ndx)

        do_it = QPushButton("set element and shape")
        do_it.clicked.connect(self.set_selected)
        layout.addRow(do_it)

        self.keep_open.stateChanged.connect(
            lambda state: do_it.setVisible(state != Qt.Checked))
        self.keep_open.stateChanged.connect(self.element_changed)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #21
0
    def _build_ui(self):
        layout = QFormLayout()

        self.cone_option = QComboBox()
        self.cone_option.addItems(["Tolman (Unsymmetrical)", "Exact"])
        ndx = self.cone_option.findText(self.settings.cone_option,
                                        Qt.MatchExactly)
        self.cone_option.setCurrentIndex(ndx)
        layout.addRow("method:", self.cone_option)

        self.radii_option = QComboBox()
        self.radii_option.addItems(["Bondi", "UMN"])
        ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly)
        self.radii_option.setCurrentIndex(ndx)
        layout.addRow("radii:", self.radii_option)

        self.display_cone = QCheckBox()
        self.display_cone.setChecked(self.settings.display_cone)
        layout.addRow("show cone:", self.display_cone)

        self.display_radii = QCheckBox()
        self.display_radii.setChecked(self.settings.display_radii)
        layout.addRow("show radii:", self.display_radii)

        set_ligand_button = QPushButton("set ligand to current selection")
        set_ligand_button.clicked.connect(self.set_ligand)
        layout.addRow(set_ligand_button)
        self.set_ligand_button = set_ligand_button

        calc_cone_button = QPushButton(
            "calculate cone angle for ligand on selected center")
        calc_cone_button.clicked.connect(self.calc_cone)
        layout.addRow(calc_cone_button)
        self.calc_cone_button = calc_cone_button

        remove_cone_button = QPushButton("remove cone visualizations")
        remove_cone_button.clicked.connect(self.del_cone)
        layout.addRow(remove_cone_button)
        self.remove_cone_button = remove_cone_button

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels([
            'model',
            'center',
            'cone angle (°)',
        ])

        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.resizeColumnToContents(0)
        self.table.resizeColumnToContents(1)
        self.table.resizeColumnToContents(2)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Stretch)
        layout.addRow(self.table)

        menu = QMenuBar()

        export = menu.addMenu("&Export")

        clear = QAction("Clear data table", self.tool_window.ui_area)
        clear.triggered.connect(self.clear_table)
        export.addAction(clear)

        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)
        menu.setVisible(True)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)
Beispiel #22
0
    def _build_ui(self):
        layout = QFormLayout()

        self.radii_option = QComboBox()
        self.radii_option.addItems(["Bondi", "UMN"])
        ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly)
        self.radii_option.setCurrentIndex(ndx)
        layout.addRow("radii:", self.radii_option)

        self.L_style = QComboBox()
        self.L_style.addItems(["FORTRAN", "AaronTools"])
        ndx = self.L_style.findText(self.settings.L_style, Qt.MatchExactly)
        self.L_style.setCurrentIndex(ndx)
        self.L_style.setToolTip(
            """FORTRAN: Add 0.4 + the ideal X-H bond length to the length
of the substituent
AaronTools: add VDW radius to the length of the substituent""")
        layout.addRow("L correction:", self.L_style)

        self.display_vectors = QCheckBox()
        self.display_vectors.setChecked(self.settings.display_vectors)
        layout.addRow("show vectors:", self.display_vectors)

        self.display_radii = QCheckBox()
        self.display_radii.setChecked(self.settings.display_radii)
        layout.addRow("show radii:", self.display_radii)

        calc_sterimol_button = QPushButton(
            "calculate parameters for selected substituents")
        calc_sterimol_button.clicked.connect(self.calc_sterimol)
        layout.addRow(calc_sterimol_button)
        self.calc_sterimol_button = calc_sterimol_button

        remove_sterimol_button = QPushButton("remove Sterimol visualizations")
        remove_sterimol_button.clicked.connect(self.del_sterimol)
        layout.addRow(remove_sterimol_button)
        self.remove_sterimol_button = remove_sterimol_button

        self.table = QTableWidget()
        self.table.setColumnCount(8)
        self.table.setHorizontalHeaderLabels([
            'model',
            'substituent atom',
            'B\u2081',
            'B\u2082',
            'B\u2083',
            'B\u2084',
            'B\u2085',
            'L',
        ])
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.resizeColumnToContents(0)
        self.table.resizeColumnToContents(1)
        self.table.resizeColumnToContents(2)
        self.table.resizeColumnToContents(3)
        self.table.resizeColumnToContents(4)
        self.table.resizeColumnToContents(5)
        self.table.resizeColumnToContents(6)
        self.table.resizeColumnToContents(7)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            3, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            4, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            5, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            6, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            7, QHeaderView.Stretch)
        layout.addRow(self.table)

        menu = QMenuBar()

        export = menu.addMenu("&Export")

        clear = QAction("Clear data table", self.tool_window.ui_area)
        clear.triggered.connect(self.clear_table)
        export.addAction(clear)

        copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area)
        copy.triggered.connect(self.copy_csv)
        shortcut = QKeySequence(Qt.CTRL + Qt.Key_C)
        copy.setShortcut(shortcut)
        export.addAction(copy)

        save = QAction("&Save CSV...", self.tool_window.ui_area)
        save.triggered.connect(self.save_csv)
        #this shortcut interferes with main window's save shortcut
        #I've tried different shortcut contexts to no avail
        #thanks Qt...
        #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S)
        #save.setShortcut(shortcut)
        #save.setShortcutContext(Qt.WidgetShortcut)
        export.addAction(save)

        delimiter = export.addMenu("Delimiter")

        comma = QAction("comma", self.tool_window.ui_area, checkable=True)
        comma.setChecked(self.settings.delimiter == "comma")
        comma.triggered.connect(lambda *args, delim="comma": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(comma)

        tab = QAction("tab", self.tool_window.ui_area, checkable=True)
        tab.setChecked(self.settings.delimiter == "tab")
        tab.triggered.connect(lambda *args, delim="tab": self.settings.
                              __setattr__("delimiter", delim))
        delimiter.addAction(tab)

        space = QAction("space", self.tool_window.ui_area, checkable=True)
        space.setChecked(self.settings.delimiter == "space")
        space.triggered.connect(lambda *args, delim="space": self.settings.
                                __setattr__("delimiter", delim))
        delimiter.addAction(space)

        semicolon = QAction("semicolon",
                            self.tool_window.ui_area,
                            checkable=True)
        semicolon.setChecked(self.settings.delimiter == "semicolon")
        semicolon.triggered.connect(lambda *args, delim="semicolon": self.
                                    settings.__setattr__("delimiter", delim))
        delimiter.addAction(semicolon)

        add_header = QAction("&Include CSV header",
                             self.tool_window.ui_area,
                             checkable=True)
        add_header.setChecked(self.settings.include_header)
        add_header.triggered.connect(self.header_check)
        export.addAction(add_header)

        comma.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        comma.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        tab.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=space: action.setChecked(False))
        tab.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        space.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        space.triggered.connect(
            lambda *args, action=semicolon: action.setChecked(False))

        semicolon.triggered.connect(
            lambda *args, action=comma: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=tab: action.setChecked(False))
        semicolon.triggered.connect(
            lambda *args, action=space: action.setChecked(False))

        menu.setNativeMenuBar(False)
        self._menu = menu
        layout.setMenuBar(menu)
        menu.setVisible(True)

        self.tool_window.ui_area.setLayout(layout)

        self.tool_window.manage(None)