class ReplDock(DockWidget): """Dock widget with terminal emulator """ def __init__(self, title, icon): DockWidget.__init__(self, core.mainWindow(), title, icon, "Alt+I") self.setObjectName(title) self.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # Copied from https://github.com/jupyter/qtconsole/blob/master/examples/inprocess_qtconsole.py, then modified based on https://github.com/jupyter/qtconsole/blob/master/qtconsole/qtconsoleapp.py -- the QtInProcessKernelManager is blocking, so infinite loops crash Enki! kernel_manager = QtKernelManager() kernel_manager.start_kernel() kernel_manager.client_factory = QtKernelClient kernel_manager.kernel.gui = 'qt' kernel_client = kernel_manager.client() kernel_client.start_channels() self.ipython_widget = RichJupyterWidget() self.ipython_widget.kernel_manager = kernel_manager self.ipython_widget.kernel_client = kernel_client # By default, iPython adds a blank line between inputs. Per Monika's request, this eliminates the extra line. See https://qtconsole.readthedocs.io/en/latest/config_options.html#options; this fix was based on info from https://stackoverflow.com/questions/38652671/ipython-5-0-remove-spaces-between-input-lines. self.ipython_widget.input_sep = '' self.ipython_widget.show() self.setWidget(self.ipython_widget) self.setFocusProxy(self.ipython_widget)
class ReplDock(DockWidget): """Dock widget with terminal emulator """ def __init__(self, title, icon): DockWidget.__init__(self, core.mainWindow(), title, icon, "Alt+I") self.setObjectName(title) self.setAllowedAreas(Qt.BottomDockWidgetArea | Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) # Copied from https://github.com/jupyter/qtconsole/blob/master/examples/inprocess_qtconsole.py, then modified based on https://github.com/jupyter/qtconsole/blob/master/qtconsole/qtconsoleapp.py -- the QtInProcessKernelManager is blocking, so infinite loops crash Enki! kernel_manager = QtKernelManager() kernel_manager.start_kernel() kernel_manager.client_factory = QtKernelClient kernel_manager.kernel.gui = 'qt' kernel_client = kernel_manager.client() kernel_client.start_channels() self.ipython_widget = RichJupyterWidget() self.ipython_widget.kernel_manager = kernel_manager self.ipython_widget.kernel_client = kernel_client # By default, iPython adds a blank line between inputs. Per Monika's request, this eliminates the extra line. See https://qtconsole.readthedocs.io/en/latest/config_options.html#options; this fix was based on info from https://stackoverflow.com/questions/38652671/ipython-5-0-remove-spaces-between-input-lines. self.ipython_widget.input_sep = '' self.ipython_widget.show() self.setWidget(self.ipython_widget) self.setFocusProxy(self.ipython_widget)
class Ipython(object): def __init__(self, scripts_path=''): self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel sys.stdout = self.kernel.stdout sys.stderr = self.kernel.stderr self.scripts_path = scripts_path self.kernel.gui = 'qt4' self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.control = RichJupyterWidget() self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(self.stop) self.control.setWindowTitle("IPython shell") self.execute('import numpy as np') self.execute('from matplotlib import pyplot as plt') self.execute('%matplotlib') self.execute('') def __del__(self): self.stop() self.close() def show(self): self.control.show() self.control.setWindowState(self.control.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive) self.control.activateWindow() def stop(self): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() def close(self): self.control.close() def push(self, vardic): self.kernel.shell.push(vardic) def execute(self, cmd): self.control.execute(cmd) def run_script(self, scriptname): scriptpath = os.path.join(self.scripts_path, scriptname) return self.control.execute('run -i %s' % scriptpath)
def show(): global ipython_widget # Prevent from being garbage collected # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel(show_banner=False) kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() ipython_widget = RichJupyterWidget() ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client ipython_widget.show()
def show(): global ipython_widget # Prevent from being garbage collected # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel(show_banner=False) kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() ipython_widget = RichJupyterWidget() ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client ipython_widget.show()
def independent_qtconsole(): kernel_manager = QtKernelManager() kernel_manager.start_kernel(show_banner=False) kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() ipython_widget = RichJupyterWidget() ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client ipython_widget.show() return ipython_widget
def __init__(self, namespace, windowtitle=None): from .. import qt_error if qt_error is not None: self._dummy = True return self.namespace = namespace self.kernel_manager = MyQtInProcessKernelManager() self.kernel_manager.start_kernel(namespace) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() control = RichJupyterWidget() self.control = control control.kernel_manager = self.kernel_manager control.kernel_client = self.kernel_client if windowtitle is not None: control.setWindowTitle("Seamless shell: " + windowtitle) control.show()
def show_console(self): global ipython_widget # Prevent from being garbage collected # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel(show_banner=False) kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() ipython_widget = RichJupyterWidget() ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client ipython_widget.show() ipython_widget.append_stream("from ConsoleInterface import *\n")
def _run_embedded_qtconsole(conn_filename): # This is launched as a new process. # # Wait max. ten seconds for the IPython kernel to be up and running, # which is done by checking for presence of the connection file # containing the kernels Zero Message Queue sockets and credentials. # # Then, start a new QApplication running the Jupyter Console client # widget connected to the kernel via the connection file. # for i in range(100): try: st = os.stat(conn_filename) except OSError as e: if e.errno != errno.ENOENT: # No such file exception is ignored, all others re-raised raise else: if st.st_size > 0: # OK, connection file found, kernel seems to be running break time.sleep(0.1) app = QtGui.QApplication(["Plot Workbench Console"]) kernel_client = QtKernelClient(connection_file=conn_filename) kernel_client.load_connection_file() kernel_client.start_channels() def exit(): kernel_client.shutdown() kernel_client.stop_channels() app.exit() ipython_widget = RichJupyterWidget() ipython_widget.kernel_client = kernel_client ipython_widget.exit_requested.connect(exit) ipython_widget.show() app.exec_()
def inprocess_qtconsole(self): #w = QtGui.QWidget() kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel(show_banner=False) kernel = kernel_manager.kernel kernel.gui = 'qt4' self.kernel_manager = kernel_manager kernel_client = kernel_manager.client() kernel_client.start_channels() self.kernel_client = kernel_client ipython_widget = RichJupyterWidget() ipython_widget.kernel_manager = kernel_manager ipython_widget.kernel_client = kernel_client ipython_widget.exit_requested.connect(self.stop_inprocess) ipython_widget.show() self.ipython_widget = ipython_widget return ipython_widget
class CentralWidget(QWidget): """The PyNetAnalyzer central widget""" def __init__(self, parent): QWidget.__init__(self) self.parent = parent self.appdata: CnaData = parent.appdata self.map_counter = 0 self.searchbar = QLineEdit() self.searchbar.setPlaceholderText("Enter search term") self.throttler = SignalThrottler(300) self.searchbar.textChanged.connect(self.throttler.throttle) self.throttler.triggered.connect(self.update_selected) self.tabs = QTabWidget() self.reaction_list = ReactionList(self.appdata) self.metabolite_list = MetaboliteList(self.appdata) self.model_info = ModelInfo(self.appdata) self.tabs.addTab(self.reaction_list, "Reactions") self.tabs.addTab(self.metabolite_list, "Metabolites") self.tabs.addTab(self.model_info, "Model") self.map_tabs = QTabWidget() self.map_tabs.setTabsClosable(True) self.map_tabs.setMovable(True) # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel(show_banner=False) kernel = kernel_manager.kernel kernel.gui = 'qt' myglobals = globals() myglobals["cna"] = self.parent self.kernel_shell = kernel_manager.kernel.shell self.kernel_shell.push(myglobals) self.kernel_client = kernel_manager.client() self.kernel_client.start_channels() # Check if client is working self.kernel_client.execute('import matplotlib.pyplot as plt') self.kernel_client.execute('%matplotlib inline') self.kernel_client.execute( "%config InlineBackend.figure_format = 'svg'") self.console = RichJupyterWidget() self.console.kernel_manager = kernel_manager self.console.kernel_client = self.kernel_client self.splitter = QSplitter() self.splitter2 = QSplitter() self.splitter2.addWidget(self.map_tabs) self.mode_navigator = ModeNavigator(self.appdata) self.splitter2.addWidget(self.mode_navigator) self.splitter2.addWidget(self.console) self.splitter2.setOrientation(Qt.Vertical) self.splitter.addWidget(self.splitter2) self.splitter.addWidget(self.tabs) self.console.show() layout = QVBoxLayout() layout.addWidget(self.searchbar) layout.addWidget(self.splitter) self.setLayout(layout) self.tabs.currentChanged.connect(self.tabs_changed) self.reaction_list.jumpToMap.connect(self.jump_to_map) self.reaction_list.jumpToMetabolite.connect(self.jump_to_metabolite) self.reaction_list.reactionChanged.connect( self.handle_changed_reaction) self.reaction_list.reactionDeleted.connect( self.handle_deleted_reaction) self.metabolite_list.metaboliteChanged.connect( self.handle_changed_metabolite) self.metabolite_list.jumpToReaction.connect(self.jump_to_reaction) self.metabolite_list.computeInOutFlux.connect(self.in_out_fluxes) self.model_info.optimizationDirectionChanged.connect( self.handle_changed_optimization_direction) self.map_tabs.tabCloseRequested.connect(self.delete_map) self.mode_navigator.changedCurrentMode.connect(self.update_mode) self.mode_navigator.modeNavigatorClosed.connect(self.update) self.update() def fit_mapview(self): self.map_tabs.currentWidget().fit() def show_bottom_of_console(self): (_, r) = self.splitter2.getRange(1) self.splitter2.moveSplitter(r * 0.5, 1) vSB = self.console.children()[2].verticalScrollBar() max_scroll = vSB.maximum() vSB.setValue(max_scroll - 100) def handle_changed_reaction(self, old_id: str, reaction: cobra.Reaction): self.parent.unsaved_changes() for mmap in self.appdata.project.maps: if old_id in self.appdata.project.maps[mmap]["boxes"].keys(): self.appdata.project.maps[mmap]["boxes"][ reaction. id] = self.appdata.project.maps[mmap]["boxes"].pop(old_id) # TODO update only relevant reaction boxes on maps self.update_maps() def handle_deleted_reaction(self, reaction: cobra.Reaction): self.appdata.project.cobra_py_model.remove_reactions( [reaction], remove_orphans=True) self.parent.unsaved_changes() for mmap in self.appdata.project.maps: if reaction.id in self.appdata.project.maps[mmap]["boxes"].keys(): self.appdata.project.maps[mmap]["boxes"].pop(reaction.id) # TODO update only relevant reaction boxes on maps self.update_maps() def handle_changed_metabolite(self, old_id: str, metabolite: cobra.Metabolite): self.parent.unsaved_changes() # TODO update only relevant reaction boxes on maps self.update_maps() def handle_changed_optimization_direction(self, direction: str): self.parent.unsaved_changes() def shutdown_kernel(self): self.console.kernel_client.stop_channels() self.console.kernel_manager.shutdown_kernel() def switch_to_reaction(self, reaction: str): self.tabs.setCurrentIndex(0) self.reaction_list.set_current_item(reaction) def minimize_reaction(self, reaction: str): self.parent.fba_optimize_reaction(reaction, mmin=True) def maximize_reaction(self, reaction: str): self.parent.fba_optimize_reaction(reaction, mmin=False) def update_reaction_value(self, reaction: str, value: str): if value == "": self.appdata.scen_values_pop(reaction) self.appdata.project.comp_values.pop(reaction, None) else: try: x = float(value) self.appdata.scen_values_set(reaction, (x, x)) except ValueError: (vl, vh) = make_tuple(value) self.appdata.scen_values_set(reaction, (vl, vh)) self.reaction_list.update() def update_reaction_maps(self, _reaction: str): self.parent.unsaved_changes() self.reaction_list.reaction_mask.update_state() def handle_mapChanged(self, _reaction: str): self.parent.unsaved_changes() def tabs_changed(self, idx): if idx == 0: self.reaction_list.update() elif idx == 1: (clean_model, unused_mets) = prune_unused_metabolites( self.appdata.project.cobra_py_model) self.appdata.project.cobra_py_model = clean_model self.metabolite_list.update() elif idx == 2: self.model_info.update() def add_map(self): while True: name = "Map " + str(self.map_counter) self.map_counter += 1 if name not in self.appdata.project.maps.keys(): break m = CnaMap(name) self.appdata.project.maps[name] = m mmap = MapView(self.appdata, name) mmap.switchToReactionMask.connect(self.switch_to_reaction) mmap.minimizeReaction.connect(self.minimize_reaction) mmap.maximizeReaction.connect(self.maximize_reaction) mmap.reactionValueChanged.connect(self.update_reaction_value) mmap.reactionRemoved.connect(self.update_reaction_maps) mmap.reactionAdded.connect(self.update_reaction_maps) mmap.mapChanged.connect(self.handle_mapChanged) self.map_tabs.addTab(mmap, m["name"]) self.update_maps() self.map_tabs.setCurrentIndex(len(self.appdata.project.maps)) self.parent.unsaved_changes() def delete_map(self, idx: int): name = self.map_tabs.tabText(idx) diag = ConfirmMapDeleteDialog(self, idx, name) diag.exec() def update_selected(self): x = self.searchbar.text() idx = self.tabs.currentIndex() if idx == 0: self.reaction_list.update_selected(x) if idx == 1: self.metabolite_list.update_selected(x) idx = self.map_tabs.currentIndex() if idx >= 0: m = self.map_tabs.widget(idx) m.update_selected(x) def update_mode(self): if len(self.appdata.project.modes) > self.mode_navigator.current: values = self.appdata.project.modes[self.mode_navigator.current] # set values self.appdata.project.scen_values.clear() self.appdata.project.comp_values.clear() for i in values: self.appdata.project.comp_values[i] = (values[i], values[i]) self.appdata.modes_coloring = True self.update() self.appdata.modes_coloring = False def update(self): if len(self.appdata.project.modes) == 0: self.mode_navigator.hide() self.mode_navigator.current = 0 else: self.mode_navigator.show() self.mode_navigator.update() idx = self.tabs.currentIndex() if idx == 0: self.reaction_list.update() elif idx == 1: self.metabolite_list.update() elif idx == 2: self.model_info.update() idx = self.map_tabs.currentIndex() if idx >= 0: m = self.map_tabs.widget(idx) m.update() def update_map(self, idx): m = self.map_tabs.widget(idx) if m is not None: m.update() def update_maps(self): for idx in range(0, self.map_tabs.count()): m = self.map_tabs.widget(idx) m.update() def jump_to_map(self, identifier: str, reaction: str): for idx in range(0, self.map_tabs.count()): name = self.map_tabs.tabText(idx) if name == identifier: m = self.map_tabs.widget(idx) self.map_tabs.setCurrentIndex(idx) m.update() m.focus_reaction(reaction) m.highlight_reaction(reaction) break def jump_to_metabolite(self, metabolite: str): self.tabs.setCurrentIndex(1) m = self.tabs.widget(1) m.set_current_item(metabolite) def jump_to_reaction(self, reaction: str): self.tabs.setCurrentIndex(0) m = self.tabs.widget(0) m.set_current_item(reaction) def in_out_fluxes(self, metabolite): self.kernel_client.execute("cna.print_in_out_fluxes('" + metabolite + "')") self.show_bottom_of_console()
class QtipWindow(QtGui.QMainWindow): """Main Qtip window class""" def __init__(self, parent=None, engine='pint', \ parfile=None, timfile=None, **kwargs): """ Initialize the main window :param parent: The parent window that embeds the Qtip window :param engine: The preferred timing package to use ('pint'/'libstempo') ['pint'] :param parfile: Par-file top open on startup :param timfile: Tim-file top open on startup """ super(QtipWindow, self).__init__(parent) self.setWindowTitle('Jupyter interface for pulsar timing') # Initialise basic gui elements self.initUI() # Start the embedded Jupyter kernel self.createJupyterKernel() # Create the display widgets self.createPlkWidget() self.createJupyterWidget() self.createOpenSomethingWidget() # Position the widgets self.initQtipLayout() # Initialize the main widget (the plk emulator) self.setQtipLayout(whichWidget='plk', showJupyter=False, firsttime=True) # The preferred engine to use (PINT) self.pref_engine = engine # We are still in MAJOR testing mode, so open a test-pulsar right away # if no par/tim file is given if parfile is None or timfile is None: testpulsar = True else: testpulsar = False # Open plk as the main widget self.requestOpenPlk(testpulsar=testpulsar, parfilename=parfile, \ timfilename=timfile, engine=self.pref_engine) self.show() def __del__(self): pass def onAbout(self): """Show an about box""" msg = constants.QtipBanner QtGui.QMessageBox.about(self, "About Qtip", msg.strip()) def initUI(self): """Initialise the user-interface elements""" # Create the main-frame widget, and the layout self.mainFrame = QtGui.QWidget() self.setCentralWidget(self.mainFrame) self.hbox = QtGui.QHBoxLayout() # HBox contains all widgets # Menu item: open par/tim files self.openParTimAction = QtGui.QAction('&Open par/tim', self) self.openParTimAction.setShortcut('Ctrl+O') self.openParTimAction.setStatusTip('Open par/tim') self.openParTimAction.triggered.connect(self.openParTim) # Menu item: exit Qtip self.exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) self.exitAction.setShortcut('Ctrl+Q') self.exitAction.setStatusTip('Exit application') self.exitAction.triggered.connect(self.close) # Previously, it was possible to switch out the 'plk' widget for another # main widget (the binary pulsar one). That one has been stripped out # now, so for now it makes no sense to 'toggle' on or off the plk # widget. However, the option is still there for now... self.togglePlkAction = QtGui.QAction('&Plk', self) self.togglePlkAction.setShortcut('Ctrl+P') self.togglePlkAction.setStatusTip('Toggle plk widget') self.togglePlkAction.triggered.connect(self.togglePlk) # Menu item: toggle the Jupyter window self.toggleJupyterAction = QtGui.QAction('&Jupyter', self) self.toggleJupyterAction.setShortcut('Ctrl+J') self.toggleJupyterAction.setStatusTip('Toggle Jupyter') self.toggleJupyterAction.triggered.connect(self.toggleJupyter) # Menu item: about Qtip self.aboutAction = QtGui.QAction('&About', self) self.aboutAction.setShortcut('Ctrl+A') self.aboutAction.setStatusTip('About Qtip') self.aboutAction.triggered.connect(self.onAbout) # The status bar self.theStatusBar = QtGui.QStatusBar() #self.statusBar() self.setStatusBar(self.theStatusBar) # A label that shows what engine is being used (hardcoded: PINT) self.engine_label = QtGui.QLabel("PINT") self.engine_label.setFrameStyle( QtGui.QFrame.Sunken|QtGui.QFrame.Panel) self.engine_label.setLineWidth(4) self.engine_label.setMidLineWidth(4) self.engine_label.setStyleSheet("QLabel{color:black;background-color:red}") self.theStatusBar.addPermanentWidget(self.engine_label) # On OSX, make sure the menu can be displayed (in the window itself) if sys.platform == 'darwin': # On OSX, the menubar is usually on the top of the screen, not in # the window. To make it in the window: QtGui.qt_mac_set_native_menubar(False) # Otherwise, if we'd like to get the system menubar at the top, then # we need another menubar object, not self.menuBar as below. In that # case, use: # self.menubar = QtGui.QMenuBar() # TODO: Somehow this does not work. Per-window one does though # Create the menu bar, and link the action items self.menubar = self.menuBar() self.fileMenu = self.menubar.addMenu('&File') self.fileMenu.addAction(self.openParTimAction) self.fileMenu.addAction(self.exitAction) self.viewMenu = self.menubar.addMenu('&View') self.viewMenu.addAction(self.togglePlkAction) self.viewMenu.addAction(self.toggleJupyterAction) self.helpMenu = self.menubar.addMenu('&Help') self.helpMenu.addAction(self.aboutAction) # What is the status quo of the user interface? self.showJupyter = False self.whichWidget = 'None' self.prevShowJupyter = None self.prevWhichWidget = 'None' def createJupyterKernel(self): """Create and start the embedded Jupyter Kernel""" # Create an in-process kernel self.kernelManager = QtInProcessKernelManager() self.kernelManager.start_kernel() self.kernel = self.kernelManager.kernel # Launch the kernel self.kernelClient = self.kernelManager.client() self.kernelClient.start_channels() # Allow inline matplotlib figures self.kernel.shell.enable_matplotlib(gui='inline') # Load the necessary packages in the embedded kernel # TODO: show this line in a cell of it's own cell = "import numpy as np, matplotlib.pyplot as plt, qtpulsar as qp" self.kernel.shell.run_cell(cell, store_history=False) # Set the in-kernel matplotlib color scheme to black. self.setMplColorScheme('black') # Outside as well (do we need this?) self.kernel.shell.run_cell(constants.matplotlib_rc_cell_black, store_history=False) def createJupyterWidget(self): """Create the Jupyter widget""" self.consoleWidget = RichJupyterWidget() #self.consoleWidget.setMinimumSize(600, 550) # Show the banner self.consoleWidget.banner = constants.QtipBanner self.consoleWidget.kernel_manager = self.kernelManager # Couple the client self.consoleWidget.kernel_client = self.kernelClient self.consoleWidget.exit_requested.connect(self.toggleJupyter) self.consoleWidget.set_default_style(colors='linux') self.consoleWidget.hide() # Register a call-back function for the Jupyter shell. This one is # executed insite the child-kernel. #self.kernel.shell.register_post_execute(self.postExecute) # # In Jupyter >= 2, we can use the event register # Events: post_run_cell, pre_run_cell, etc...` self.kernel.shell.events.register('pre_execute', self.preExecute) self.kernel.shell.events.register('post_execute', self.postExecute) self.kernel.shell.events.register('post_run_cell', self.postRunCell) def createOpenSomethingWidget(self): """Create the OpenSomething widget. Do not add it to the layout yet TODO: This widget should become the first main widget to see? At the moment, we're avoiding it for the sake of testing purposes """ self.openSomethingWidget = OpenSomethingWidget(parent=self.mainFrame, \ openFile=self.requestOpenPlk) self.openSomethingWidget.hide() def createPlkWidget(self): """Create the Plk widget""" self.plkWidget = PlkWidget(parent=self.mainFrame) self.plkWidget.hide() def toggleJupyter(self): """Toggle the Jupyter widget on or off""" self.setQtipLayout(showJupyter = not self.showJupyter) def togglePlk(self): """Toggle the plk widget on or off""" self.setQtipLayout(whichWidget='plk') def initQtipLayout(self): """Initialise the Qtip layout""" # If other 'main' widgets exist, they can be added here self.hbox.addWidget(self.openSomethingWidget) self.hbox.addWidget(self.plkWidget) self.hbox.addStretch(1) self.hbox.addWidget(self.consoleWidget) self.mainFrame.setLayout(self.hbox) def hideAllWidgets(self): """Hide all widgets of the mainFrame""" # Remove all widgets from the main window # No, hiding seems to work better """ while self.hbox.count(): item = self.hbox.takeAt(0) if isinstance(item, QtGui.QWidgetItem): #item.widget().deleteLater() item.widget().hide() elif isinstance(item, QtGui.QSpacerItem): #self.hbox.removeItem(item) pass else: #fcbox.clearLayout(item.layout()) #self.hbox.removeItem(item) pass """ self.openSomethingWidget.hide() self.plkWidget.hide() self.consoleWidget.hide() def showVisibleWidgets(self): """Show the correct widgets in the mainFrame""" # Add the widgets we need if self.whichWidget.lower() == 'opensomething': self.openSomethingWidget.show() elif self.whichWidget.lower() == 'plk': self.plkWidget.show() # Other widgets can be added here if self.showJupyter: self.consoleWidget.show() else: pass # Request focus back to the main widget if self.whichWidget.lower() == 'plk' and not self.showJupyter: self.plkWidget.setFocusToCanvas() # Do it for other main widgets, if they exist #elif self.whichWidget.lower() == 'binary' and not self.showJupyter: # self.binaryWidget.setFocusToCanvas() # Do we immediately get focus to the Jupyter console? #elif self.showJupyter: # self.consoleWidget.setFocus() def setQtipLayout(self, whichWidget=None, showJupyter=None, firsttime=False): """Given the current main widget, hide all the other widgets :param whichWidget: Which main widget we are showing right now :param showJupyter: Whether to show the Jupyter console :param firsttime: Whether or not this is the first time setting the layout. If so, resize to proper dimensions. TODO: How to do this more elegantly? """ if not whichWidget is None: self.whichWidget = whichWidget if not showJupyter is None: self.showJupyter = showJupyter # After hiding the widgets, wait 0 milliseonds before showing them again # (what a dirty hack, ugh!) self.hideAllWidgets() QtCore.QTimer.singleShot(0, self.showVisibleWidgets) self.prevWhichWidget = self.whichWidget if self.showJupyter != self.prevShowJupyter: # Jupyter has been toggled self.prevShowJupyter = self.showJupyter if self.showJupyter: self.resize(1350, 550) self.mainFrame.resize(1350, 550) else: self.resize(650, 550) self.mainFrame.resize(650, 550) # TODO: How to do this more elegantly? if firsttime: # Set position slightly more to the left of the screen, so we can # still open Jupyter self.move(50, 100) self.mainFrame.setLayout(self.hbox) self.mainFrame.show() def requestOpenPlk(self, parfilename=None, timfilename=None, \ testpulsar=False, engine='pint'): """Request to open a file in the plk widget :param parfilename: The parfile to open. If none, ask the user :param timfilename: The timfile to open. If none, ask the user """ self.setQtipLayout(whichWidget='plk', showJupyter=self.showJupyter) if parfilename is None and not testpulsar: parfilename = QtGui.QFileDialog.getOpenFileName(self, 'Open par-file', '~/') if timfilename is None and not testpulsar: timfilename = QtGui.QFileDialog.getOpenFileName(self, 'Open tim-file', '~/') # Load the pulsar self.openPlkPulsar(parfilename, timfilename, engine=engine, \ testpulsar=testpulsar) def setMplColorScheme(self, scheme): """ Set the matplotlib color scheme :param scheme: 'black'/'white', the color scheme """ # Obtain the Widget background color color = self.palette().color(QtGui.QPalette.Window) r, g, b = color.red(), color.green(), color.blue() rgbcolor = (r/255.0, g/255.0, b/255.0) if scheme == 'white': rcP = constants.mpl_rcParams_white rcP['axes.facecolor'] = rgbcolor rcP['figure.facecolor'] = rgbcolor rcP['figure.edgecolor'] = rgbcolor rcP['savefig.facecolor'] = rgbcolor rcP['savefig.edgecolor'] = rgbcolor elif scheme == 'black': rcP = constants.mpl_rcParams_black for key, value in rcP.iteritems(): matplotlib.rcParams[key] = value def openParTim(self): """Open a par-file and a tim-file""" # Ask the user for a par and tim file, and open these with libstempo/pint parfilename = QtGui.QFileDialog.getOpenFileName(self, 'Open par-file', '~/') timfilename = QtGui.QFileDialog.getOpenFileName(self, 'Open tim-file', '~/') # Load the pulsar self.openPlkPulsar(parfilename, timfilename, engine=self.pref_engine) def openPlkPulsar(self, parfilename, timfilename, engine='pint', \ testpulsar=False): """Open a pulsar, given a parfile and a timfile :param parfilename: The name of the parfile to open :param timfilename: The name fo the timfile to open :param engine: Which pulsar timing engine to use [pint] :param testpulsar: If True, open the test pulsar (J1744, NANOGrav) """ if engine=='pint': trypint = True else: trypint = False engine, pclass = qp.get_engine(trypint=trypint) # This all is a bit ugly... if engine == 'libstempo': if not testpulsar: # Obtain the directory name of the timfile, and change to it timfiletup = os.path.split(timfilename) dirname = timfiletup[0] reltimfile = timfiletup[-1] relparfile = os.path.relpath(parfilename, dirname) savedir = os.getcwd() # Change directory to the base directory of the tim-file to deal with # INCLUDE statements in the tim-file if dirname != '': os.chdir(dirname) # Load the pulsar cell = "psr = qp."+pclass+"('"+relparfile+"', '"+reltimfile+"')" self.kernel.shell.run_cell(cell) psr = self.kernel.shell.ns_table['user_local']['psr'] # Change directory back to where we were if dirname != '': os.chdir(savedir) else: cell = "psr = qp."+pclass+"(testpulsar=True)" self.kernel.shell.run_cell(cell) psr = self.kernel.shell.ns_table['user_local']['psr'] elif engine == 'pint': if not testpulsar: psr = qp.PPulsar(parfilename, timfilename) cell = "psr = qp."+pclass+"('"+parfilename+"', '"+timfilename+"')" else: psr = qp.PPulsar(testpulsar=True) cell = "psr = qp."+pclass+"(testpulsar=True)" self.kernel.shell.run_cell(cell) psr = self.kernel.shell.ns_table['user_local']['psr'] else: print("Engine = ", engine) raise NotImplemented("Only works with PINT/libstempo") # Update the plk widget self.plkWidget.setPulsar(psr) # Communicating with the kernel goes as follows # self.kernel.shell.push({'foo': 43, 'print_process_id': print_process_id}, interactive=True) # print("Embedded, we have:", self.kernel.shell.ns_table['user_local']['foo']) def keyPressEvent(self, event, **kwargs): """Handle a key-press event :param event: event that is handled here """ key = event.key() if key == QtCore.Qt.Key_Escape: self.close() elif key == QtCore.Qt.Key_Left: #print("Left pressed") pass else: #print("Other key") pass #print("QtipWindow: key press") super(QtipWindow, self).keyPressEvent(event, **kwargs) def mousePressEvent(self, event, **kwargs): """Handle a mouse-click event :param event: event that is handled here """ super(QtipWindow, self).mousePressEvent(event, **kwargs) def preExecute(self): """Callback function that is run prior to execution of a cell""" pass def postExecute(self): """Callback function that is run after execution of a code""" pass def postRunCell(self): """Callback function that is run after execution of a cell (after post-execute) """ # TODO: Do more than just update the plot, but also update _all_ the # widgets. Make a callback in plkWidget for that. QtipWindow might also # want to loop over some stuff. if self.whichWidget == 'plk': #self.plkWidget.updatePlot() pass
class IPythonDock(Dock): def __init__(self, *args, **kwargs): super(IPythonDock, self).__init__(*args, **kwargs) self.setMinimumHeight(25) self.setMinimumWidth(500) self.setWindowTitle("IPython Shell") self.setAllowedAreas(QtCore.Qt.AllDockWidgetAreas) self.console = RichJupyterWidget(name="console") self.console.font_size = 7 self.setWidget(self.console) def setup_ipython(self, main_window): """ Sets up the ipython shell for the relevant docks. :return: """ self.console.kernel_manager = kernel_manager = \ QtInProcessKernelManager() kernel_manager.start_kernel(show_banner=True) kernel_manager.kernel.gui = 'qt' self.console.kernel_client = kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() self.console.exit_requested.connect(stop) self.push_vars({"KatilInstance": main_window}) self.console.show() self.inject_globals() self.inject_debugs() def push_vars(self, variableDict): """ Given a dictionary containing name / value pairs, push those variables to the Jupyter console widget """ self.console.kernel_manager.kernel.shell.push(variableDict) def pull_var(self, varName, delete=False): v = self.console.kernel_manager.kernel.shell.user_ns[varName] if delete: del self.console.kernel_manager.kernel.shell.user_ns[varName] return v def delete_var(self, varName): del self.console.kernel_manager.kernel.shell.user_ns[varName] def clear(self): """ Clears the terminal """ self.console._control.clear() # self.kernel_manager def print_text(self, text): """ Prints some plain text to the console """ self.console._append_plain_text(text) def execute_command(self, command): """ Execute a command in the frame of the console widget """ self.console._execute(command, False) def inject_globals(self, glbls=None): """ Inject the globals() dict into the IPython kernel under the key '_injected' :return: """ if glbls is None: glbls = globals() self.push_vars({"_injected": glbls}) self.execute_command("from PyQt5.QtWidgets import *") self.execute_command("from praatkatili import *") def inject_debugs(self): self.push_vars({'canvas': self.findChildren(PlotCanvas)})