def main(): # Print the ID of the main process print_process_id() app = guisupport.get_app_qt4() # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process kernel_manager = QtAsyncInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel.shell.push({'foo': 43, 'print_process_id': print_process_id}) kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() guisupport.start_event_loop_qt4(app)
def show_ipython_console(): # from https://github.com/ipython/ipython/blob/1.x/examples/inprocess/embedded_qtconsole.py # this might be able to be a dockable panel at some point in the future. # it should also only allow one window open at a time - I think it steals stdout at start # and opening a new window stops output working on the old one! app = guisupport.get_app_qt4() # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() guisupport.start_event_loop_qt4(app)
def embed_shell_widget( parent_ptr ): ''' Create a RichIPythonWidget as a child of the given parent QWidget. Parent is assumed to be an integer and is wrapped into a QWidget using sip. This function may only be called when init_embedded_python() previously returned True. It may throw an ImportError if sip or PyQt4 is missing. If it successfully returns, the widget was successfully embedded. ''' global _kmgr, _kclient, widget if( _kmgr is None ): raise RuntimeError( "Kernel manager not initialized!" ) #print "embedding interactive python widget", parent_ptr, type(parent_ptr) import IPython from IPython.lib import guisupport if IPython.version_info[0] < 4: from IPython.qt.console.rich_ipython_widget import RichIPythonWidget as RichWidget else: from qtconsole.rich_jupyter_widget import RichJupyterWidget as RichWidget import sip from PyQt4 import QtGui, QtCore # Wave the magic wand and turn an integer into a QWidget object. parent = sip.wrapinstance(parent_ptr, QtGui.QWidget) widget = RichWidget(parent=parent, local_kernel=True) widget.kernel_manager = _kmgr widget.kernel_client = _kclient parent.layout().addWidget(widget) widget.change_font_size(-2) import __main__ __main__.ipw = widget
def initialize(self): # Init your plugin self.misc_s = self.locator.get_service('misc') explorer_container = self.locator.get_service('explorer') tree = explorer_container.get_tree_projects() kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() self.ipython_console = RichIPythonWidget() self.ipython_console.kernel_manager = kernel_manager self.ipython_console.kernel_client = kernel_client self.ipython_console.exit_requested.connect(stop) self.ipython_console.show() self.misc_s.add_widget(self.ipython_console, IMAGES["console"], "IPython console") addp = SIGNAL("addProjectToConsole(QString)") delp = SIGNAL("removeProjectFromConsole(QString)") self.connect(tree, addp, self._add_project) self.connect(tree, delp, self._del_project)
def __init__(self, parent=None, getfocus=None): super(IPythonView, self).__init__(parent) # Create an in-process kernel self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.shell = self.kernel.shell self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.control = RichIPythonWidget() self.control.set_default_style(colors='linux') self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(self.stop) # Enable Pylab mode. self.shell.enable_pylab() self.shell.automagic = True # Add some variables in the namespace. self.push(galry=galry) box = QtGui.QVBoxLayout() box.addWidget(self.control) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box)
def __init__(self, main_window): """ desc: Constructor. arguments: main_window: The main window object. """ super(ipython_console, self).__init__(main_window) kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() self.kernel = kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.banner1 = '' kernel_client = kernel_manager.client() kernel_client.start_channels() self.control = RichIPythonWidget() self.control.banner = self.banner() self.control.kernel_manager = kernel_manager self.control.kernel_client = kernel_client self.verticalLayout = QtGui.QVBoxLayout(self) self.verticalLayout.setContentsMargins(0,0,0,0) self.setLayout(self.verticalLayout) self.verticalLayout.addWidget(self.control)
def main(): """Start kernel manager and client, create window, run app event loop""" app = guisupport.get_app_qt4() if INPROCESS: from IPython.qt.inprocess import QtInProcessKernelManager km = QtInProcessKernelManager() else: from IPython.qt.manager import QtKernelManager km = QtKernelManager() km.start_kernel() km.kernel.gui = 'qt4' kc = km.client() kc.start_channels() widget = RichIPythonWidget() widget.kernel_manager = km widget.kernel_client = kc if CLEANSHUTDOWN: # slow exit on CTRL+D def stop(): kc.stop_channels() km.shutdown_kernel() app.exit() widget.exit_requested.connect(stop) else: # fast exit on CTRL+D widget.exit_requested.connect(app.quit) widget.show() guisupport.start_event_loop_qt4(app)
class IPythonView(QtGui.QWidget): def __init__(self, parent=None, getfocus=None): super(IPythonView, self).__init__(parent) # Create an in-process kernel self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.shell = self.kernel.shell self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.control = RichIPythonWidget() self.control.set_default_style(colors='linux') self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(self.stop) # Enable Pylab mode. self.shell.enable_pylab() self.shell.automagic = True # Add some variables in the namespace. self.push(galry=galry) box = QtGui.QVBoxLayout() box.addWidget(self.control) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box) def stop(self, *args): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() # Public methods. # --------------- def set_data(self, **kwargs): self.push(**kwargs) def push(self, **kwargs): """Inject variables in the interactive namespace.""" self.shell.push(kwargs) def run_file(self, file): """Execute a Python file in the interactive namespace.""" self.shell.safe_execfile(file, self.shell.user_global_ns) def run_cell(self, *args, **kwargs): """Execute a cell.""" self.shell.run_cell(*args, **kwargs)
class IPythonView(QtGui.QWidget): def __init__(self, parent=None, getfocus=None): super(IPythonView, self).__init__(parent) # Create an in-process kernel self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.shell = self.kernel.shell self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.control = RichIPythonWidget() self.control.set_default_style(colors='linux') self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(self.stop) # Enable Pylab mode. self.shell.enable_pylab() self.shell.automagic = True # Add some variables in the namespace. self.push(galry=galry) box = QtGui.QVBoxLayout() box.addWidget(self.control) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box) def stop(self, *args): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() # Public methods. # --------------- def set_data(self, **kwargs): self.push(**kwargs) def push(self, **kwargs): """Inject variables in the interactive namespace.""" self.shell.push(kwargs) def run_file(self, file): """Execute a Python file in the interactive namespace.""" self.shell.safe_execfile(file, self.shell.user_global_ns) def run_cell(self, *args, **kwargs): """Execute a cell.""" self.shell.run_cell(*args, **kwargs)
def hide(self): """suspend() -> None Called when hiding the parent window in order to recover the previous state. """ #recovering the state sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ sys.stdin = sys.__stdin__ RichIPythonWidget.hide(self)
def show(self): """show() -> None Store previous state and starts capturing all interactive input and output. """ # capture all interactive input/output sys.stdout = self sys.stderr = self sys.stdin = self RichIPythonWidget.show(self)
def __init__(self): RichIPythonWidget.__init__(self) self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'window': self, 'kernel': self.kernel}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.kernel_client.execute('%pylab inline') self.exit_requested.connect(self.exit_requested_func)
def __init__(self): RichIPythonWidget.__init__(self) self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'window': self, 'kernel': self.kernel}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.kernel_client.execute('%pylab inline') self.exit_requested.connect(self.exit_requested_func)
def initialize(self): # Init your plugin self.misc_s = self.locator.get_service('misc') explorer_container = self.locator.get_service('explorer') tree = explorer_container.get_tree_projects() kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() self.ipython_console = RichIPythonWidget() self.ipython_console.kernel_manager = kernel_manager self.ipython_console.kernel_client = kernel_client self.ipython_console.exit_requested.connect(stop) self.ipython_console.show() self.misc_s.add_widget(self.ipython_console, IMAGES["console"], "IPython console") addp = SIGNAL("addProjectToConsole(QString)") delp = SIGNAL("removeProjectFromConsole(QString)") self.connect(tree, addp, self._add_project) self.connect(tree, delp, self._del_project)
def create_widget(self): """ Create the underlying widget. """ self.widget = QFrame(self.parent_widget()) self.ipy_widget = RichIPythonWidget() assert self.page_control is not None # always use paging
def __init__(self, parent=None, getfocus=None): super(IPythonView, self).__init__(parent) # Create an in-process kernel self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.shell = self.kernel.shell self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.control = RichIPythonWidget() self.control.set_default_style(colors='linux') self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(self.stop) # Enable Pylab mode. self.shell.enable_pylab() self.shell.automagic = True # Add some variables in the namespace. self.push(galry=galry) box = QtGui.QVBoxLayout() box.addWidget(self.control) box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) self.setLayout(box)
def setup_console_widget(self): # Console if CONSOLE_TYPE == 'pyqtgraph.console': self.console_widget = pyqtgraph.console.ConsoleWidget( namespace={ 'app': self, 'pg': pg, 'np': np }, text="ScopeFoundry Console") elif CONSOLE_TYPE == 'qtconsole': # https://github.com/ipython/ipython-in-depth/blob/master/examples/Embedding/inprocess_qtconsole.py self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() #self.console_widget = RichIPythonWidget() self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle("ScopeFoundry IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client else: raise ValueError("CONSOLE_TYPE undefined") return self.console_widget
def main(self): # Print the ID of the main process #self.print_process_id() #app = guisupport.get_app_qt4() # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push(self.common.__dict__) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() def stop(): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() #app.exit() self.control = RichIPythonWidget(banner = self.banner) self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(stop) #start widget with certain inputs: #import pylab, which includes all numpy; import pandas as pd #second argument is whether the execution is hidden e.g. whether a line is used #I have turned on hide. self.control._execute('import pylab as pl; import pandas as pd',True)
def eventFilter(self, obj, event): """ Reimplemented to ensure a console-like behavior in the underlying text widgets. """ etype = event.type() if etype == QtCore.QEvent.KeyPress: self.running_workflow = False return RichIPythonWidget.eventFilter(self, obj, event)
def _load_ipython(self): # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel_manager.kernel.gui = "qt4" kernel_manager.kernel.shell.enable_pylab(gui="inline") kernel_client = kernel_manager.client() kernel_client.start_channels() control = RichIPythonWidget() self.ipythonDockWidget.setWidget(control) control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(kernel_client.stop_channels) control.exit_requested.connect(kernel_manager.shutdown_kernel) class IPythonNamespaceUpdater(QtCore.QObject): shell = kernel_manager.kernel.shell def eventFilter(self, target, e): if e.type() == QtCore.QEvent.Enter: self.shell.push(globals()) return False control.installEventFilter(IPythonNamespaceUpdater(self)) class Debug(object): def __init__(self, shell): self.shell = shell def __call__(self): import inspect frame = inspect.currentframe() try: temp = frame.f_back.f_globals temp.update(frame.f_back.f_locals) finally: del frame self.shell.run_line_magic("reset", "-f -s") self.shell.push(temp) # now monkeypatch hexrd.debug to use the qt console: hexrd.debug = Debug(kernel_manager.kernel.shell)
def terminal_widget(**kwargs): # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel.shell.push(kwargs) kernel_client = kernel_manager.client() kernel_client.start_channels() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client return control
def __init__(self, partent): kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt' kernel_client = kernel_manager.client() kernel_client.start_channels() QtGui.QWidget.__init__(self) displayname = QtGui.QLabel('iPython Terminal Widget') mainlayout = QtGui.QGridLayout(self) # console=IPythonWidget(self) console = RichIPythonWidget(self) console.kernel_manager = kernel_manager console.kernel_client = kernel_client console.exit_requested.connect(self.stop) mainlayout.addWidget(console, 0, 0)
def __init__(self, parent=None): RichIPythonWidget.__init__(self, parent) self.kernel_manager = km self.kernel_client = kernel_client self.exit_requested.connect(stop) #locals() returns the original dictionary, not a copy as #the docs say # self.firstLocals = copy.copy(locals()) # self.shell = IPythonXXX(self.firstLocals,None) # layout = QtGui.QVBoxLayout() # layout.setMargin(0) # layout.setSpacing(0) # layout.addWidget(self.shell) # self.setLayout(layout) # self.setWidget(self.shell) self.setWindowTitle("Console") # self.setTitleBarWidget(QtGui.QLabel(self.shell.windowTitle())) # self.monitorWindowTitle(self.shell) self.vistrails_interpreter = get_default_interpreter()
def __init__(self,partent): kernel_manager=QtInProcessKernelManager() kernel_manager.start_kernel() kernel=kernel_manager.kernel kernel.gui ='qt' kernel_client=kernel_manager.client() kernel_client.start_channels() QtGui.QWidget.__init__(self) displayname=QtGui.QLabel('iPython Terminal Widget') mainlayout=QtGui.QGridLayout(self) # console=IPythonWidget(self) console=RichIPythonWidget(self) console.kernel_manager=kernel_manager console.kernel_client=kernel_client console.exit_requested.connect(self.stop) mainlayout.addWidget(console,0,0)
def __init__(self, parent=None): super(ConsoleDockWidget, self).__init__(parent) self.setWindowTitle("Console") self.setAllowedAreas(QtCore.Qt.BottomDockWidgetArea) self.wgt_console = RichIPythonWidget() self.add_widget(self.wgt_console) self.setVisible(False)
def main(): # Print the ID of the main process print_process_id() app = guisupport.get_app_qt4() # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel.shell.push({'foo': 43, 'print_process_id': print_process_id}) kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() guisupport.start_event_loop_qt4(app)
def shell(kernel_manager, kernel_client): widget = RichIPythonWidget() widget.kernel_manager = kernel_manager widget.kernel_client = kernel_client widget.exit_requested.connect(stop) widget.setWindowTitle("IPython shell") return widget
def main(): #LETS ALSO DO SOME IPYTHOPN PARRALLEL STUFF global splicer app = guisupport.get_app_qt4() from LZM100 import splicer # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel.shell.push({'splicer': splicer}) kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() #app = QtGui.QApplication(sys.argv) #ex = Example() b = TaperDesign(Taper()) sys.exit(app.exec_())
def show_ipython_console(): # from https://github.com/ipython/ipython/blob/1.x/examples/inprocess/embedded_qtconsole.py # this might be able to be a dockable panel at some point in the future. # it should also only allow one window open at a time - I think it steals stdout at start # and opening a new window stops output working on the old one! app = guisupport.get_app_qt4() # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() guisupport.start_event_loop_qt4(app)
def createIPythonWidget(self): """ Create the IPython widget """ self.consoleWidget = RichIPythonWidget() #self.consoleWidget.setMinimumSize(600, 550) self.consoleWidget.banner = QtipBanner self.consoleWidget.kernel_manager = self.kernelManager self.consoleWidget.kernel_client = self.kernelClient self.consoleWidget.exit_requested.connect(self.toggleIPython) self.consoleWidget.set_default_style(colors='linux') self.consoleWidget.hide() # Register a call-back function for the IPython shell. This one is # executed insite the child-kernel. #self.kernel.shell.register_post_execute(self.postExecute) # # In IPython >= 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 setup_console_widget(self): self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle("py4DSTEM IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client return self.console_widget
class INinjaConsole(plugin.Plugin): def initialize(self): # Init your plugin self.misc_s = self.locator.get_service('misc') explorer_container = self.locator.get_service('explorer') tree = explorer_container.get_tree_projects() kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() self.ipython_console = RichIPythonWidget() self.ipython_console.kernel_manager = kernel_manager self.ipython_console.kernel_client = kernel_client self.ipython_console.exit_requested.connect(stop) self.ipython_console.show() self.misc_s.add_widget(self.ipython_console, IMAGES["console"], "IPython console") addp = SIGNAL("addProjectToConsole(QString)") delp = SIGNAL("removeProjectFromConsole(QString)") self.connect(tree, addp, self._add_project) self.connect(tree, delp, self._del_project) def _add_project(self, project_path): self.ipython_console.execute("import sys; sys.path += ['%s']" % project_path) def _del_project(self, project_path): """This is ugly, but I was in a hurry and copied form console widget""" self.ipython_console.execute("import sys; " "sys.path = [path for path in sys.path " "if path != '%s']" % project_path) def finish(self): # Shutdown your plugin pass def get_preferences_widget(self): # Return a widget for customize your plugin pass
def _createConsoleWidget(self): if is_using_pyqt5(): layout = QtWidgets.QVBoxLayout() else: layout = QtGui.QVBoxLayout() connection_file = find_connection_file(self.connection_file) self.kernel_manager = QtKernelManager(connection_file=connection_file) self.kernel_manager.load_connection_file() self.kernel_manager.client_factory = QtKernelClient self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.ipython_widget = RichIPythonWidget(self.parent) self.ipython_widget.kernel_manager = self.kernel_manager self.ipython_widget.kernel_client = self.kernel_client layout.addWidget(self.ipython_widget) return layout
class INinjaConsole(plugin.Plugin): def initialize(self): # Init your plugin self.misc_s = self.locator.get_service('misc') explorer_container = self.locator.get_service('explorer') tree = explorer_container.get_tree_projects() kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() self.ipython_console = RichIPythonWidget() self.ipython_console.kernel_manager = kernel_manager self.ipython_console.kernel_client = kernel_client self.ipython_console.exit_requested.connect(stop) self.ipython_console.show() self.misc_s.add_widget(self.ipython_console, IMAGES["console"], "IPython console") addp = SIGNAL("addProjectToConsole(QString)") delp = SIGNAL("removeProjectFromConsole(QString)") self.connect(tree, addp, self._add_project) self.connect(tree, delp, self._del_project) def _add_project(self, project_path): self.ipython_console.execute("import sys; sys.path += ['%s']" % project_path) def _del_project(self, project_path): """This is ugly, but I was in a hurry and copied form console widget""" self.ipython_console.execute("import sys; " "sys.path = [path for path in sys.path " "if path != '%s']" % project_path) def finish(self): # Shutdown your plugin pass def get_preferences_widget(self): # Return a widget for customize your plugin pass
def setup_console_widget(self): self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() #Avoid setting up multiple consoles alreadysetup = False if hasattr(self, 'console_widget'): if (isinstance(self.console_widget, RichJupyterWidget)): alreadysetup = True if not alreadysetup: self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle("py4DSTEM IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client return self.console_widget
def createIPythonWidget(self): """ Create the IPython widget """ self.consoleWidget = RichIPythonWidget() #self.consoleWidget.setMinimumSize(600, 550) self.consoleWidget.banner = QtipBanner self.consoleWidget.kernel_manager = self.kernelManager self.consoleWidget.kernel_client = self.kernelClient self.consoleWidget.exit_requested.connect(self.toggleIPython) self.consoleWidget.set_default_style(colors='linux') self.consoleWidget.hide() # Register a call-back function for the IPython shell. This one is # executed insite the child-kernel. #self.kernel.shell.register_post_execute(self.postExecute) # # In IPython >= 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 _load_ipython(self): # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel_manager.kernel.gui = 'qt4' kernel_manager.kernel.shell.enable_pylab(gui='inline') kernel_client = kernel_manager.client() kernel_client.start_channels() control = RichIPythonWidget() self.ipythonDockWidget.setWidget(control) control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(kernel_client.stop_channels) control.exit_requested.connect(kernel_manager.shutdown_kernel) class IPythonNamespaceUpdater(QtCore.QObject): shell = kernel_manager.kernel.shell def eventFilter(self, target, e): if e.type() == QtCore.QEvent.Enter: self.shell.push(globals()) return False control.installEventFilter(IPythonNamespaceUpdater(self)) class Debug(object): def __init__(self, shell): self.shell = shell def __call__(self): import inspect frame = inspect.currentframe() try: temp = frame.f_back.f_globals temp.update(frame.f_back.f_locals) finally: del frame self.shell.run_line_magic('reset', '-f -s') self.shell.push(temp) # now monkeypatch hexrd.debug to use the qt console: hexrd.debug = Debug(kernel_manager.kernel.shell)
def procsteppython_do_run(stepglobals, runfunc, argkw, ipythonmodelist, action, scripthref, pycode_text, pycode_lineno): if not ipythonmodelist[0]: resultdict = runfunc(**argkw) return resultdict else: # ipython mode # in-process kernel, a-la https://raw.githubusercontent.com/ipython/ipython/master/examples/Embedding/inprocess_qtconsole.py ## Set PyQt4 API version to 2 and import it -- required for ipython compatibility #import sip #sip.setapi('QVariant', 2) #sip.setapi('QString', 2) #sip.setapi('QDateTime', 2) #sip.setapi('QDate', 2) #sip.setapi('QTextStream', 2) #sip.setapi('QTime', 2) #sip.setapi('QUrl', 2) #from PyQt4 import QtGui # force IPython to use PyQt4 by importing it first # RHEL6 compatibility -- if running under Python 2.6, just import IPython, get PyQt4 if sys.version_info < (2, 7): from IPython.qt.console.rich_ipython_widget import RichIPythonWidget from IPython.qt.inprocess import QtInProcessKernelManager pass else: # Under more recent OS's: Make matplotlib use PySide # http://stackoverflow.com/questions/6723527/getting-pyside-to-work-with-matplotlib import matplotlib matplotlib.use('Qt4Agg') matplotlib.rcParams['backend.qt4'] = 'PySide' pass import IPython from IPython.core.interactiveshell import DummyMod if LooseVersion(IPython.__version__) >= LooseVersion('4.0.0'): # Recent Jupyter/ipython: Import from qtconsole # Force PySide bindings import PySide.QtCore from qtconsole.qt import QtGui from qtconsole.inprocess import QtInProcessKernelManager # Obtain the running QApplication instance app = QtGui.QApplication.instance() if app is None: # Start our own if necessary app = QtGui.QApplication([]) pass pass else: from IPython.qt.inprocess import QtInProcessKernelManager from IPython.lib import guisupport app = guisupport.get_app_qt4() pass kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' #sys.stderr.write("id(stepglobals)=%d" % (id(stepglobals))) # Make ipython use our globals as its global dictionary # ... but first keep a backup stepglobalsbackup = copy.copy(stepglobals) (kernel.user_module, kernel.user_ns) = kernel.shell.prepare_user_module( user_ns=stepglobals) # Should we attempt to run the function here? # (gui, backend) = kernel.shell.enable_matplotlib("qt4") #,import_all=False) # (args.gui, import_all=import_all) (gui, backend, clobbered) = kernel.shell.enable_pylab( "qt4", import_all=False) # (args.gui, import_all=import_all) # kernel.shell.push(stepglobals) # provide globals as variables -- no longer necessary as it's using our namespace already kernel.shell.push(argkw) # provide arguments as variables kernel.shell.push( {"kernel": kernel}, interactive=False) # provide kernel for debugging purposes kernel_client = kernel_manager.client() kernel_client.start_channels() abort_requested_list = [False ] # encapsulated in a list to make it mutable def stop(): control.hide() kernel_client.stop_channels() kernel_manager.shutdown_kernel() app.exit() pass def abort(): # simple exit doesn't work. See http://stackoverflow.com/questions/1527689/exit-from-ipython # too bad this doesn't work right now!!! class Quitter(object): def __repr__(self): sys.exit() pass kernel.shell.push({"quitter": Quitter()}) kernel.shell.ex("quitter") stop() abort_requested_list.pop() abort_requested_list.append(True) pass if pycode_text is None: kernel.shell.write("\n\nExecute %s/%s\n" % (scripthref.getpath(), runfunc.__name__)) pass else: kernel.shell.write( "\n\nExecute %s/%s/%s\n" % (scripthref.getpath(), action, runfunc.__name__)) pass kernel.shell.write("Assign return value to \"ret\" and press Ctrl-D\n") kernel.shell.write("Set cont=True to disable interactive mode\n") # kernel.shell.write("call abort() to exit\n") if LooseVersion(IPython.__version__) >= LooseVersion('4.0.0'): # Recent Jupyter/ipython: Import from qtconsole from qtconsole.rich_jupyter_widget import RichJupyterWidget as RichIPythonWidget pass else: from IPython.qt.console.rich_ipython_widget import RichIPythonWidget pass control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() #sys.stderr.write("lines=%s\n" % (str(lines))) #sys.stderr.write("lines[0]=%s\n" % (str(lines[0]))) try: if pycode_text is None: (lines, startinglineno) = inspect.getsourcelines(runfunc) assert (lines[0].startswith("def") ) # first line of function is the defining line del lines[0] # remove def line lines.insert(0, "if 1:\n") # allow function to be indented runfunc_syntaxtree = ast.parse( "".join(lines), filename=scripthref.getpath(), mode='exec' ) # BUG: Should set dont_inherit parameter and properly determine which __future__ import flags should be passed # fixup line numbers for syntreenode in ast.walk(runfunc_syntaxtree): if hasattr(syntreenode, "lineno"): syntreenode.lineno += startinglineno - 1 pass pass # runfunc_syntaxtree should consist of the if statement we just added # use _fields attribute to look up fields of an AST element # (e.g. test, body, orelse for IF) # then those fields can be accessed directly assert (len(runfunc_syntaxtree.body) == 1) code_container = runfunc_syntaxtree.body[0] assert (isinstance(code_container, ast.If) ) # code_container is the if statement we just wrote kernel.shell.push( {"runfunc_syntaxtree": runfunc_syntaxtree}, interactive=False ) # provide processed syntax tree for debugging purposes pass else: fullsyntaxtree = ast.parse( pycode_text ) # BUG: Should set dont_inherit parameter and properly determine which __future__ import flags should be passed # fixup line numbers for syntreenode in ast.walk(fullsyntaxtree): if hasattr(syntreenode, "lineno"): syntreenode.lineno += pycode_lineno - 1 pass pass code_container = None for codeelement in fullsyntaxtree.body: if isinstance(codeelement, ast.FunctionDef): if codeelement.name == runfunc.__name__: code_container = codeelement runfunc_syntaxtree = codeelement pass pass pass if code_container is None: raise ValueError( "Couldn't find code for %s for ipython execution" % (runfunc.__name__)) kernel.shell.push( {"fullsyntaxtree": fullsyntaxtree}, interactive=False ) # provide full syntax tree for debugging purposes pass # identify global variables from runfunc_syntaxtree globalvars = set() for treeelem in ast.walk(runfunc_syntaxtree): if isinstance(treeelem, ast.Global): globalvars = globalvars.union(treeelem.names) pass pass kernel.shell.push({"abort": abort}) # provide abort function kernel.shell.push({"cont": False}) # continue defaults to False returnstatement = code_container.body[-1] if isinstance(returnstatement, ast.Return): # last statement is a return statement! # Create assign statement that assigns # the result to ret retassign = ast.Assign(targets=[ ast.Name(id="ret", ctx=ast.Store(), lineno=returnstatement.lineno, col_offset=returnstatement.col_offset) ], value=returnstatement.value, lineno=returnstatement.lineno, col_offset=returnstatement.col_offset) del code_container.body[-1] # remove returnstatement code_container.body.append(retassign) # add assignment pass runfunc_lines = code_container.body kernel.shell.push( { "runfunc_lines": runfunc_lines, "scripthref": scripthref }, interactive=False ) # provide processed syntax tree for debugging purposes # kernel.shell.run_code(compile("kernel.shell.run_ast_nodes(runfunc_lines,scriptpath,interactivity='all')","None","exec")) if LooseVersion(IPython.__version__) >= LooseVersion('4.0.0'): # Recent Jupyter/ipython: Import from qtconsole from qtconsole.inprocess import QtCore pass else: from IPython.qt.inprocess import QtCore pass QTimer = QtCore.QTimer def showret(): control.execute("ret") pass def runcode(): control.execute( "kernel.shell.run_ast_nodes(runfunc_lines,scripthref.getpath(),interactivity='none')" ) # QTimer.singleShot(25,showret) # get callback 25ms into main loop # showret disabled because it prevents you from running the # debugger in post-mortem mode to troubleshoot an exception: # import pdb; pdb.pm() pass QTimer.singleShot(25, runcode) # get callback 25ms into main loop # control.execute("kernel.shell.run_ast_nodes(runfunc_lines,scripthref.getpath(),interactivity='none')") pass except: (exctype, excvalue) = sys.exc_info()[:2] sys.stderr.write( "%s while attempting to prepare URL %s code for interactive execution: %s\n" % (exctype.__name__, scripthref.absurl(), str(excvalue))) traceback.print_exc() raise if LooseVersion(IPython.__version__) >= LooseVersion('4.0.0'): # Recent Jupyter/ipython: Import from qtconsole app.exec_() pass else: # Old ipython guisupport.start_event_loop_qt4(app) pass if abort_requested_list[0]: pass if kernel.shell.ev("cont"): # cont==True -> disable interactive mode ipythonmodelist.pop() ipythonmodelist.append(False) pass try: retval = kernel.shell.ev( "ret") # Assign result dictionary to "ret" variable pass except NameError: # if ret not assigned, return {} retval = {} pass # Performing this execution changed values in stepglobals # but it should have only done that for variables specified # as 'global' in the function. # So: Update our backup of the value of stepglobals, # according to the specified globals, and # replace stepglobals with that updated backup stepglobalsbackup.update( dict([(varname, stepglobals[varname]) for varname in globalvars])) stepglobals.clear() stepglobals.update(stepglobalsbackup) return retval pass
class IPythonInProcess(object): def __init__(self,common,customBanner=None): if customBanner!=None: self.banner=customBanner self.common = common self.kernel_manager = None self.kernel = None self.control = None self.kernel_client = None self.init_qtconsole() def init_qtconsole(self): self.main() def print_process_id(self): print('Process ID is:', os.getpid()) def main(self): # Print the ID of the main process #self.print_process_id() #app = guisupport.get_app_qt4() # Create an in-process kernel # >>> print_process_id() # will print the same process ID as the main process self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push(self.common.__dict__) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() def stop(): self.kernel_client.stop_channels() self.kernel_manager.shutdown_kernel() #app.exit() self.control = RichIPythonWidget(banner = self.banner) self.control.kernel_manager = self.kernel_manager self.control.kernel_client = self.kernel_client self.control.exit_requested.connect(stop) #start widget with certain inputs: #import pylab, which includes all numpy; import pandas as pd #second argument is whether the execution is hidden e.g. whether a line is used #I have turned on hide. self.control._execute('import pylab as pl; import pandas as pd',True) def SHOW(self): self.control.show() #guisupport.start_event_loop_qt4(app) def pushVariables(self,variableDict): """ Given a dictionary containing name / value pairs, push those variables to the IPython console widget """ self.kernel_manager.kernel.shell.push(variableDict) def clearTerminal(self): """ Clears the terminal """ self._control.clear() def printText(self,text): """ Prints some plain text to the console """ self._append_plain_text(text) def executeCommand(self,command): """ Execute a command in the frame of the console widget """ self.control._execute(command,False)
class BaseApp(QtCore.QObject): def __init__(self, argv): QtCore.QObject.__init__(self) self.log = get_logger_from_class(self) self.this_dir, self.this_filename = os.path.split(__file__) self.qtapp = QtWidgets.QApplication.instance() if not self.qtapp: self.qtapp = QtWidgets.QApplication(argv) self.settings = LQCollection() self.setup_console_widget() # FIXME Breaks things for microscopes, but necessary for stand alone apps! #if hasattr(self, "setup"): # self.setup() if not hasattr(self, 'name'): self.name = "ScopeFoundry" self.qtapp.setApplicationName(self.name) def exec_(self): return self.qtapp.exec_() def setup_console_widget(self): # Console if CONSOLE_TYPE == 'pyqtgraph.console': self.console_widget = pyqtgraph.console.ConsoleWidget( namespace={ 'app': self, 'pg': pg, 'np': np }, text="ScopeFoundry Console") elif CONSOLE_TYPE == 'qtconsole': # https://github.com/ipython/ipython-in-depth/blob/master/examples/Embedding/inprocess_qtconsole.py self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() #self.console_widget = RichIPythonWidget() self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle("ScopeFoundry IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client else: raise ValueError("CONSOLE_TYPE undefined") return self.console_widget def setup(self): pass def settings_save_ini(self, fname, save_ro=True): """""" config = configparser.ConfigParser() config.optionxform = str config.add_section('app') config.set('app', 'name', self.name) for lqname, lq in self.settings.as_dict().items(): if not lq.ro or save_ro: config.set('app', lqname, lq.ini_string_value()) with open(fname, 'w') as configfile: config.write(configfile) self.log.info("ini settings saved to {} {}".format( fname, config.optionxform)) def settings_load_ini(self, fname): self.log.info("ini settings loading from " + fname) config = configparser.ConfigParser() config.optionxform = str config.read(fname) if 'app' in config.sections(): for lqname, new_val in config.items('app'): #print(lqname) lq = self.settings.as_dict().get(lqname) if lq: if lq.dtype == bool: new_val = str2bool(new_val) lq.update_value(new_val) def settings_save_ini_ask(self, dir=None, save_ro=True): """Opens a Save dialogue asking the user to select a save destination and give the save file a filename. Saves settings to an .ini file.""" # TODO add default directory, etc fname, _ = QtWidgets.QFileDialog.getSaveFileName( self.ui, caption=u'Save Settings', dir=u"", filter=u"Settings (*.ini)") #print(repr(fname)) if fname: self.settings_save_ini(fname, save_ro=save_ro) return fname def settings_load_ini_ask(self, dir=None): """Opens a Load dialogue asking the user which .ini file to load into our app settings. Loads settings from an .ini file.""" # TODO add default directory, etc fname, _ = QtWidgets.QFileDialog.getOpenFileName( None, "Settings (*.ini)") #print(repr(fname)) if fname: self.settings_load_ini(fname) return fname
def __new__(self, interpreter=None, message="", log="", parent=None): obj = RichIPythonWidget() obj.__class__ = ShellWidget return obj
def console(client, args): local = { 'client': client, 'auth': client.auth, 'reset': client.reset, 'config': client.config, 'execute': client.execute, } if args['scriptName']: ############################################################# # EXECUTE FILE # ############################################################# sys.argv = [] sys.argv.append(args['scriptName']) sys.argv.extend(args['scriptArgs']) try: f = open(sys.argv[0]) source_code = f.read() f.close() except IOError as e: raise pyAMI.exception.Error(e) compiled_code = compile(source_code, sys.argv[0], 'exec') safe_exec(compiled_code, globals(), local) ############################################################# else: ############################################################# # RUN CONSOLE # ############################################################# sys.argv = [sys.argv[0]] ############################################################# banner = pyAMI.config.banner if args['nosplash'] == False else '' ############################################################# if args['gIPython']: ##################################################### # IPYTHON GRAPHICAL MODE # ##################################################### try: from IPython.qt.console.rich_ipython_widget import RichIPythonWidget from IPython.qt.inprocess import QtInProcessKernelManager from IPython.lib import guisupport except ImportError as e: raise pyAMI.exception.Error('module `IPython` not properly installed: %s' % e) ################################ # HACK IPYTHON BANNER # ################################ RichIPythonWidget._banner_default = lambda self: banner ################################ # KERNEL_MANAGER # ################################ kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() ################################ # KERNEL_CLIENT # ################################ kernel_client = kernel_manager.client() kernel_client.start_channels() ################################ # PYAMI # ################################ kernel_manager.kernel.shell.push(local) ################################ # APPLICATION # ################################ a = guisupport.get_app_qt4() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() a.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.show() guisupport.start_event_loop_qt4(a) ##################################################### elif args['cIPython']: ##################################################### # IPYTHON CONSOLE MODE # ##################################################### try: from IPython.terminal.embed import InteractiveShellEmbed except ImportError as e: raise pyAMI.exception.Error('module `IPython` not properly installed: %s' % e) ################################ # SHELL # ################################ shell = InteractiveShellEmbed(banner1 = banner, banner2 = None) shell(local_ns = local) ##################################################### else: ##################################################### # DEFAULT MODE # ##################################################### code.interact(banner = banner, local = local) ##################################################### return 0
def setup_console_widget(self, kernel=None): """ Create and return console QWidget. If Jupyter / IPython is installed this widget will be a full-featured IPython console. If Jupyter is unavailable it will fallback to a pyqtgraph.console.ConsoleWidget. If the app is started in an Jupyter notebook, the console will be connected to the notebook's IPython kernel. the returned console_widget will also be accessible as self.console_widget In order to see the console widget, remember to insert it into an existing window or call self.console_widget.show() to create a new window """ if CONSOLE_TYPE == 'pyqtgraph.console': self.console_widget = pyqtgraph.console.ConsoleWidget( namespace={ 'app': self, 'pg': pg, 'np': np }, text="ScopeFoundry Console") elif CONSOLE_TYPE == 'qtconsole': if kernel == None: try: # try to find an existing kernel #https://github.com/jupyter/notebook/blob/master/docs/source/examples/Notebook/Connecting%20with%20the%20Qt%20Console.ipynb import ipykernel as kernel conn_file = kernel.get_connection_file() import qtconsole.qtconsoleapp self.qtconsole_app = qtconsole.qtconsoleapp.JupyterQtConsoleApp( ) self.console_widget = self.qtconsole_app.new_frontend_connection( conn_file) self.console_widget.setWindowTitle( "ScopeFoundry IPython Console") except: # make your own new in-process kernel # https://github.com/ipython/ipython-in-depth/blob/master/examples/Embedding/inprocess_qtconsole.py self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.shell.banner1 += """ ScopeFoundry Console Variables: * np: numpy package * app: the ScopeFoundry App object """ self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() #self.console_widget = RichIPythonWidget() self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle( "ScopeFoundry IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client else: import qtconsole.qtconsoleapp self.qtconsole_app = qtconsole.qtconsoleapp.JupyterQtConsoleApp( ) self.console_widget = self.qtconsole_app.new_frontend_connection( kernel.get_connection_file()) self.console_widget.setWindowTitle( "ScopeFoundry IPython Console") else: raise ValueError("CONSOLE_TYPE undefined") return self.console_widget
class BaseApp(QtCore.QObject): def __init__(self, argv=[]): QtCore.QObject.__init__(self) self.log = get_logger_from_class(self) self.this_dir, self.this_filename = os.path.split(__file__) self.qtapp = QtWidgets.QApplication.instance() if not self.qtapp: self.qtapp = QtWidgets.QApplication(argv) self.settings = LQCollection() # auto creation of console widget self.setup_console_widget() # FIXME Breaks things for microscopes, but necessary for stand alone apps! #if hasattr(self, "setup"): # self.setup() self.setup_logging() if not hasattr(self, 'name'): self.name = "ScopeFoundry" self.qtapp.setApplicationName(self.name) def exec_(self): return self.qtapp.exec_() def setup_console_widget(self, kernel=None): """ Create and return console QWidget. If Jupyter / IPython is installed this widget will be a full-featured IPython console. If Jupyter is unavailable it will fallback to a pyqtgraph.console.ConsoleWidget. If the app is started in an Jupyter notebook, the console will be connected to the notebook's IPython kernel. the returned console_widget will also be accessible as self.console_widget In order to see the console widget, remember to insert it into an existing window or call self.console_widget.show() to create a new window """ if CONSOLE_TYPE == 'pyqtgraph.console': self.console_widget = pyqtgraph.console.ConsoleWidget( namespace={ 'app': self, 'pg': pg, 'np': np }, text="ScopeFoundry Console") elif CONSOLE_TYPE == 'qtconsole': if kernel == None: try: # try to find an existing kernel #https://github.com/jupyter/notebook/blob/master/docs/source/examples/Notebook/Connecting%20with%20the%20Qt%20Console.ipynb import ipykernel as kernel conn_file = kernel.get_connection_file() import qtconsole.qtconsoleapp self.qtconsole_app = qtconsole.qtconsoleapp.JupyterQtConsoleApp( ) self.console_widget = self.qtconsole_app.new_frontend_connection( conn_file) self.console_widget.setWindowTitle( "ScopeFoundry IPython Console") except: # make your own new in-process kernel # https://github.com/ipython/ipython-in-depth/blob/master/examples/Embedding/inprocess_qtconsole.py self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.shell.banner1 += """ ScopeFoundry Console Variables: * np: numpy package * app: the ScopeFoundry App object """ self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() #self.console_widget = RichIPythonWidget() self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle( "ScopeFoundry IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client else: import qtconsole.qtconsoleapp self.qtconsole_app = qtconsole.qtconsoleapp.JupyterQtConsoleApp( ) self.console_widget = self.qtconsole_app.new_frontend_connection( kernel.get_connection_file()) self.console_widget.setWindowTitle( "ScopeFoundry IPython Console") else: raise ValueError("CONSOLE_TYPE undefined") return self.console_widget def setup(self): pass def settings_save_ini(self, fname, save_ro=True): """""" config = configparser.ConfigParser() config.optionxform = str config.add_section('app') config.set('app', 'name', self.name) for lqname, lq in self.settings.as_dict().items(): if not lq.ro or save_ro: config.set('app', lqname, lq.ini_string_value()) with open(fname, 'w') as configfile: config.write(configfile) self.log.info("ini settings saved to {} {}".format( fname, config.optionxform)) def settings_load_ini(self, fname): self.log.info("ini settings loading from " + fname) config = configparser.ConfigParser() config.optionxform = str config.read(fname) if 'app' in config.sections(): for lqname, new_val in config.items('app'): #print(lqname) lq = self.settings.as_dict().get(lqname) if lq: if lq.dtype == bool: new_val = str2bool(new_val) lq.update_value(new_val) def settings_save_ini_ask(self, dir=None, save_ro=True): """Opens a Save dialogue asking the user to select a save destination and give the save file a filename. Saves settings to an .ini file.""" # TODO add default directory, etc fname, _ = QtWidgets.QFileDialog.getSaveFileName( self.ui, caption=u'Save Settings', dir=u"", filter=u"Settings (*.ini)") #print(repr(fname)) if fname: self.settings_save_ini(fname, save_ro=save_ro) return fname def settings_load_ini_ask(self, dir=None): """Opens a Load dialogue asking the user which .ini file to load into our app settings. Loads settings from an .ini file.""" # TODO add default directory, etc fname, _ = QtWidgets.QFileDialog.getOpenFileName( None, "Settings (*.ini)") #print(repr(fname)) if fname: self.settings_load_ini(fname) return fname def setup_logging(self): logging.basicConfig( level=logging.WARN) #, filename='example.log', stream=sys.stdout) logging.getLogger('traitlets').setLevel(logging.WARN) logging.getLogger('ipykernel.inprocess').setLevel(logging.WARN) logging.getLogger('LoggedQuantity').setLevel(logging.WARN) logging.getLogger('PyQt5').setLevel(logging.WARN) logger = logging.getLogger('FoundryDataBrowser') self.logging_widget = QtWidgets.QWidget() self.logging_widget.setWindowTitle("Log") self.logging_widget.setLayout(QtWidgets.QVBoxLayout()) self.logging_widget.search_lineEdit = QtWidgets.QLineEdit() self.logging_widget.log_textEdit = QtWidgets.QTextEdit("") self.logging_widget.layout().addWidget( self.logging_widget.search_lineEdit) self.logging_widget.layout().addWidget( self.logging_widget.log_textEdit) self.logging_widget.log_textEdit.document().setDefaultStyleSheet( "body{font-family: Courier;}") self.logging_widget_handler = LoggingQTextEditHandler( self.logging_widget.log_textEdit, level=logging.DEBUG) logging.getLogger().addHandler(self.logging_widget_handler)
def __new__(self, interpreter=None, message="", log='', parent=None): obj = RichIPythonWidget() obj.__class__ = ShellWidget return obj
from PyQt4.QtGui import QApplication app = QApplication(sys.argv) kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() # here you should exit your application with a suitable call sys.exit() widget = RichIPythonWidget() widget.kernel_manager = kernel_manager widget.kernel_client = kernel_client widget.exit_requested.connect(stop) widget.setWindowTitle("IPython shell") ipython_widget = widget ipython_widget.show() app.exec_() sys.exit()
class QtipWindow(QtGui.QMainWindow): """ Main Qtip window Note, is the main window now, but the content will later be moved to a libstempo tab, as part of the Piccard suite """ def __init__(self, parent=None, engine='libstempo', \ parfile=None, timfile=None, **kwargs): super(QtipWindow, self).__init__(parent) self.setWindowTitle('QtIpython interface to Piccard/libstempo') # Initialise basic gui elements self.initUI() # Start the embedded IPython kernel self.createIPythonKernel() # Create the display widgets self.createBinaryWidget() self.createPlkWidget() self.createIPythonWidget() self.createOpenSomethingWidget() # Position the widgets self.initQtipLayout() self.setQtipLayout(whichWidget='opensomething', showIPython=False, firsttime=True) # We are still in MAJOR testing mode, so open a test-pulsar right away # (delete this line when going into production) if parfile is None or timfile is None: testpulsar = True else: testpulsar = False # Are we going to open plk straight away? self.requestOpenPlk(testpulsar=testpulsar, parfilename=parfile, \ timfilename=timfile, engine=engine) self.show() def __del__(self): pass def onAbout(self): msg = """ A plk emulator, written in Python. Powered by PyQt, matplotlib, libstempo, and IPython: """ QtGui.QMessageBox.about(self, "About the demo", 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 # Create the menu action items self.openParTimAction = QtGui.QAction('&Open', self) self.openParTimAction.setShortcut('Ctrl+O') self.openParTimAction.setStatusTip('Open par/tim') self.openParTimAction.triggered.connect(self.openParTim) 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) self.toggleBinaryAction = QtGui.QAction('&Binary', self) self.toggleBinaryAction.setShortcut('Ctrl+B') self.toggleBinaryAction.setStatusTip('Toggle binary widget') self.toggleBinaryAction.triggered.connect(self.toggleBinary) self.togglePlkAction = QtGui.QAction('&Plk', self) self.togglePlkAction.setShortcut('Ctrl+P') self.togglePlkAction.setStatusTip('Toggle plk widget') self.togglePlkAction.triggered.connect(self.togglePlk) self.toggleIPythonAction = QtGui.QAction('&IPython', self) self.toggleIPythonAction.setShortcut('Ctrl+I') self.toggleIPythonAction.setStatusTip('Toggle IPython') self.toggleIPythonAction.triggered.connect(self.toggleIPython) self.aboutAction = QtGui.QAction('&About', self) self.aboutAction.setShortcut('Ctrl+A') self.aboutAction.setStatusTip('About Qtip') self.aboutAction.triggered.connect(self.onAbout) self.theStatusBar = QtGui.QStatusBar() #self.statusBar() self.setStatusBar(self.theStatusBar) self.engine_label = QtGui.QLabel("Tempo2") 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 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.toggleBinaryAction) self.viewMenu.addAction(self.togglePlkAction) self.viewMenu.addAction(self.toggleIPythonAction) self.helpMenu = self.menubar.addMenu('&Help') self.helpMenu.addAction(self.aboutAction) # What is the status quo of the user interface? self.showIPython = False self.whichWidget = 'None' self.prevShowIPython = None self.prevWhichWidget = 'None' def createIPythonKernel(self): """ Create the IPython Kernel """ # Create an in-process kernel self.kernelManager = QtInProcessKernelManager() self.kernelManager.start_kernel() self.kernel = self.kernelManager.kernel self.kernelClient = self.kernelManager.client() self.kernelClient.start_channels() self.kernel.shell.enable_matplotlib(gui='inline') # Load the necessary packages in the embedded kernel 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 createIPythonWidget(self): """ Create the IPython widget """ self.consoleWidget = RichIPythonWidget() #self.consoleWidget.setMinimumSize(600, 550) self.consoleWidget.banner = QtipBanner self.consoleWidget.kernel_manager = self.kernelManager self.consoleWidget.kernel_client = self.kernelClient self.consoleWidget.exit_requested.connect(self.toggleIPython) self.consoleWidget.set_default_style(colors='linux') self.consoleWidget.hide() # Register a call-back function for the IPython shell. This one is # executed insite the child-kernel. #self.kernel.shell.register_post_execute(self.postExecute) # # In IPython >= 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: probably should use a signal to implement this call instead of openParTim """ 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 createBinaryWidget(self): """ Create the binary model widget """ self.binaryWidget = BinaryWidget(parent=self.mainFrame) self.binaryWidget.hide() def toggleIPython(self): """ Toggle the IPython widget on or off """ self.setQtipLayout(showIPython = not self.showIPython) def toggleBinary(self): """ Toggle the binary model widget on or off """ self.setQtipLayout(whichWidget='binary') def togglePlk(self): """ Toggle the plk widget on or off """ self.setQtipLayout(whichWidget='plk') def initQtipLayout(self): """ Initialise the Qtip layout """ self.hbox.addWidget(self.openSomethingWidget) self.hbox.addWidget(self.plkWidget) self.hbox.addWidget(self.binaryWidget) 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 # ??? """ 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.binaryWidget.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() elif self.whichWidget.lower() == 'piccard': pass elif self.whichWidget.lower() == 'binary': self.binaryWidget.show() if self.showIPython: self.consoleWidget.show() else: pass if self.whichWidget.lower() == 'plk' and not self.showIPython: self.plkWidget.setFocusToCanvas() elif self.whichWidget.lower() == 'binary' and not self.showIPython: self.binaryWidget.setFocusToCanvas() #elif self.showIPython: # self.consoleWidget.setFocus() def setQtipLayout(self, whichWidget=None, showIPython=None, firsttime=False): """ Given which widgets to show, display the right widgets and hide the rest @param whichWidget: Which widget to show @param showIPython: Whether to show the IPython console """ if not whichWidget is None: self.whichWidget = whichWidget if not showIPython is None: self.showIPython = showIPython # After hiding the widgets, wait 25 (or 0?) miliseconds before showing them again self.hideAllWidgets() QtCore.QTimer.singleShot(0, self.showVisibleWidgets) self.prevWhichWidget = self.whichWidget if self.showIPython != self.prevShowIPython: # IPython has been toggled self.prevShowIPython = self.showIPython if self.showIPython: self.resize(1350, 550) self.mainFrame.resize(1350, 550) else: self.resize(650, 550) self.mainFrame.resize(650, 550) if firsttime: # Set position slightly more to the left of the screen, so we can # still open IPython self.move(200, 100) self.mainFrame.setLayout(self.hbox) self.mainFrame.show() def requestOpenPlk(self, parfilename=None, timfilename=None, \ testpulsar=False, engine='libstempo'): """ 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', showIPython=self.showIPython) 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.openPulsar(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, filename=None, engine='libstempo'): """ Open a par-file and a tim-file """ print("openParTim called with {0}".format(filename)) # Ask the user for a par and tim file, and open these with libstempo if isinstance(filename, str): parfilename = filename else: parfilename = QtGui.QFileDialog.getOpenFileName(self, 'Open par-file', '~/') timfilename = QtGui.QFileDialog.getOpenFileName(self, 'Open tim-file', '~/') # Load the pulsar self.openPulsar(parfilename, timfilename, engine=engine) def openPulsar(self, parfilename, timfilename, engine='libstempo', 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 [libstempo] @param testpulsar: If True, open the test pulsar (J1744, NANOGrav) """ if engine=='pint': trypint = True else: trypint = False self.engine, pclass = qp.get_engine(trypint=trypint) 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 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 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': cell = "psr = qp."+pclass+"(testpulsar=True)" self.kernel.shell.run_cell(cell) psr = self.kernel.shell.ns_table['user_local']['psr'] else: raise NotImplemented("Only works with PINT/libstempo") # Update the plk widget self.plkWidget.setPulsar(psr) self.binaryWidget.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 """ #print("QtipWindow: mouse click") 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() elif self.whichWidget == 'binary': self.binaryWidget.updatePlot()
class ipython_console(base_console, QtGui.QWidget): """ desc: An IPython-based debug window. """ def __init__(self, main_window): """ desc: Constructor. arguments: main_window: The main window object. """ super(ipython_console, self).__init__(main_window) kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() self.kernel = kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.banner1 = '' kernel_client = kernel_manager.client() kernel_client.start_channels() self.control = RichIPythonWidget() self.control.banner = self.banner() self.control.kernel_manager = kernel_manager self.control.kernel_client = kernel_client self.verticalLayout = QtGui.QVBoxLayout(self) self.verticalLayout.setContentsMargins(0,0,0,0) self.setLayout(self.verticalLayout) self.verticalLayout.addWidget(self.control) def clear(self): """See base_console.""" self.control.reset(clear=True) def focus(self): """See base_console.""" self.control._control.setFocus() def reset(self): """See base_console.""" self.kernel.shell.reset() self.kernel.shell.push(self.default_globals()) self.clear() super(ipython_console, self).reset() def show_prompt(self): """See base_console.""" self.control._show_interpreter_prompt() def get_workspace_globals(self): """See base_console.""" return self.kernel.shell.user_global_ns.copy() def set_workspace_globals(self, _globals={}): """See base_console.""" self.kernel.shell.push(_globals) def validTheme(self, cs): """ returns: desc: True if the colorscheme is valid, False otherwise. type: bool """ for key in [ u'Background', u'Default', u'Prompt in', u'Prompt out', u'Comment', u'Keyword', u'Identifier', u'Double-quoted string', u'Invalid', u'Number', u'Operator', ]: if key not in cs: return False return True def setTheme(self): """ desc: Sets the theme, based on the QProgEdit settings. """ from QProgEdit import QColorScheme if not hasattr(QColorScheme, cfg.qProgEditColorScheme): debug.msg(u'Failed to set debug-output colorscheme') return u'' cs = getattr(QColorScheme, cfg.qProgEditColorScheme) if not self.validTheme(cs): debug.msg(u'Invalid debug-output colorscheme') return u'' self.control._highlighter.set_style(pygments_style_factory(cs)) qss = u'''QPlainTextEdit, QTextEdit { background-color: %(Background)s; color: %(Default)s; } .in-prompt { color: %(Prompt in)s; } .in-prompt-number { font-weight: bold; } .out-prompt { color: %(Prompt out)s; } .out-prompt-number { font-weight: bold; } ''' % cs self.control.style_sheet = qss self.control._control.setFont(QtGui.QFont(cfg.qProgEditFontFamily, cfg.qProgEditFontSize)) def setup(self, main_window): """See base_subcomponent.""" super(ipython_console, self).setup(main_window) self.kernel.shell.push(self.default_globals()) def write(self, s): """See base_console.""" self.control._append_plain_text(str(s)) def execute(self, s): """See base_console.""" self.main_window.ui.dock_stdout.setVisible(True) self.control.execute(s) def focusInEvent(self, e): self.control.setFocus() e.accept()
def __init__(self, args): """Initializes application""" super(QSceneGraphEditor, self).__init__(args) self._mainWindow = QtGui.QMainWindow() self._editor = QSceneGraphEditorWindow() self._mainWindow.setCentralWidget(self._editor) exitAction = QtGui.QAction('&Exit', self._mainWindow) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(self._mainWindow.close) newAction = QtGui.QAction('&New', self._mainWindow) newAction.setShortcut('Ctrl+N') newAction.setStatusTip('Creates a simple default scene') newAction.triggered.connect(self._editor.new) openAction = QtGui.QAction('&Open...', self._mainWindow) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Open scene graph from file') openAction.triggered.connect(self._editor.open) saveAction = QtGui.QAction('&Save', self._mainWindow) saveAction.setShortcut('Ctrl+S') saveAction.setStatusTip('Save scene graph') saveAction.triggered.connect(self._editor.save) saveAsAction = QtGui.QAction('&Save As...', self._mainWindow) saveAsAction.setStatusTip('Save scene graph to another file') saveAsAction.triggered.connect(self._editor.saveAs) insertObjectAction = QtGui.QAction('&Insert...', self._mainWindow) insertObjectAction.setShortcut('Ctrl+I') insertObjectAction.setStatusTip('Inserts new scene object before current one') insertObjectAction.triggered.connect(self._editor.inspectorWidget.insertObject) appendObjectAction = QtGui.QAction('&Append...', self._mainWindow) appendObjectAction.setShortcut('Ctrl+K') appendObjectAction.setStatusTip('Inserts new scene object after current one') appendObjectAction.triggered.connect(self._editor.inspectorWidget.appendObject) deleteObjectAction = QtGui.QAction('&Delete', self._mainWindow) deleteObjectAction.setShortcut('DEL') deleteObjectAction.setStatusTip('Deletes currently selected scene object') deleteObjectAction.triggered.connect(self._editor.inspectorWidget.deleteObject) refreshObjectAction = QtGui.QAction('&Refresh', self._mainWindow) refreshObjectAction.setShortcut('F5') refreshObjectAction.setStatusTip('Recreates tree view from root node') refreshObjectAction.triggered.connect(self._editor.refresh) viewAllAction = QtGui.QAction('View &All', self._mainWindow) viewAllAction.setShortcut('Ctrl+A') viewAllAction.setStatusTip('Resets camera in scene so all object are visible') viewAllAction.triggered.connect(self._editor.previewWidget.sceneManager.view_all) viewManipAction = QtGui.QAction('Camera &Manipulation', self._mainWindow) viewManipAction.setShortcut('Ctrl+M') viewManipAction.setStatusTip('Enables manipulation of camera in the scene') viewManipAction.setCheckable(True) viewManipAction.setChecked(True) viewManipAction.connect(QtCore.SIGNAL("triggered(bool)"), self._editor.previewWidget.sceneManager.interaction) self._editor.previewWidget.sceneManager.interaction(True) #self._mainWindow.statusBar() menubar = self._mainWindow.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(newAction) fileMenu.addAction(openAction) fileMenu.addAction(saveAction) fileMenu.addAction(saveAsAction) fileMenu.addSeparator() fileMenu.addAction(exitAction) objectsMenu = menubar.addMenu('&Scene Object') objectsMenu.addAction(insertObjectAction) objectsMenu.addAction(appendObjectAction) objectsMenu.addAction(deleteObjectAction) objectsMenu.addSeparator() objectsMenu.addAction(refreshObjectAction) viewMenu = menubar.addMenu('&View') viewMenu.addAction(viewAllAction) viewMenu.addAction(viewManipAction) if "--ipython" in self.arguments(): # start with IPython console at bottom of application from IPython.qt.console.rich_ipython_widget import RichIPythonWidget from IPython.qt.inprocess import QtInProcessKernelManager from IPython.lib import guisupport import inventor # Create an in-process kernel kernel_manager = QtInProcessKernelManager() kernel_manager.start_kernel() kernel = kernel_manager.kernel kernel.gui = 'qt4' kernel.shell.push({'iv': inventor, 'root': self._editor._root, 'view': self._editor.previewWidget.sceneManager }) kernel_client = kernel_manager.client() kernel_client.start_channels() def stop(): kernel_client.stop_channels() kernel_manager.shutdown_kernel() self.exit() control = RichIPythonWidget() control.kernel_manager = kernel_manager control.kernel_client = kernel_client control.exit_requested.connect(stop) control.font = QtGui.QFont(control.font.family(), 10); self.addVerticalWidget(control) # load default scene or from file if argument is given file = "#Inventor V2.1 ascii\n\nSeparator { " \ "DirectionalLight {} OrthographicCamera { position 0 0 5 height 5 }" \ "TrackballManip {} Material { diffuseColor 1 0 0 }" \ "Cone {} }" if (len(self.arguments()) > 1) and ("." in self.arguments()[-1]): extension = self.arguments()[-1].split('.')[-1].lower() if extension in [ 'iv', 'vrml', '3ds', 'stl' ]: file = self.arguments()[-1]; self._editor.load(file)
class DataViewer(QtWidgets.QMainWindow): """ The class is used by instantiating and then entering the main Qt loop with, e.g.: app = DataViewer(sys.argv) app.exec_() """ def __init__(self, argv): """ Initialize class, setting up windows and widgets. """ # Define this as the QApplication object self.qtapp = QtWidgets.QApplication.instance() if not self.qtapp: self.qtapp = QtWidgets.QApplication(argv) QtWidgets.QMainWindow.__init__(self) self.this_dir, self.this_filename = os.path.split(__file__) # Make settings collection self.settings = LQCollection() # Set up sub-windows and arrange into primary py4DSTEM window self.diffraction_space_widget = self.setup_diffraction_space_widget() self.real_space_widget = self.setup_real_space_widget() self.control_widget = self.setup_control_widget() self.console_widget = self.setup_console_widget() self.main_window = self.setup_main_window() # Set up temporary datacube self.datacube = DataCube(data=np.zeros((10, 10, 10, 10))) # Set up initial views in real and diffraction space self.update_diffraction_space_view() self.update_virtual_detector_shape() self.update_virtual_detector_mode() self.update_real_space_view() self.diffraction_space_widget.ui.normDivideRadio.setChecked(True) self.diffraction_space_widget.normRadioChanged() return ############################################### ############ Widget setup methods ############# ############################################### def setup_control_widget(self): """ Set up the control window for diffraction space. """ #self.control_widget = load_qt_ui_file(sibling_path(__file__, "control_widget.ui")) self.control_widget = ControlPanel() self.control_widget.setWindowTitle("Control Panel") ############################ Controls ############################### # For each control: # # -creates items in self.settings # # -connects UI changes to updates in self.settings # # -connects updates in self.settings items to function calls # # -connects button clicks to function calls # ##################################################################### # Load self.settings.New('data_filename', dtype='file') self.settings.data_filename.connect_to_browse_widgets( self.control_widget.lineEdit_LoadFile, self.control_widget.pushButton_BrowseFiles) self.settings.data_filename.updated_value.connect(self.load_file) # Preprocess self.settings.New('R_Nx', dtype=int, initial=1) self.settings.New('R_Ny', dtype=int, initial=1) self.settings.New('bin_r', dtype=int, initial=1) self.settings.New('bin_q', dtype=int, initial=1) self.settings.New('crop_r_showROI', dtype=bool, initial=False) self.settings.New('crop_q_showROI', dtype=bool, initial=False) self.settings.New('isCropped_r', dtype=bool, initial=False) self.settings.New('isCropped_q', dtype=bool, initial=False) self.settings.New('crop_rx_min', dtype=int, initial=0) self.settings.New('crop_rx_max', dtype=int, initial=0) self.settings.New('crop_ry_min', dtype=int, initial=0) self.settings.New('crop_ry_max', dtype=int, initial=0) self.settings.New('crop_qx_min', dtype=int, initial=0) self.settings.New('crop_qx_max', dtype=int, initial=0) self.settings.New('crop_qy_min', dtype=int, initial=0) self.settings.New('crop_qy_max', dtype=int, initial=0) self.settings.R_Nx.connect_bidir_to_widget( self.control_widget.spinBox_Nx) self.settings.R_Ny.connect_bidir_to_widget( self.control_widget.spinBox_Ny) self.settings.bin_r.connect_bidir_to_widget( self.control_widget.spinBox_Bin_Real) self.settings.bin_q.connect_bidir_to_widget( self.control_widget.spinBox_Bin_Diffraction) self.settings.crop_r_showROI.connect_bidir_to_widget( self.control_widget.checkBox_Crop_Real) self.settings.crop_q_showROI.connect_bidir_to_widget( self.control_widget.checkBox_Crop_Diffraction) self.settings.R_Nx.updated_value.connect(self.update_scan_shape_Nx) self.settings.R_Ny.updated_value.connect(self.update_scan_shape_Ny) self.settings.crop_r_showROI.updated_value.connect( self.toggleCropROI_real) self.settings.crop_q_showROI.updated_value.connect( self.toggleCropROI_diffraction) self.control_widget.pushButton_CropData.clicked.connect(self.crop_data) self.control_widget.pushButton_BinData.clicked.connect(self.bin_data) self.control_widget.pushButton_EditFileMetadata.clicked.connect( self.edit_file_metadata) self.control_widget.pushButton_EditDirectoryMetadata.clicked.connect( self.edit_directory_metadata) self.control_widget.pushButton_SaveFile.clicked.connect(self.save_file) self.control_widget.pushButton_SaveDirectory.clicked.connect( self.save_directory) # Virtual detectors self.settings.New('virtual_detector_shape', dtype=int, initial=0) self.settings.New('virtual_detector_mode', dtype=int, initial=0) self.settings.virtual_detector_shape.connect_bidir_to_widget( self.control_widget.buttonGroup_DetectorShape) self.settings.virtual_detector_mode.connect_bidir_to_widget( self.control_widget.buttonGroup_DetectorMode) self.settings.virtual_detector_shape.updated_value.connect( self.update_virtual_detector_shape) self.settings.virtual_detector_mode.updated_value.connect( self.update_virtual_detector_mode) return self.control_widget def setup_diffraction_space_widget(self): """ Set up the diffraction space window. """ # Create pyqtgraph ImageView object self.diffraction_space_widget = pg.ImageView() self.diffraction_space_widget.setImage(np.zeros((512, 512))) # Create virtual detector ROI selector self.virtual_detector_roi = pg.RectROI([256, 256], [50, 50], pen=(3, 9)) self.diffraction_space_widget.getView().addItem( self.virtual_detector_roi) self.virtual_detector_roi.sigRegionChangeFinished.connect( self.update_real_space_view) # Name and return self.diffraction_space_widget.setWindowTitle('Diffraction Space') return self.diffraction_space_widget def setup_real_space_widget(self): """ Set up the real space window. """ # Create pyqtgraph ImageView object self.real_space_widget = pg.ImageView() self.real_space_widget.setImage(np.zeros((512, 512))) # Add point selector connected to displayed diffraction pattern self.real_space_point_selector = pg_point_roi( self.real_space_widget.getView()) self.real_space_point_selector.sigRegionChanged.connect( self.update_diffraction_space_view) # Name and return self.real_space_widget.setWindowTitle('Real Space') return self.real_space_widget def setup_console_widget(self): self.kernel_manager = QtInProcessKernelManager() self.kernel_manager.start_kernel() self.kernel = self.kernel_manager.kernel self.kernel.gui = 'qt4' self.kernel.shell.push({'np': np, 'app': self}) self.kernel_client = self.kernel_manager.client() self.kernel_client.start_channels() self.console_widget = RichJupyterWidget() self.console_widget.setWindowTitle("py4DSTEM IPython Console") self.console_widget.kernel_manager = self.kernel_manager self.console_widget.kernel_client = self.kernel_client return self.console_widget def setup_main_window(self): """ Setup main window, arranging sub-windows inside """ self.main_window = QtWidgets.QWidget() self.main_window.setWindowTitle("py4DSTEM") layout_data = QtWidgets.QHBoxLayout() layout_data.addWidget(self.diffraction_space_widget, 1) layout_data.addWidget(self.real_space_widget, 1) layout_data_and_control = QtWidgets.QHBoxLayout() layout_data_and_control.addWidget(self.control_widget, 0) layout_data_and_control.addLayout(layout_data, 1) layout_data_and_control.setSpacing(0) layout_data_and_control.setContentsMargins(0, 0, 0, 0) self.main_window.setLayout(layout_data_and_control) self.main_window.setGeometry(0, 0, 3600, 1600) self.console_widget.setGeometry(0, 1800, 1600, 250) self.main_window.show() self.main_window.raise_() self.console_widget.show() self.console_widget.raise_() return self.main_window ################################################################## ############## Methods connecting to user inputs ################# ################################################################## ################################################################## # In general, these methods collect any relevant user inputs, # # then pass them to functions defined elsewhere, often in e.g. # # the process directory. # # Additional functionality here should be avoided, to ensure # # consistent output between processing run through the GUI # # or from the command line. # ################################################################## ################ Load ################ def load_file(self): """ Loads a file by creating and storing a DataCube object. """ fname = self.settings.data_filename.val print("Loading file", fname) # Instantiate DataCube object self.datacube = None gc.collect() self.datacube = read(fname) # Update scan shape information self.settings.R_Nx.update_value(self.datacube.R_Nx) self.settings.R_Ny.update_value(self.datacube.R_Ny) # Update data views self.update_diffraction_space_view() self.update_virtual_detector_shape() self.update_virtual_detector_mode() self.update_real_space_view() # Normalize diffraction space view self.diffraction_space_widget.ui.normDivideRadio.setChecked(True) self.diffraction_space_widget.normRadioChanged() # Set scan size maxima self.control_widget.spinBox_Nx.setMaximum(self.datacube.R_N) self.control_widget.spinBox_Ny.setMaximum(self.datacube.R_N) return ############## Preprocess ############## ### Scan Shape ### def update_scan_shape_Nx(self): R_Nx = self.settings.R_Nx.val self.settings.R_Ny.update_value(int(self.datacube.R_N / R_Nx)) R_Ny = self.settings.R_Ny.val self.datacube.set_scan_shape(R_Nx, R_Ny) self.update_real_space_view() def update_scan_shape_Ny(self): R_Ny = self.settings.R_Ny.val self.settings.R_Nx.update_value(int(self.datacube.R_N / R_Ny)) R_Nx = self.settings.R_Nx.val self.datacube.set_scan_shape(R_Nx, R_Ny) self.update_real_space_view() ### Crop ### def toggleCropROI_real(self, show=True): """ If show=True, makes an RIO. If False, removes the ROI. """ if show: self.crop_roi_real = pg.RectROI( [0, 0], [self.datacube.R_Nx, self.datacube.R_Ny], pen=(3, 9), removable=True, translateSnap=True, scaleSnap=True) self.crop_roi_real.setPen(color='r') self.real_space_widget.getView().addItem(self.crop_roi_real) else: if hasattr(self, 'crop_roi_real'): self.real_space_widget.getView().removeItem(self.crop_roi_real) self.crop_roi_real = None else: pass def toggleCropROI_diffraction(self, show=True): """ If show=True, makes an RIO. If False, removes the ROI. """ if show: self.crop_roi_diffraction = pg.RectROI( [0, 0], [self.datacube.Q_Nx, self.datacube.Q_Ny], pen=(3, 9), removable=True, translateSnap=True, scaleSnap=True) self.crop_roi_diffraction.setPen(color='r') self.diffraction_space_widget.getView().addItem( self.crop_roi_diffraction) else: if hasattr(self, 'crop_roi_diffraction'): self.diffraction_space_widget.getView().removeItem( self.crop_roi_diffraction) self.crop_roi_diffraction = None else: pass def crop_data(self): # Diffraction space if self.control_widget.checkBox_Crop_Diffraction.isChecked(): # Get crop limits from ROI slices_q, transforms_q = self.crop_roi_diffraction.getArraySlice( self.datacube.data4D[0, 0, :, :], self.diffraction_space_widget.getImageItem()) slice_qx, slice_qy = slices_q crop_Qx_min, crop_Qx_max = slice_qx.start, slice_qx.stop - 1 crop_Qy_min, crop_Qy_max = slice_qy.start, slice_qy.stop - 1 crop_Qx_min, crop_Qx_max = max(0, crop_Qx_min), min( self.datacube.Q_Nx, crop_Qx_max) crop_Qy_min, crop_Qy_max = max(0, crop_Qy_min), min( self.datacube.Q_Ny, crop_Qy_max) # Move ROI selector x0, y0 = self.virtual_detector_roi.x( ), self.virtual_detector_roi.y() x0_len, y0_len = self.virtual_detector_roi.size() xf = int(x0 * (crop_Qx_max - crop_Qx_min) / self.datacube.Q_Nx) yf = int(y0 * (crop_Qy_max - crop_Qy_min) / self.datacube.Q_Ny) xf_len = int(x0_len * (crop_Qx_max - crop_Qx_min) / self.datacube.Q_Nx) yf_len = int(y0_len * (crop_Qy_max - crop_Qy_min) / self.datacube.Q_Ny) self.virtual_detector_roi.setPos((xf, yf)) self.virtual_detector_roi.setSize((xf_len, yf_len)) # Crop data self.datacube.crop_data_diffraction(crop_Qx_min, crop_Qx_max, crop_Qy_min, crop_Qy_max) # Update settings self.settings.crop_qx_min.update_value(crop_Qx_min) self.settings.crop_qx_max.update_value(crop_Qx_max) self.settings.crop_qy_min.update_value(crop_Qy_min) self.settings.crop_qy_max.update_value(crop_Qy_max) self.settings.isCropped_q.update_value(True) # Uncheck crop checkbox and remove ROI self.control_widget.checkBox_Crop_Diffraction.setChecked(False) # Update display self.update_diffraction_space_view() else: self.settings.isCropped_q.update_value(False) # Real space if self.control_widget.checkBox_Crop_Real.isChecked(): # Get crop limits from ROI slices_r, transforms_r = self.crop_roi_real.getArraySlice( self.datacube.data4D[:, :, 0, 0], self.real_space_widget.getImageItem()) slice_rx, slice_ry = slices_r crop_Rx_min, crop_Rx_max = slice_rx.start, slice_rx.stop - 1 crop_Ry_min, crop_Ry_max = slice_ry.start, slice_ry.stop - 1 crop_Rx_min, crop_Rx_max = max(0, crop_Rx_min), min( self.datacube.R_Nx, crop_Rx_max) crop_Ry_min, crop_Ry_max = max(0, crop_Ry_min), min( self.datacube.R_Ny, crop_Ry_max) # Move point selector x0, y0 = self.real_space_point_selector.x( ), self.real_space_point_selector.y() xf = int(x0 * (crop_Rx_max - crop_Rx_min) / self.datacube.R_Nx) yf = int(y0 * (crop_Ry_max - crop_Ry_min) / self.datacube.R_Ny) self.real_space_point_selector.setPos((xf, yf)) # Crop data self.datacube.crop_data_real(crop_Rx_min, crop_Rx_max, crop_Ry_min, crop_Ry_max) # Update settings self.settings.crop_rx_min.update_value(crop_Rx_min) self.settings.crop_rx_max.update_value(crop_Rx_max) self.settings.crop_ry_min.update_value(crop_Ry_min) self.settings.crop_ry_max.update_value(crop_Ry_max) self.settings.isCropped_r.update_value(True) self.settings.R_Nx.update_value(self.datacube.R_Nx, send_signal=False) self.settings.R_Ny.update_value(self.datacube.R_Ny, send_signal=False) # Uncheck crop checkbox and remove ROI self.control_widget.checkBox_Crop_Real.setChecked(False) # Update display self.update_real_space_view() else: self.settings.isCropped_r.update_value(False) ### Bin ### def bin_data(self): # Get bin factors from GUI bin_factor_Q = self.settings.bin_q.val bin_factor_R = self.settings.bin_r.val if bin_factor_Q > 1: # Move ROI selector x0, y0 = self.virtual_detector_roi.x( ), self.virtual_detector_roi.y() x0_len, y0_len = self.virtual_detector_roi.size() xf = int(x0 / bin_factor_Q) yf = int(y0 / bin_factor_Q) xf_len = int(x0_len / bin_factor_Q) yf_len = int(y0_len / bin_factor_Q) self.virtual_detector_roi.setPos((xf, yf)) self.virtual_detector_roi.setSize((xf_len, yf_len)) # Bin data self.datacube.bin_data_diffraction(bin_factor_Q) # Update display self.update_diffraction_space_view() if bin_factor_R > 1: # Move point selector x0, y0 = self.real_space_point_selector.x( ), self.real_space_point_selector.y() xf = int(x0 / bin_factor_R) yf = int(y0 / bin_factor_R) self.real_space_point_selector.setPos((xf, yf)) # Bin data self.datacube.bin_data_real(bin_factor_R) # Update settings self.settings.R_Nx.update_value(self.datacube.R_Nx, send_signal=False) self.settings.R_Ny.update_value(self.datacube.R_Ny, send_signal=False) # Update display self.update_real_space_view() # Set bin factors back to 1 self.settings.bin_q.update_value(1) self.settings.bin_r.update_value(1) ### Metadata ### def edit_file_metadata(self): """ Creates a popup dialog with tabs for different metadata groups, and fields in each group with current, editable metadata values. """ # Make widget self.EditMetadataWidget = EditMetadataWidget(self.datacube) self.EditMetadataWidget.setWindowTitle("Metadata Editor") self.EditMetadataWidget.show() self.EditMetadataWidget.raise_() # Cancel or save self.EditMetadataWidget.pushButton_Cancel.clicked.connect( self.cancel_editMetadata) self.EditMetadataWidget.pushButton_Save.clicked.connect( self.save_editMetadata) def cancel_editMetadata(self): self.EditMetadataWidget.close() def save_editMetadata(self): print("Updating metadata...") for i in range(self.EditMetadataWidget.tabs.count()): tab = self.EditMetadataWidget.tabs.widget(i) # Get appropriate metadata dict tabname = self.EditMetadataWidget.tabs.tabText(i) metadata_dict_name = [ name for name in self.datacube.metadata.__dict__.keys() if tabname[1:] in name ][0] metadata_dict = getattr(self.datacube.metadata, metadata_dict_name) for row in tab.layout().children(): key = row.itemAt(0).widget().text() try: value = row.itemAt(1).widget().text() except AttributeError: # Catches alternate widget (QPlainTextEdit) in comments tab value = row.itemAt(1).widget().toPlainText() try: value = float(value) except ValueError: pass metadata_dict[key] = value self.EditMetadataWidget.close() print("Done.") def edit_directory_metadata(self): print('edit directory metadata pressed') pass ### Save ### def save_file(self): """ Saving files to the .h5 format. This method: 1) opens a separate dialog 2) puts a name in the "Save as:" field according to the original filename and any preprocessing that's been done 2) Exits with or without saving when 'Save' or 'Cancel' buttons are pressed. """ # Make widget save_path = os.path.splitext( self.settings.data_filename.val)[0] + '.h5' self.save_widget = SaveWidget(save_path) self.save_widget.setWindowTitle("Save as...") self.save_widget.show() self.save_widget.raise_() # Cancel or save self.save_widget.pushButton_Cancel.clicked.connect(self.cancel_saveas) self.save_widget.pushButton_Execute.clicked.connect( self.execute_saveas) def cancel_saveas(self): self.save_widget.close() def execute_saveas(self): f = self.save_widget.lineEdit_SavePath.text() print("Saving file to {}".format(f)) save_dataobject(self.datacube, f) self.save_widget.close() def save_directory(self): print('save directory metadata pressed') pass ################# Virtual Detectors ################# def update_virtual_detector_shape(self): """ Virtual detector shapes are mapped to integers, following the IDs assigned to the radio buttons in VirtualDetectorWidget in dialogs.py. They are as follows: 1: Rectangular 2: Circular 3: Annular """ detector_shape = self.settings.virtual_detector_shape.val x, y = self.diffraction_space_view.shape x0, y0 = x / 2, y / 2 xr, yr = x / 10, y / 10 # Remove existing detector if hasattr(self, 'virtual_detector_roi'): self.diffraction_space_widget.view.scene().removeItem( self.virtual_detector_roi) if hasattr(self, 'virtual_detector_roi_inner'): self.diffraction_space_widget.view.scene().removeItem( self.virtual_detector_roi_inner) if hasattr(self, 'virtual_detector_roi_outer'): self.diffraction_space_widget.view.scene().removeItem( self.virtual_detector_roi_outer) # Rectangular detector if detector_shape == 0: self.virtual_detector_roi = pg.RectROI( [int(x0 - xr / 2), int(y0 - yr / 2)], [int(xr), int(yr)], pen=(3, 9)) self.diffraction_space_widget.getView().addItem( self.virtual_detector_roi) self.virtual_detector_roi.sigRegionChangeFinished.connect( self.update_real_space_view) # Circular detector elif detector_shape == 1: self.virtual_detector_roi = pg.CircleROI( [int(x0 - xr / 2), int(y0 - yr / 2)], [int(xr), int(yr)], pen=(3, 9)) self.diffraction_space_widget.getView().addItem( self.virtual_detector_roi) self.virtual_detector_roi.sigRegionChangeFinished.connect( self.update_real_space_view) # Annular dector elif detector_shape == 2: # Make outer detector self.virtual_detector_roi_outer = pg.CircleROI( [int(x0 - xr), int(y0 - yr)], [int(2 * xr), int(2 * yr)], pen=(3, 9)) self.diffraction_space_widget.getView().addItem( self.virtual_detector_roi_outer) # Make inner detector self.virtual_detector_roi_inner = pg.CircleROI( [int(x0 - xr / 2), int(y0 - yr / 2)], [int(xr), int(yr)], pen=(4, 9), movable=False) self.diffraction_space_widget.getView().addItem( self.virtual_detector_roi_inner) # Connect size/position of inner and outer detectors self.virtual_detector_roi_outer.sigRegionChangeFinished.connect( self.update_annulus_pos) self.virtual_detector_roi_outer.sigRegionChangeFinished.connect( self.update_annulus_radii) self.virtual_detector_roi_inner.sigRegionChangeFinished.connect( self.update_annulus_radii) # Connect to real space view update function self.virtual_detector_roi_outer.sigRegionChangeFinished.connect( self.update_real_space_view) self.virtual_detector_roi_inner.sigRegionChangeFinished.connect( self.update_real_space_view) else: raise ValueError( "Unknown detector shape value {}. Must be 0, 1, or 2.".format( detector_shape)) self.update_virtual_detector_mode() self.update_real_space_view() def update_annulus_pos(self): """ Function to keep inner and outer rings of annulus aligned. """ R_outer = self.virtual_detector_roi_outer.size().x() / 2 R_inner = self.virtual_detector_roi_inner.size().x() / 2 # Only outer annulus is draggable; when it moves, update position of inner annulus x0 = self.virtual_detector_roi_outer.pos().x() + R_outer y0 = self.virtual_detector_roi_outer.pos().y() + R_outer self.virtual_detector_roi_inner.setPos(x0 - R_inner, y0 - R_inner) def update_annulus_radii(self): R_outer = self.virtual_detector_roi_outer.size().x() / 2 R_inner = self.virtual_detector_roi_inner.size().x() / 2 if R_outer < R_inner: x0 = self.virtual_detector_roi_outer.pos().x() + R_outer y0 = self.virtual_detector_roi_outer.pos().y() + R_outer self.virtual_detector_roi_outer.setSize(2 * R_inner + 6) self.virtual_detector_roi_outer.setPos(x0 - R_inner - 3, y0 - R_inner - 3) def update_virtual_detector_mode(self): """ Virtual detector modes are mapped to integers, following the IDs assigned to the radio buttons in VirtualDetectorWidget in dialogs.py. They are as follows: 0: Integrate 1: Difference, X 2: Difference, Y 3: CoM, Y 4: CoM, X """ detector_mode = self.settings.virtual_detector_mode.val detector_shape = self.settings.virtual_detector_shape.val # Integrating detector if detector_mode == 0: if detector_shape == 0: self.get_virtual_image = self.datacube.get_virtual_image_rect_integrate elif detector_shape == 1: self.get_virtual_image = self.datacube.get_virtual_image_circ_integrate elif detector_shape == 2: self.get_virtual_image = self.datacube.get_virtual_image_annular_integrate else: raise ValueError( "Unknown detector shape value {}".format(detector_shape)) # Difference detector elif detector_mode == 1: if detector_shape == 0: self.get_virtual_image = self.datacube.get_virtual_image_rect_diffX elif detector_shape == 1: self.get_virtual_image = self.datacube.get_virtual_image_circ_diffX elif detector_shape == 2: self.get_virtual_image = self.datacube.get_virtual_image_annular_diffX else: raise ValueError( "Unknown detector shape value {}".format(detector_shape)) elif detector_mode == 2: if detector_shape == 0: self.get_virtual_image = self.datacube.get_virtual_image_rect_diffY elif detector_shape == 1: self.get_virtual_image = self.datacube.get_virtual_image_circ_diffY elif detector_shape == 2: self.get_virtual_image = self.datacube.get_virtual_image_annular_diffY else: raise ValueError( "Unknown detector shape value {}".format(detector_shape)) # CoM detector elif detector_mode == 3: if detector_shape == 0: self.get_virtual_image = self.datacube.get_virtual_image_rect_CoMX elif detector_shape == 1: self.get_virtual_image = self.datacube.get_virtual_image_circ_CoMX elif detector_shape == 2: self.get_virtual_image = self.datacube.get_virtual_image_annular_CoMX else: raise ValueError( "Unknown detector shape value {}".format(detector_shape)) elif detector_mode == 4: if detector_shape == 0: self.get_virtual_image = self.datacube.get_virtual_image_rect_CoMY elif detector_shape == 1: self.get_virtual_image = self.datacube.get_virtual_image_circ_CoMY elif detector_shape == 2: self.get_virtual_image = self.datacube.get_virtual_image_annular_CoMY else: raise ValueError( "Unknown detector shape value {}".format(detector_shape)) else: raise ValueError( "Unknown detector mode value {}".format(detector_mode)) self.update_real_space_view() ################## Get virtual images ################## def update_diffraction_space_view(self): roi_state = self.real_space_point_selector.saveState() x0, y0 = roi_state['pos'] xc, yc = int(x0 + 1), int(y0 + 1) # Set the diffraction space image new_diffraction_space_view, success = self.datacube.get_diffraction_space_view( xc, yc) if success: self.diffraction_space_view = new_diffraction_space_view self.diffraction_space_widget.setImage(self.diffraction_space_view, autoLevels=False, autoRange=False) else: pass return def update_real_space_view(self): detector_shape = self.settings.virtual_detector_shape.val # Rectangular detector if detector_shape == 0: # Get slices corresponding to ROI slices, transforms = self.virtual_detector_roi.getArraySlice( self.datacube.data4D[0, 0, :, :], self.diffraction_space_widget.getImageItem()) slice_x, slice_y = slices # Get the virtual image and set the real space view new_real_space_view, success = self.get_virtual_image( slice_x, slice_y) if success: self.real_space_view = new_real_space_view self.real_space_widget.setImage(self.real_space_view, autoLevels=True) else: pass # Circular detector elif detector_shape == 1: # Get slices corresponding to ROI slices, transforms = self.virtual_detector_roi.getArraySlice( self.datacube.data4D[0, 0, :, :], self.diffraction_space_widget.getImageItem()) slice_x, slice_y = slices # Get the virtual image and set the real space view new_real_space_view, success = self.get_virtual_image( slice_x, slice_y) if success: self.real_space_view = new_real_space_view self.real_space_widget.setImage(self.real_space_view, autoLevels=True) else: pass # Annular detector elif detector_shape == 2: # Get slices corresponding to ROI slices, transforms = self.virtual_detector_roi_outer.getArraySlice( self.datacube.data4D[0, 0, :, :], self.diffraction_space_widget.getImageItem()) slice_x, slice_y = slices slices_inner, transforms = self.virtual_detector_roi_inner.getArraySlice( self.datacube.data4D[0, 0, :, :], self.diffraction_space_widget.getImageItem()) slice_inner_x, slice_inner_y = slices_inner R = 0.5 * ((slice_inner_x.stop - slice_inner_x.start) / (slice_x.stop - slice_x.start) + (slice_inner_y.stop - slice_inner_y.start) / (slice_y.stop - slice_y.start)) # Get the virtual image and set the real space view new_real_space_view, success = self.get_virtual_image( slice_x, slice_y, R) if success: self.real_space_view = new_real_space_view self.real_space_widget.setImage(self.real_space_view, autoLevels=True) else: pass else: print( "Error: unknown detector shape value {}. Must be 0, 1, or 2.". format(detector_shape)) return def exec_(self): return self.qtapp.exec_()
class QtipWindow(QtGui.QMainWindow): """ Main Qtip window Note, is the main window now, but the content will later be moved to a libstempo tab, as part of the Piccard suite """ def __init__(self, parent=None, engine='libstempo', \ parfile=None, timfile=None, **kwargs): super(QtipWindow, self).__init__(parent) self.setWindowTitle('QtIpython interface to Piccard/libstempo') # Initialise basic gui elements self.initUI() # Start the embedded IPython kernel self.createIPythonKernel() # Create the display widgets self.createBinaryWidget() self.createPlkWidget() self.createIPythonWidget() self.createOpenSomethingWidget() # Position the widgets self.initQtipLayout() self.setQtipLayout(whichWidget='opensomething', showIPython=False, firsttime=True) # We are still in MAJOR testing mode, so open a test-pulsar right away # (delete this line when going into production) if parfile is None or timfile is None: testpulsar = True else: testpulsar = False # Are we going to open plk straight away? self.requestOpenPlk(testpulsar=testpulsar, parfilename=parfile, \ timfilename=timfile, engine=engine) self.show() def __del__(self): pass def onAbout(self): msg = """ A plk emulator, written in Python. Powered by PyQt, matplotlib, libstempo, and IPython: """ QtGui.QMessageBox.about(self, "About the demo", 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 # Create the menu action items self.openParTimAction = QtGui.QAction('&Open', self) self.openParTimAction.setShortcut('Ctrl+O') self.openParTimAction.setStatusTip('Open par/tim') self.openParTimAction.triggered.connect(self.openParTim) 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) self.toggleBinaryAction = QtGui.QAction('&Binary', self) self.toggleBinaryAction.setShortcut('Ctrl+B') self.toggleBinaryAction.setStatusTip('Toggle binary widget') self.toggleBinaryAction.triggered.connect(self.toggleBinary) self.togglePlkAction = QtGui.QAction('&Plk', self) self.togglePlkAction.setShortcut('Ctrl+P') self.togglePlkAction.setStatusTip('Toggle plk widget') self.togglePlkAction.triggered.connect(self.togglePlk) self.toggleIPythonAction = QtGui.QAction('&IPython', self) self.toggleIPythonAction.setShortcut('Ctrl+I') self.toggleIPythonAction.setStatusTip('Toggle IPython') self.toggleIPythonAction.triggered.connect(self.toggleIPython) self.aboutAction = QtGui.QAction('&About', self) self.aboutAction.setShortcut('Ctrl+A') self.aboutAction.setStatusTip('About Qtip') self.aboutAction.triggered.connect(self.onAbout) self.theStatusBar = QtGui.QStatusBar() #self.statusBar() self.setStatusBar(self.theStatusBar) self.engine_label = QtGui.QLabel("Tempo2") 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 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.toggleBinaryAction) self.viewMenu.addAction(self.togglePlkAction) self.viewMenu.addAction(self.toggleIPythonAction) self.helpMenu = self.menubar.addMenu('&Help') self.helpMenu.addAction(self.aboutAction) # What is the status quo of the user interface? self.showIPython = False self.whichWidget = 'None' self.prevShowIPython = None self.prevWhichWidget = 'None' def createIPythonKernel(self): """ Create the IPython Kernel """ # Create an in-process kernel self.kernelManager = QtInProcessKernelManager() self.kernelManager.start_kernel() self.kernel = self.kernelManager.kernel self.kernelClient = self.kernelManager.client() self.kernelClient.start_channels() self.kernel.shell.enable_matplotlib(gui='inline') # Load the necessary packages in the embedded kernel 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 createIPythonWidget(self): """ Create the IPython widget """ self.consoleWidget = RichIPythonWidget() #self.consoleWidget.setMinimumSize(600, 550) self.consoleWidget.banner = QtipBanner self.consoleWidget.kernel_manager = self.kernelManager self.consoleWidget.kernel_client = self.kernelClient self.consoleWidget.exit_requested.connect(self.toggleIPython) self.consoleWidget.set_default_style(colors='linux') self.consoleWidget.hide() # Register a call-back function for the IPython shell. This one is # executed insite the child-kernel. #self.kernel.shell.register_post_execute(self.postExecute) # # In IPython >= 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: probably should use a signal to implement this call instead of openParTim """ 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 createBinaryWidget(self): """ Create the binary model widget """ self.binaryWidget = BinaryWidget(parent=self.mainFrame) self.binaryWidget.hide() def toggleIPython(self): """ Toggle the IPython widget on or off """ self.setQtipLayout(showIPython=not self.showIPython) def toggleBinary(self): """ Toggle the binary model widget on or off """ self.setQtipLayout(whichWidget='binary') def togglePlk(self): """ Toggle the plk widget on or off """ self.setQtipLayout(whichWidget='plk') def initQtipLayout(self): """ Initialise the Qtip layout """ self.hbox.addWidget(self.openSomethingWidget) self.hbox.addWidget(self.plkWidget) self.hbox.addWidget(self.binaryWidget) 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 # ??? """ 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.binaryWidget.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() elif self.whichWidget.lower() == 'piccard': pass elif self.whichWidget.lower() == 'binary': self.binaryWidget.show() if self.showIPython: self.consoleWidget.show() else: pass if self.whichWidget.lower() == 'plk' and not self.showIPython: self.plkWidget.setFocusToCanvas() elif self.whichWidget.lower() == 'binary' and not self.showIPython: self.binaryWidget.setFocusToCanvas() #elif self.showIPython: # self.consoleWidget.setFocus() def setQtipLayout(self, whichWidget=None, showIPython=None, firsttime=False): """ Given which widgets to show, display the right widgets and hide the rest @param whichWidget: Which widget to show @param showIPython: Whether to show the IPython console """ if not whichWidget is None: self.whichWidget = whichWidget if not showIPython is None: self.showIPython = showIPython # After hiding the widgets, wait 25 (or 0?) miliseconds before showing them again self.hideAllWidgets() QtCore.QTimer.singleShot(0, self.showVisibleWidgets) self.prevWhichWidget = self.whichWidget if self.showIPython != self.prevShowIPython: # IPython has been toggled self.prevShowIPython = self.showIPython if self.showIPython: self.resize(1350, 550) self.mainFrame.resize(1350, 550) else: self.resize(650, 550) self.mainFrame.resize(650, 550) if firsttime: # Set position slightly more to the left of the screen, so we can # still open IPython self.move(200, 100) self.mainFrame.setLayout(self.hbox) self.mainFrame.show() def requestOpenPlk(self, parfilename=None, timfilename=None, \ testpulsar=False, engine='libstempo'): """ 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', showIPython=self.showIPython) 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.openPulsar(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, filename=None, engine='libstempo'): """ Open a par-file and a tim-file """ print("openParTim called with {0}".format(filename)) # Ask the user for a par and tim file, and open these with libstempo if isinstance(filename, str): parfilename = filename else: parfilename = QtGui.QFileDialog.getOpenFileName( self, 'Open par-file', '~/') timfilename = QtGui.QFileDialog.getOpenFileName( self, 'Open tim-file', '~/') # Load the pulsar self.openPulsar(parfilename, timfilename, engine=engine) def openPulsar(self, parfilename, timfilename, engine='libstempo', 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 [libstempo] @param testpulsar: If True, open the test pulsar (J1744, NANOGrav) """ if engine == 'pint': trypint = True else: trypint = False self.engine, pclass = qp.get_engine(trypint=trypint) 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 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 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': cell = "psr = qp." + pclass + "(testpulsar=True)" self.kernel.shell.run_cell(cell) psr = self.kernel.shell.ns_table['user_local']['psr'] else: raise NotImplemented("Only works with PINT/libstempo") # Update the plk widget self.plkWidget.setPulsar(psr) self.binaryWidget.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 """ #print("QtipWindow: mouse click") 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() elif self.whichWidget == 'binary': self.binaryWidget.updatePlot()