def file_fetch_pdb(parent): form = parent.load_form('fetch') form.input_assembly.setEditText(parent.cmd.get('assembly')) def get_command(*args): code = form.input_code.text() if len(code) != 4: return '' def get_name(w): name = w.text() if name: return ', ' + name return '' if form.input_check_pdb.isChecked(): command = 'set assembly, "%s"\nfetch %s%s%s' % ( form.input_assembly.currentText(), code, form.input_chain.currentText(), get_name(form.input_name)) else: command = '' if form.input_check_2fofc.isChecked(): command += '\nfetch %s%s, type=2fofc' % ( code, get_name(form.input_name_2fofc)) if form.input_check_fofc.isChecked(): command += '\nfetch %s%s, type=fofc' % ( code, get_name(form.input_name_fofc)) return command def update_output_command(*args): form.output_command.setText(get_command()) def code_changed(code): for combo in [form.input_assembly, form.input_chain]: if combo.count() != 1: text = combo.currentText() combo.clear() combo.addItem('') combo.setEditText(text) if len(code) == 4: update_assemblies(code) update_chains(code) update_output_command() def run(): if len(form.input_code.text()) != 4: QtWidgets.QMessageBox.warning(parent, "Error", "Need 4 letter PDB code") return parent.cmd.do(get_command()) form._dialog.close() # async events update_assemblies = AsyncFunc(_get_assemblies, form.input_assembly.addItems) update_chains = AsyncFunc(_get_chains, form.input_chain.addItems) # hook up events form.input_code.textChanged.connect(code_changed) form.input_chain.editTextChanged.connect(update_output_command) form.input_assembly.editTextChanged.connect(update_output_command) form.input_name.textChanged.connect(update_output_command) form.input_name_2fofc.textChanged.connect(update_output_command) form.input_name_fofc.textChanged.connect(update_output_command) form.input_check_pdb.stateChanged.connect(update_output_command) form.input_check_2fofc.stateChanged.connect(update_output_command) form.input_check_fofc.stateChanged.connect(update_output_command) form.button_ok.clicked.connect(run) update_output_command() form._dialog.show()
def dialog(_self=None): if _self is None: from pymol import cmd as _self dialog = QtWidgets.QDialog() uifile = os.path.join(os.path.dirname(__file__), 'apbs.ui') form = loadUi(uifile, dialog) form._dialog = dialog form._proclist = [] def set_apbs_in(contents): form.apbs_template.setPlainText(contents.strip()) # hide options widgets form.optarea_prep.setVisible(False) form.optarea_apbs.setVisible(False) form.optarea_surf.setVisible(False) form.optarea_other.setVisible(False) # pre-fill form with likely data names = _self.get_object_list() names += ['(' + n + ')' for n in _self.get_names('public_selections')] if names: form.input_sele.clear() form.input_sele.addItems([ ('polymer & ' + name) if _self.count_atoms('polymer & ' + name) > 0 else name for name in names ]) form.surf_map.addItems(_self.get_names_of_type('object:map')) set_apbs_in(electrostatics.template_apbs_in) # executables from distutils.spawn import find_executable form.apbs_exe.setText(electrostatics.find_apbs_exe() or 'apbs') form.pdb2pqr_exe.setText( find_executable('pdb2pqr') or # acellera::htmd-pdb2pqr provides pdb2pqr_cli find_executable('pdb2pqr_cli') or find_executable( 'share/pdb2pqr/pdb2pqr.py', os.getenv('FREEMOL', '/usr')) or 'pdb2pqr') # for async panels form._callInMainThread = MainThreadCaller() run_impl_async = AsyncFunc(run_impl) # "Run" button callback def run(): form.tabWidget.setEnabled(False) form.button_ok.clicked.disconnect() form.button_ok.clicked.connect(abort) form.button_ok.setText('Abort') form._capture = StdOutCapture() # detach from main thread run_impl_async(form, _self) # "Run" button "finally" actions (main thread) @run_impl_async.finished.connect def run_finally(args): _, exception = args form._proclist[:] = [] stdout = form._capture.release() print(stdout) form.button_ok.setText('Run') form.button_ok.clicked.disconnect() form.button_ok.clicked.connect(run) form.button_ok.setEnabled(True) form.tabWidget.setEnabled(True) if exception is not None: handle_exception(exception, stdout) return quit_msg = "Finished with Success. Close the APBS dialog?" if QMessageBox.Yes == QMessageBox.question(form._dialog, 'Finished', quit_msg, QMessageBox.Yes, QMessageBox.No): form._dialog.close() def handle_exception(e, stdout): if isinstance(e, SilentAbort): return msg = str(e) or 'unknown error' msgbox = QMessageBox(QMessageBox.Critical, 'Error', msg, QMessageBox.Close, form._dialog) if stdout.strip(): msgbox.setDetailedText(stdout) msgbox.exec_() # "Abort" button callback def abort(): form.button_ok.setEnabled(False) while form._proclist: p = form._proclist.pop() try: p.terminate() p.returncode = -15 # SIGTERM except OSError as e: print(e) # selection checker check_sele_timer = QtCore.QTimer() check_sele_timer.setSingleShot(True) # grid auto-value form.apbs_grid_userchanged = False form.apbs_grid.setStyleSheet('background: #ff6') @form.apbs_grid.editingFinished.connect def _(): form.apbs_grid_userchanged = True form.apbs_grid.setStyleSheet('') @check_sele_timer.timeout.connect def _(): has_props = ['no', 'no'] def callback(partial_charge, elec_radius): if partial_charge: has_props[0] = 'YES' if elec_radius > 0: has_props[1] = 'YES' n = _self.iterate(form.input_sele.currentText(), 'callback(partial_charge, elec_radius)', space={'callback': callback}) # grid auto-value (keep map size in the order of 200x200x200) if n > 1 and not form.apbs_grid_userchanged: e = _self.get_extent(form.input_sele.currentText()) volume = (e[1][0] - e[0][0]) * (e[1][1] - e[0][1]) * (e[1][2] - e[0][2]) grid = max(0.5, volume**0.333 / 200.0) form.apbs_grid.setValue(grid) if n < 1: label = 'Selection is invalid' color = '#f66' elif has_props == ['YES', 'YES']: label = 'No preparation necessary, selection has charges and radii' form.do_prepare.setChecked(False) color = '#6f6' else: label = 'Selection needs preparation (partial_charge: %s, elec_radius: %s)' % tuple( has_props) form.do_prepare.setChecked(True) color = '#fc6' form.label_sele_has.setText(label) form.label_sele_has.setStyleSheet('background: %s; padding: 5' % color) check_sele_timer.start(0) @form.apbs_exe_browse.clicked.connect def _(): fnames = getOpenFileNames(None, filter='apbs (apbs*);;All Files (*)')[0] if fnames: form.apbs_exe.setText(fnames[0]) @form.pdb2pqr_exe_browse.clicked.connect def _(): fnames = getOpenFileNames( None, filter='pdb2pqr (pdb2pqr*);;All Files (*)')[0] if fnames: form.pdb2pqr_exe.setText(fnames[0]) # hook up events form.input_sele.currentIndexChanged.connect( lambda: check_sele_timer.start(0)) form.input_sele.editTextChanged.connect( lambda: check_sele_timer.start(1000)) form.button_ok.clicked.connect(run) # "Register" opens a web browser @form.button_register.clicked.connect def _(): import webbrowser webbrowser.open("http://www.poissonboltzmann.org/") @form.button_load.clicked.connect def _(): fnames = getOpenFileNames(None, filter='APBS Input (*.in);;All Files (*)')[0] if fnames: contents = load_apbs_in(form, fnames[0]) set_apbs_in(contents) @form.button_reset.clicked.connect def _(): set_apbs_in(electrostatics.template_apbs_in) form._dialog.show() form._dialog.resize(500, 600)