def __init__(self, session, tool_name): # Standard template stuff for intializing tool super().__init__(session, tool_name) from chimerax.core.ui.gui import MainToolWindow self.tool_window = MainToolWindow(self) self.tool_window.manage(placement="side") parent = self.tool_window.ui_area # Create an HTML viewer for our user interface. # We can include other Qt widgets if we want to. from PyQt5.QtWidgets import QGridLayout from chimerax.core.ui.widgets import HtmlView layout = QGridLayout() self.html_view = HtmlView(parent, size_hint=(575, 200), interceptor=self._navigate, schemes=[self.CUSTOM_SCHEME]) layout.addWidget(self.html_view, 0, 0) # row 0, column 0 parent.setLayout(layout) # Register for model addition/removal so we can update model list from chimerax.core.models import ADD_MODELS, REMOVE_MODELS t = session.triggers self._add_handler = t.add_handler(ADD_MODELS, self._update_models) self._remove_handler = t.add_handler(REMOVE_MODELS, self._update_models) # Go! self._update_models()
def __init__(self, session, tool_name): ToolInstance.__init__(self, session, tool_name) # FIXME: display_name' defaults to class name with spaces inserted # between lower-then-upper-case characters (therefore "Tool UI" # in this case), so only override if different name desired self.display_name = "custom name for running tool" from chimerax.core.ui.gui import MainToolWindow self.tool_window = MainToolWindow(self) self.tool_window.manage(placement="side") parent = self.tool_window.ui_area
class ToolUI(ToolInstance): SESSION_ENDURING = False # if SESSION_ENDURING is True, tool instance not deleted at session closure def __init__(self, session, tool_name): ToolInstance.__init__(self, session, tool_name) # FIXME: display_name' defaults to class name with spaces inserted # between lower-then-upper-case characters (therefore "Tool UI" # in this case), so only override if different name desired self.display_name = "Xlink Analyzer" from chimerax.core.ui.gui import MainToolWindow self.tool_window = MainToolWindow(self) self.tool_window.manage(placement="side") parent = self.tool_window.ui_area
def layout_main(tool): # Standard template stuff tool.display_name = "Tempy" tool.tool_window = MainToolWindow(tool) tool.tool_window.manage(placement="side") parent = tool.tool_window.ui_area policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) parent.setSizePolicy(policy) layout = QVBoxLayout() tool.top_layout = layout # Create some tabs tab_widget = QTabWidget(parent) tab_widget.setMinimumHeight(210) tab_widget.setMinimumWidth(400) tab_widget.setSizePolicy(policy) tab_smoc = QWidget() tab_smoc.setMinimumHeight(210) tab_smoc.setMinimumWidth(400) tab_smoc.setSizePolicy(policy) tab_widget.addTab(tab_smoc, "SMOC") tab_sccc = QWidget() tab_sccc.setMinimumHeight(210) tab_sccc.setMinimumWidth(400) tab_sccc.setSizePolicy(policy) tab_widget.addTab(tab_sccc, "SCCC") tab_ccc = QWidget() tab_ccc.setMinimumHeight(210) tab_ccc.setMinimumWidth(400) tab_ccc.setSizePolicy(policy) tab_widget.addTab(tab_ccc, "CCC") tab_nmi = QWidget() tab_nmi.setMinimumHeight(210) tab_nmi.setMinimumWidth(400) tab_nmi.setSizePolicy(policy) tab_widget.addTab(tab_nmi, "NMI") tab_dif = QWidget() tab_dif.setMinimumHeight(210) tab_dif.setMinimumWidth(400) tab_dif.setSizePolicy(policy) tab_widget.addTab(tab_dif, "DIFMAP") # Now layout each tab layout_nmi(tool, tab_nmi) layout_sccc(tool, tab_sccc) layout_smoc(tool, tab_smoc) layout_ccc(tool, tab_ccc) layout_dif(tool, tab_dif) parent.setLayout(layout) layout.addWidget(tab_widget) # Figures for SMOC tool._figure = None tool._canvas = None
class SampleTool(ToolInstance): SESSION_ENDURING = False SESSION_SKIP = True # No session saving for now CUSTOM_SCHEME = "sample" # HTML scheme for custom links display_name = "Sample Tool" def __init__(self, session, tool_name): # Standard template stuff for intializing tool super().__init__(session, tool_name) from chimerax.core.ui.gui import MainToolWindow self.tool_window = MainToolWindow(self) self.tool_window.manage(placement="side") parent = self.tool_window.ui_area # Create an HTML viewer for our user interface. # We can include other Qt widgets if we want to. from PyQt5.QtWidgets import QGridLayout from chimerax.core.ui.widgets import HtmlView layout = QGridLayout() self.html_view = HtmlView(parent, size_hint=(575, 200), interceptor=self._navigate, schemes=[self.CUSTOM_SCHEME]) layout.addWidget(self.html_view, 0, 0) # row 0, column 0 parent.setLayout(layout) # Register for model addition/removal so we can update model list from chimerax.core.models import ADD_MODELS, REMOVE_MODELS t = session.triggers self._add_handler = t.add_handler(ADD_MODELS, self._update_models) self._remove_handler = t.add_handler(REMOVE_MODELS, self._update_models) # Go! self._update_models() def _update_models(self, trigger=None, trigger_data=None): # Called to update page with current list of models from chimerax.core.atomic import AtomicStructure html = ["<h2>Sample Tool</h2>", "<ul>"] from urllib.parse import quote for m in self.session.models.list(type=AtomicStructure): html.append("<li><a href=\"%s:%s\">%s - %s</a></li>" % (self.CUSTOM_SCHEME, quote(m.atomspec()), m.id_string(), m.name)) html.extend(["</ul>", "<h3>Output:</h3>", '<div id="output">Counts appear here</div>']) self.html_view.setHtml('\n'.join(html)) def _navigate(self, info): # Called when link is clicked. # "info" is an instance of QWebEngineUrlRequestInfo url = info.requestUrl() scheme = url.scheme() if scheme == self.CUSTOM_SCHEME: # Intercept our custom scheme. # Method may be invoked in a different thread than # the main thread where Qt calls may be made. self.session.ui.thread_safe(self._run, url.path()) def _run(self, atomspec): # Execute "sample count" command for given atomspec from chimerax.core.commands import run from chimerax.core.logger import StringPlainTextLog with StringPlainTextLog(self.session.logger) as log: try: run(self.session, "sample count " + atomspec) finally: html = "<pre>\n%s</pre>" % log.getvalue() js = ('document.getElementById("output").innerHTML = %s' % repr(html)) self.html_view.page().runJavaScript(js)
class ViewDockTool(ToolInstance): SESSION_ENDURING = False SESSION_SKIP = True # No session saving for now CUSTOM_SCHEME = "viewdockx" # HTML scheme for custom links display_name = "ViewDockX" def __init__(self, session, tool_name, structures=None): # Standard template stuff for intializing tool super().__init__(session, tool_name) from chimerax.core.ui.gui import MainToolWindow self.tool_window = MainToolWindow(self) self.tool_window.manage(placement="side") if structures is None: structures = session.models.list(type=AtomicStructure) self.structures = structures parent = self.tool_window.ui_area # Create an HTML viewer for our user interface. # We can include other Qt widgets if we want to. from PyQt5.QtWidgets import QGridLayout from chimerax.core.ui.widgets import HtmlView layout = QGridLayout() self.html_view = HtmlView(parent, size_hint=(575, 200), interceptor=self._navigate, schemes=[self.CUSTOM_SCHEME]) layout.addWidget(self.html_view, 0, 0) # row 0, column 0 parent.setLayout(layout) # Register for model addition/removal so we can update model list from chimerax.core.models import REMOVE_MODELS t = session.triggers # self._add_handler = t.add_handler(ADD_MODELS, self._update_models) self._remove_handler = t.add_handler(REMOVE_MODELS, self._update_models) # Go! self._update_models() def delete(self): t = self.session.triggers if self._remove_handler: t.remove_handler(self._remove_handler) self._remove_handler = None super().delete() def _update_models(self, trigger=None, trigger_data=None): """ Called to update page with current list of models""" from urllib.parse import urlunparse, urlencode if trigger_data is not None: for struct in self.structures: if struct in trigger_data: self.structures.remove(struct) if not self.structures: self.delete() return # TRANSFERS ALL KEYS INTO A SET, THEN A LIST category_set = set() for struct in self.structures: try: category_set.update({key for key in struct.viewdock_comment}) except AttributeError: pass category_list = sorted(list(category_set), key=str.lower) #################### #### TABLE #### #################### table = [] table.append( '<table id="viewdockx_table" class="tablesorter" style="width:100%">' ) ########################### ### COLUMN HEADERS ### ########################### # COLUMN HEADER | ID | table.append('<thead><tr>') table.append('<th class="id">ID</th>') # COLUMN HEADERS | NAME |...|...|... table.append('<th>NAME</th>') for category in category_list: if category.upper() == "NAME": pass else: table.append('<th>{}</th>'.format(category.upper())) table.append("</tr></thead>") ######################## ### COLUMN DATA ### ######################## table.append('<tbody>') for struct in self.structures: try: comment_dict = struct.viewdock_comment except AttributeError: # for files with empty comment sections comment_dict = {} # MAKES THE URL FOR EACH STRUCTURE args = [("atomspec", struct.atomspec())] query = urlencode(args) #url = urlunparse((self.CUSTOM_SCHEME, "", "", "", query, "")) checkbox_url = urlunparse( (self.CUSTOM_SCHEME, "", "checkbox", "", query, "")) link_url = urlunparse( (self.CUSTOM_SCHEME, "", "link", "", query, "")) # ADDING ID VALUE table.append("<tr>") table.extend([ '<td class="id">', # for checkbox + atomspec string '<span class="checkbox">' '<input class="checkbox, struct" type="checkbox" href="{}"/>' '{}</span>'.format(checkbox_url, struct.atomspec()[1:]), # for atomspec links only '<span class="link"><a href="{}">{}</a></span>'.format( link_url, struct.atomspec()[1:]), '</td>' ]) # ADDING VALUE FOR NAME for category in category_list: if category.upper() == "NAME": try: table.append('<td>{}</td>'.format( comment_dict[category])) except KeyError: table.append('<td>missing</td>') # ADDING THE REST for category in category_list: try: if category.upper() != "NAME": table.append('<td>{}</td>'.format( comment_dict[category])) except KeyError: table.append('<td>missing</td>') table.append("</tr>") table.append("</tbody>") table.append("</table>") import os from PyQt5.QtCore import QUrl # os.path.join() dir_path = os.path.dirname(os.path.abspath(__file__)) # lib_path = os.path.join(dir_path, "lib") qurl = QUrl.fromLocalFile(os.path.join(dir_path, "viewdockx.html")) with open(os.path.join(dir_path, "viewdockx_frame.html"), "r") as file: template = file.read() output = template.replace("TABLE", ('\n'.join(table)))\ .replace("urlbase", qurl.url()) self.html_view.setHtml(output, qurl) # output_file = os.path.join( # "C:/Users/hannahku/Desktop/RBVIInternship/GitHub/UCSF-RBVI-Internship/ViewDockX/src/output-test.html") # print(output_file) # with open(output_file, "w") as file2: # file2.write(output) # print("TEST SUCCESS") def _navigate(self, info): # Called when link is clicked. # "info" is an instance of QWebEngineUrlRequestInfo from urllib.parse import parse_qs url = info.requestUrl() scheme = url.scheme() if scheme == self.CUSTOM_SCHEME: # Intercept our custom scheme. # Method may be invoked in a different thread than # the main thread where Qt calls may be made. query = parse_qs(url.query()) path = url.path() function_map = { "check_all": self.check_all, "checkbox": self.checkbox, "link": self.link, "graph": self.graph } function_map[path](query) # self.session.ui.thread_safe(function_map[path](query)) def check_all(self, query): """shows or hides all structures""" show_all = query["show_all"][0] self.session.ui.thread_safe(self._run_checkall, show_all) def checkbox(self, query): """shows or hides individual structure""" from chimerax.core.commands.cli import StructuresArg print(query) try: atomspec = query["atomspec"][0] disp = query["display"][0] except (KeyError, ValueError): atomspec = "missing" structures = StructuresArg.parse(atomspec, self.session)[0] self.session.ui.thread_safe(self._run_cb, structures, disp) def link(self, query): """shows only selected structure""" from chimerax.core.commands.cli import StructuresArg try: atomspec = query["atomspec"][0] except (KeyError, ValueError): atomspec = "missing" structures = StructuresArg.parse(atomspec, self.session)[0] self.session.ui.thread_safe(self._run_link, structures) def graph(self, query): """open new window to render graph""" pass def _run_cb(self, structures, disp): if disp == "0": for struct in self.structures: if structures[0] == struct: struct.display = False else: for struct in self.structures: if structures[0] == struct: struct.display = True def _run_link(self, structures): for struct in self.structures: struct.display = struct in structures def _run_checkall(self, show_all): if show_all == "true": for struct in self.structures: struct.display = True else: for struct in self.structures: struct.display = False