Esempio n. 1
1
 def layout(self):
     
     area = DockArea()
     self.win.setCentralWidget(area)
     self.win.resize(2000,1900)
     self.win.setWindowTitle(self.title)
     
     docks=[]
     docks.append(Dock("Parameters", size=(500,1000)))
     docks.append(Dock("Voltage", size=(1000,250)))
     docks.append(Dock("Recovery current", size=(1000,250)))
     docks.append(Dock("Phase plane", size=(1000,500)))
     docks.append(Dock("Test set", size=(500,1000)))  
     docks.append(Dock("Analysis", size=(500,350)))  
                   
     area.addDock(docks[4], 'left')      ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet)
     area.addDock(docks[0], 'right',docks[4]) 
     area.addDock(docks[1], 'right') 
     area.addDock(docks[2], 'bottom',docks[1]) 
     area.addDock(docks[3], 'bottom',docks[2])
     area.addDock(docks[5], 'bottom',docks[0])                 
     for d,w in zip(docks, self.obj.widgets):
         d.addWidget(w)
Esempio n. 2
0
    def __init__(self, fit: chisurf.fitting.fit.FitGroup,
                 parent: QtWidgets.QWidget, **kwargs):
        super().__init__(fit=fit, parent=parent)
        self.layout = QtWidgets.QVBoxLayout(self)
        self.data_x, self.data_y = None, None

        self.pltControl = DistributionPlotControl(self, parent=self, **kwargs)

        area = DockArea()
        self.layout.addWidget(area)
        hide_title = plot_settings['hideTitle']
        d2 = Dock("Fit", size=(500, 400), hideTitle=hide_title)

        self.p1 = QtWidgets.QPlainTextEdit()
        p2 = pg.PlotWidget(useOpenGL=pyqtgraph_settings['useOpenGL'])

        d2.addWidget(p2)

        area.addDock(d2, 'top')

        distribution_plot = p2.getPlotItem()

        self.distribution_plot = distribution_plot
        self.distribution_curve = distribution_plot.plot(x=[0.0],
                                                         y=[0.0],
                                                         pen=pg.mkPen(
                                                             colors['data'],
                                                             width=lw),
                                                         name='Data')
Esempio n. 3
0
    def layout(self):

        area = DockArea()
        self.win.setCentralWidget(area)
        self.win.resize(2000, 1900)
        self.win.setWindowTitle(self.title)

        docks = []
        docks.append(Dock("Parameters", size=(500, 1000)))
        docks.append(Dock("Voltage", size=(1000, 250)))
        docks.append(Dock("Recovery current", size=(1000, 250)))
        docks.append(Dock("Phase plane", size=(1000, 500)))
        docks.append(Dock("Test set", size=(500, 1000)))
        docks.append(Dock("Analysis", size=(500, 350)))

        area.addDock(
            docks[4], 'left'
        )  ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet)
        area.addDock(docks[0], 'right', docks[4])
        area.addDock(docks[1], 'right')
        area.addDock(docks[2], 'bottom', docks[1])
        area.addDock(docks[3], 'bottom', docks[2])
        area.addDock(docks[5], 'bottom', docks[0])
        for d, w in zip(docks, self.obj.widgets):
            d.addWidget(w)
    def setup_widgets(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        dock_position = Dock("Position")
        dock_area.addDock(dock_position)

        # Position 2d plot
        position_graphics = pg.GraphicsLayoutWidget()
        position_graphics.show()
        view = position_graphics.addViewBox()
        self.position_img = pg.ImageItem(border='w')
        view.addItem(self.position_img)
        dock_position.addWidget(position_graphics)

        # Status widget
        dock_status = Dock("Status", size=(800, 1))
        dock_area.addDock(dock_status, 'top')
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.spin_box = Qt.QSpinBox(value=1)
        self.spin_box.setMaximum(10)
        self.spin_box.setSuffix(" Threshold")

        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        dock_status.addWidget(cw)

        self.spin_box.valueChanged.connect(lambda value: self.send_command(str(value)))
Esempio n. 5
0
    def setup_widgets(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        dock_position = Dock("Position")
        dock_area.addDock(dock_position)

        # Position 2d plot
        position_graphics = pg.GraphicsLayoutWidget()
        position_graphics.show()
        view = position_graphics.addViewBox()
        self.position_img = pg.ImageItem(border='w')
        view.addItem(self.position_img)
        dock_position.addWidget(position_graphics)

        # Status widget
        dock_status = Dock("Status", size=(800, 1))
        dock_area.addDock(dock_status, 'top')
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.spin_box = Qt.QSpinBox(value=1)
        self.spin_box.setMaximum(10)
        self.spin_box.setSuffix(" Threshold")

        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        dock_status.addWidget(cw)

        self.spin_box.valueChanged.connect(
            lambda value: self.send_command(str(value)))
Esempio n. 6
0
    def __init__(self, scan_z, webcam_focus_lock, *args, **kwargs):

        super().__init__(*args, **kwargs)

        self.scan_z = scan_z

        self.filewarning = FileWarning()

        # Dock widget
        dockArea = DockArea()

        # Focus lock widget
        focusDock = Dock("Focus lock", size=(500, 500))
        self.focusWidget = focus.FocusWidget(self.scan_z, webcam_focus_lock)
        focusDock.addWidget(self.focusWidget)
        dockArea.addDock(focusDock, "left")

        self.setWindowTitle('Tempesta - Focus lock edition')
        self.cwidget = QtGui.QWidget()
        self.setCentralWidget(self.cwidget)

        # Widgets' layout
        layout = QtGui.QGridLayout()
        self.cwidget.setLayout(layout)
        layout.addWidget(dockArea, 0, 0, 1, 1)
    def __init__(self, fit: chisurf.fitting.fit.FitGroup, *args, **kwargs):
        super(ParameterScanPlot, self).__init__(fit)

        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)

        self.data_x, self.data_y = None, None

        self.pltControl = ParameterScanWidget(model=fit.model, parent=self)

        area = DockArea()
        self.layout.addWidget(area)
        hide_title = plot_settings['hideTitle']
        d2 = Dock("Chi2-Surface", hideTitle=hide_title)

        self.p1 = QtWidgets.QPlainTextEdit()
        p2 = pg.PlotWidget()

        d2.addWidget(p2)

        area.addDock(d2, 'top')

        distribution_plot = p2.getPlotItem()

        self.distribution_plot = distribution_plot
        self.distribution_curve = distribution_plot.plot(x=[0.0],
                                                         y=[0.0],
                                                         pen=pg.mkPen(
                                                             colors['data'],
                                                             width=lw),
                                                         name='Data')
Esempio n. 8
0
 def create_dock(self):
     area = DockArea()
     self.obj_graph['param']['dock'] = Dock("setting parameters")
     self.obj_graph['plot']['dock'] = Dock("graphic 1")
     self.obj_graph['plot2']['dock'] = Dock("graphic 2")
     area.addDock(self.obj_graph['param']['dock'], 'left')
     area.addDock(self.obj_graph['plot']['dock'], 'right')
     area.addDock(self.obj_graph['plot2']['dock'], 'bottom',
                  self.obj_graph['plot']['dock'])
     self.setCentralWidget(area)
Esempio n. 9
0
class MainWindow(QtWidgets.QMainWindow):
    """The only window of the application."""
    def __init__(self, settings):
        super(MainWindow, self).__init__()
        self.settings = settings

        self.setupUi()

        self.dock_area = DockArea()
        self.setCentralWidget(self.dock_area)

        self.createDocks()

        self.loadSettings()
        self.setWindowTitle('Rb Lock')

    def setupUi(self):
        pass

    def createDocks(self):
        self.rb_lock_widget = RbLockWidget(self.settings, self)
        self.rb_lock_widget_dock = Dock('Rb Lock', widget=self.rb_lock_widget)
        self.dock_area.addDock(self.rb_lock_widget_dock)

    def loadSettings(self):
        """Load window state from self.settings"""

        self.settings.beginGroup('mainwindow')
        geometry = self.settings.value('geometry')
        state = self.settings.value('windowstate')
        dock_string = str(self.settings.value('dockstate'))
        if dock_string is not "":
            dock_state = eval(dock_string)
            self.dock_area.restoreState(dock_state)
        self.settings.endGroup()

        self.restoreGeometry(geometry)
        self.restoreState(state)

    def saveSettings(self):
        """Save window state to self.settings."""
        self.settings.beginGroup('mainwindow')
        self.settings.setValue('geometry', self.saveGeometry())
        self.settings.setValue('windowstate', self.saveState())
        dock_state = self.dock_area.saveState()
        # dock_state returned here is a python dictionary. Coundn't find a good
        # way to save dicts in QSettings, hence just using representation
        # of it.
        self.settings.setValue('dockstate', repr(dock_state))
        self.settings.endGroup()

    def closeEvent(self, event):
        self.rb_lock_widget.saveSettings()
        self.saveSettings()
    def _add_btn_layout(self):
        # add a DockArea for buttons
        area = DockArea()
        dock = Dock("Functions")
        area.addDock(dock)
        area.show()

        self.vlayout.addWidget(area, 1, 1)
        btn_layout = pg.LayoutWidget()
        dock.addWidget(btn_layout)
        self.btn_layout = btn_layout
Esempio n. 11
0
class MainWindow(QMainWindow, Ui_MainWindow):
    """The only window of the application."""

    def __init__(self, settings):
        super(MainWindow, self).__init__()
        self.settings = settings

        self.setupUi(self)

        self.dock_area = DockArea()
        self.setCentralWidget(self.dock_area)

        self.createDocks()

        self.loadSettings()

    def createDocks(self):
        self.zmq_subscriber = ZMQSubscriber(self.settings, self)
        self.zmq_subscriber_dock = Dock('Subscriber',
                                        widget=self.zmq_subscriber)
        self.dock_area.addDock(self.zmq_subscriber_dock)

    def loadSettings(self):
        """Load window state from self.settings"""

        self.settings.beginGroup('mainwindow')
        geometry = self.settings.value('geometry').toByteArray()
        state = self.settings.value('windowstate').toByteArray()
        dock_string = str(self.settings.value('dockstate').toString())
        if dock_string is not "":
            dock_state = eval(dock_string)
            self.dock_area.restoreState(dock_state)
        self.settings.endGroup()

        self.restoreGeometry(geometry)
        self.restoreState(state)

    def saveSettings(self):
        """Save window state to self.settings."""
        self.settings.beginGroup('mainwindow')
        self.settings.setValue('geometry', self.saveGeometry())
        self.settings.setValue('windowstate', self.saveState())
        dock_state = self.dock_area.saveState()
        # dock_state returned here is a python dictionary. Coundn't find a good
        # way to save dicts in QSettings, hence just using representation
        # of it.
        self.settings.setValue('dockstate', repr(dock_state))
        self.settings.endGroup()

    def closeEvent(self, event):
        self.zmq_subscriber.saveSettings()
        self.saveSettings()
Esempio n. 12
0
    def setup_widgets(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        dock_position = Dock("Position")
        dock_area.addDock(dock_position)

        # Position 2d plot
        position_graphics = pg.GraphicsLayoutWidget()
        position_graphics.show()
        view = position_graphics.addViewBox()
        self.position_img = pg.ImageItem(border='w')
        view.addItem(self.position_img)
        dock_position.addWidget(position_graphics)
Esempio n. 13
0
    def create_graph_views(self):
        """
        Creates the window containing the graph views.
        :return: None
        """
        dock_area = DockArea()
        self.setCentralWidget(dock_area)

        dock_3d = Dock('3D')
        dock_area.addDock(dock_3d)

        dock_1d = Dock('1D')
        dock_area.addDock(dock_1d, 'above', dock_3d)

        dock_2d = Dock('2D')
        dock_area.addDock(dock_2d, 'above', dock_3d)

        self.plot_3d = Plot3DWidget(self.model_wrapper, dock_3d)
        dock_3d.addWidget(self.plot_3d)

        self.plot_2d = Plot2DWidget(self.model_wrapper, self.statusBar(),
                                    dock_2d)
        dock_2d.addWidget(self.plot_2d)

        self.plot_1d = Plot1DWidget(self.model_wrapper, self.statusBar(),
                                    dock_1d)
        dock_1d.addWidget(self.plot_1d)

        # TODO: move away from this function
        dock_list = Dock('integration')
        dock_area.addDock(dock_list)
        dock_list.addWidget(IntegrationList(self.model_wrapper, dock_list))
Esempio n. 14
0
def main():
    app = QtWidgets.QApplication(sys.argv)
    win = QtWidgets.QMainWindow()
    area = DockArea()
    win.setCentralWidget(area)
    win.show()

    dock = Dock(name='Test Dock', area=area)
    area.addDock(dock)

    QtCore.QThread.sleep(2)
    dock.close()
    QtWidgets.QApplication.processEvents()
    sys.exit(app.exec_())
    def setup_plots(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        dock_position = Dock("Position Correlation")
        dock_area.addDock(dock_position)

        # Position 2d plot
        position_graphics = pg.GraphicsLayoutWidget()
        position_graphics.show()
        view = position_graphics.addViewBox()
        self.position_img = pg.ImageItem(border='w')
        view.addItem(self.position_img)
        dock_position.addWidget(position_graphics)
Esempio n. 16
0
    def __init__(self, fit):
        super().__init__(fit=fit)

        self.trajectory = fit.model
        self.source = fit.model

        self.layout = QtWidgets.QVBoxLayout(self)
        area = DockArea()
        self.layout.addWidget(area)
        hide_title = chisurf.settings.gui['plot']['hideTitle']
        d1 = Dock("RMSD")
        d2 = Dock("dRMSD")
        d3 = Dock("Energy")
        d4 = Dock("FRET")

        p1 = pg.PlotWidget()
        p2 = pg.PlotWidget()
        p3 = pg.PlotWidget()
        p4 = pg.PlotWidget()

        d1.addWidget(p1)
        d2.addWidget(p2)
        d3.addWidget(p3)
        d4.addWidget(p4)

        area.addDock(d1, 'top')
        area.addDock(d2, 'right', d1)
        area.addDock(d3, 'bottom')
        area.addDock(d4, 'right', d3)

        # RMSD - Curves
        self.rmsd_plot = p1.getPlotItem()
        self.drmsd_plot = p2.getPlotItem()
        self.energy_plot = p3.getPlotItem()
        self.fret_plot = p4.getPlotItem()

        lw = chisurf.settings.gui['plot']['line_width']
        self.rmsd_curve = self.rmsd_plot.plot(x=[0.0],
                                              y=[0.0],
                                              pen=pg.mkPen(colors['irf'],
                                                           width=lw),
                                              name='rmsd')
        self.drmsd_curve = self.drmsd_plot.plot(x=[0.0],
                                                y=[0.0],
                                                pen=pg.mkPen(colors['data'],
                                                             width=lw),
                                                name='drmsd')
        self.energy_curve = self.energy_plot.plot(x=[0.0],
                                                  y=[0.0],
                                                  pen=pg.mkPen(
                                                      colors['models'],
                                                      width=lw),
                                                  name='energy')
        self.fret_curve = self.fret_plot.plot(x=[0.0],
                                              y=[0.0],
                                              pen=pg.mkPen(colors['models'],
                                                           width=lw),
                                              name='fret')
Esempio n. 17
0
class Tab(QWidget):
    def __init__(self, num_tabs=3):
        super().__init__()
        self.num_tabs = num_tabs

        self.initUI()

    def initUI(self):
        self.layout = QGridLayout(self)
        self.dock_area = DockArea()
        self.layout.addWidget(self.dock_area)
        self.add_docks()

    def add_docks(self):
        self.d1 = QDockWidget('d1')
        self.d2 = QDockWidget('d2')
        self.dock_area.addDock(self.d1.dock)
Esempio n. 18
0
    def initDialog(self,results=None,KData=None,bDrawText=False):
        # 1) creates layouts
        dialog = QtGui.QDialog()   
        mainLayout = QtGui.QHBoxLayout()
        rightLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(rightLayout)
        dialog.setLayout(mainLayout)        
        dialog.setWindowTitle(('Strategy Results'))
        # 2) creates widgets         
        from Widgets.pgCandleWidgetCross import pgCandleWidgetCross
        from Widgets.pgCrossAddition import pgCrossAddition
        from pyqtgraph.dockarea import DockArea,Dock     
        
    

        area = DockArea()
        ## Create docks, place them into the window one at a time.
        ## Note that size arguments are only a suggestion; docks will still have to
        ## fill the entire dock area and obey the limits of their internal widgets.
        d1 = Dock("price", size=(200,100))
        d2 = Dock("position", size=(200,100))


        area.addDock(d1, 'bottom')  
        area.addDock(d2, 'bottom')  

        rightLayout.addWidget(area)
       
       
       
        
        pgCandleView = pgCandleWidgetCross(dataForCandle=KData)            
        PyqtGraphindicators = pgCrossAddition()
        toShow = pgCandleView
        self.pricePlot(toShow) 
        d1.addWidget(toShow)   
        
        PyqtGraphPosition = pgCrossAddition()
        self.positionPlot(PyqtGraphPosition)        
        d2.addWidget(PyqtGraphPosition)
        PyqtGraphPosition.showGrid(x=True, y=True)
        
        PyqtGraphPosition.setXLink(toShow)        
        return dialog
Esempio n. 19
0
def make_sequential_flowchart_with_gui(clsList, inputData=None, log=True):
    nodes, fc = make_sequential_flowchart(clsList, inputData=inputData)

    win = QtGui.QMainWindow()
    area = DockArea()
    win.setCentralWidget(area)

    for node in nodes:
        if node.useUi and node.uiClass is not None:
            nodeDock = Dock(node.name())
            nodeDock.addWidget(node.ui)
            area.addDock(nodeDock)

    if log:
        logDock = Dock('Log')
        logDock.addWidget(plottrlog.setupLogging(makeDialog=False))
        area.addDock(logDock, 'bottom')

    win.show()

    return nodes, fc, win
Esempio n. 20
0
File: UI.py Progetto: queezz/AXUV
class UIWindow(object):
    def __init__(self):
        super().__init__()
        pg.setConfigOptions(imageAxisOrder='row-major')

        self.MainWindow = QtGui.QMainWindow()
        self.tabwidg = QtGui.QTabWidget()
        self.area = DockArea()
        self.plotDock = Dock("Plots", size=(400, 400))
        self.surfaceDock = Dock("Contour", size=(250, 400))
        self.controlDock = ControlDock()
        self.controlDock.setStretch(*(10, 100))
        self.graph = Graph()
        self.contour = Contour()

        self.MainWindow.setGeometry(20, 50, 1200, 600)
        self.MainWindow.setObjectName("Monitor")
        self.MainWindow.setWindowTitle("AXUV tool")
        self.MainWindow.statusBar().showMessage('')
        self.MainWindow.setAcceptDrops(True)
        self.__setLayout()

    def __setLayout(self):
        self.MainWindow.setCentralWidget(self.tabwidg)
        self.tabwidg.addTab(self.area, "Data")

        self.area.addDock(self.plotDock, "right")
        self.area.addDock(self.controlDock, "left")
        self.area.addDock(self.surfaceDock, "bottom", self.controlDock)

        self.plotDock.addWidget(self.graph)
        self.surfaceDock.addWidget(self.contour)

    def showMain(self):
        self.MainWindow.show()
Esempio n. 21
0
    def run(self):  # 2. Implement run()
        window = QMainWindow()
        version = self.build_settings['version']
        window.setWindowTitle("real_time_vocoder.py v" + version)
        area = DockArea()
        d1 = Dock("Plot Widget", size=(800, 200), closable=False)
        d2 = Dock("Parameter Widget", size=(200, 200), closable=False)
        # parameter_widget2 = parameterWidget()
        # parameter_widget.setObjectName("F0Slider")
        # parameter_widget.setStyleSheet("""
        #     QSlider{
        #         background:red;
        #         size:100px;
        #     }
        # """)
        self.spectogram_widget = SpectrogramWidget()
        self.wave_widget = WaveWidget()
        self.mic = MicrophoneRecorder(True,
                                      self.spectogram_widget.read_collected,
                                      self.wave_widget.read_collected)

        # コントロールのレイアウト設定
        self.createParamterWidget()

        d1.addWidget(self.spectogram_widget)
        d1.addWidget(self.wave_widget)
        d2.addWidget(self.mainControl)
        area.addDock(d1)
        area.addDock(d2, "right")

        interval = CHUNKS / FS
        t = QtCore.QTimer()
        t.timeout.connect(self.mic.read)
        t.start(interval / 1000)  #QTimer takes ms
        window.resize(800, 400)
        window.setCentralWidget(area)
        window.show()
        self.app.aboutToQuit.connect(self.mic.close)
        return self.app.exec_()  # 3. End run() with this line
Esempio n. 22
0
 def setup_status_widget(self, parent):  # Visualizes the nodes + their connections + CPU usage
     # Status dock area showing setup
     dock_area = DockArea()
     parent.addTab(dock_area, 'Status')
     self.status_dock = Dock("Status")
     dock_area.addDock(self.status_dock)
     # GraphicsLayout to align graphics
     status_graphics_widget = pg.GraphicsLayoutWidget()
     status_graphics_widget.show()
     self.status_dock.addWidget(status_graphics_widget)
     try:
         self.configuration['receiver']
     except KeyError:
         return
     # Create nodes with links from configuration file for converter/receiver
     for receiver_index, (receiver_name, receiver_settings) in enumerate(self.configuration['receiver'].items()):
         # Add receiver info
         view = status_graphics_widget.addViewBox(row=receiver_index, col=5, lockAspect=True, enableMouse=False)
         text = pg.TextItem('Receiver\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200))
         text.setPos(0.5, 0.5)
         view.addItem(text)
         # Add corresponding producer info
         try:
             if self.configuration['converter']:
                 try:
                     actual_converter = self.configuration['converter'][receiver_name]
                     view = status_graphics_widget.addViewBox(row=receiver_index, col=1, lockAspect=True, enableMouse=False)
                     text = pg.TextItem('Producer\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200))
                     text.setPos(0.5, 0.5)
                     view.addItem(text)
                     view = status_graphics_widget.addViewBox(row=receiver_index, col=3, lockAspect=True, enableMouse=False)
                     text = pg.TextItem('Converter\n%s' % receiver_settings, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200))
                     text.setPos(0.5, 0.5)
                     view.addItem(text)
                 except KeyError:  # no converter for receiver
                     pass
         except KeyError:  # No converter defined in configruation
             pass
Esempio n. 23
0
 def setup_status_widget(self, parent):  # Visualizes the nodes + their connections + CPU usage
     # Status dock area showing setup
     dock_area = DockArea()
     parent.addTab(dock_area, 'Status')
     self.status_dock = Dock("Status")
     dock_area.addDock(self.status_dock)
     # GraphicsLayout to align graphics
     status_graphics_widget = pg.GraphicsLayoutWidget()
     status_graphics_widget.show()
     self.status_dock.addWidget(status_graphics_widget)
     try:
         self.configuration['receiver']
     except KeyError:
         return
     # Create nodes with links from configuration file for converter/receiver
     for receiver_index, (receiver_name, receiver_settings) in enumerate(self.configuration['receiver'].items()):
         # Add receiver info
         view = status_graphics_widget.addViewBox(row=receiver_index, col=5, lockAspect=True, enableMouse=False)
         text = pg.TextItem('Receiver\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200))
         text.setPos(0.5, 0.5)
         view.addItem(text)
         # Add corresponding producer info
         try:
             if self.configuration['converter']:
                 try:
                     actual_converter = self.configuration['converter'][receiver_name]
                     view = status_graphics_widget.addViewBox(row=receiver_index, col=1, lockAspect=True, enableMouse=False)
                     text = pg.TextItem('Producer\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200))
                     text.setPos(0.5, 0.5)
                     view.addItem(text)
                     view = status_graphics_widget.addViewBox(row=receiver_index, col=3, lockAspect=True, enableMouse=False)
                     text = pg.TextItem('Converter\n%s' % receiver_settings, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200))
                     text.setPos(0.5, 0.5)
                     view.addItem(text)
                 except KeyError:  # no converter for receiver
                     pass
         except KeyError:  # No converter defined in configruation
             pass
Esempio n. 24
0
 def create_dock(self):
     area = DockArea()
     self.obj_graph['param']['dock'] = Dock("setting parameters")
     self.obj_graph['plot']['dock'] = Dock("R (V) function of current (mA)")
     self.obj_graph['plot2']['dock'] = Dock("Phi (deg) function of current (mA)")
     area.addDock(self.obj_graph['param']['dock'], 'left')
     area.addDock(self.obj_graph['plot']['dock'],'right')
     area.addDock(self.obj_graph['plot2']['dock'],'bottom',self.obj_graph['plot']['dock'])
     self.setCentralWidget(area)
Esempio n. 25
0
class PV_Setup(QWidget):
    """
    This Widget sets up and shows all the PV necessary for SAXS/WAXS/GI-SAXS/GI-WAXS/ASAXS data collection
    """
    def __init__(self,parent=None):
        QWidget.__init__(self, parent)
        self.motors={}
        self.scalars={}
        self.detectors={}
        self.devices={}

        self.vbLayout=QVBoxLayout(self)
        self.setupDockArea=DockArea(self)
        self.vbLayout.addWidget(self.setupDockArea)
        
        #Creating the docks
        self.motorDock=Dock("Motors",size=(300,300))
        self.scalarDock=Dock("Scalars",size=(300,300))
        self.detectorDock=Dock("Area Detectors",size=(300,300))
        self.deviceDock=Dock("Devices",size=(300,300))
        
        #Adding the Docks to the DockArea
        self.setupDockArea.addDock(self.detectorDock)
        self.setupDockArea.addDock(self.scalarDock)
        self.setupDockArea.addDock(self.motorDock)
        self.setupDockArea.addDock(self.deviceDock)

        #Moving the Docks w.r.t each other to position them as tabs
        self.setupDockArea.moveDock(self.detectorDock,'above',self.deviceDock)
        self.setupDockArea.moveDock(self.scalarDock,'above',self.detectorDock)
        self.setupDockArea.moveDock(self.motorDock,'above',self.scalarDock)

        #Populating the docks with other widgets
        self.motorPV=PVInfo_Widget(parent=self,pvType='Motor')
        self.motorDock.addWidget(self.motorPV.layout)
        self.scalarPV=PVInfo_Widget(parent=self,pvType='Scalar')
        self.scalarDock.addWidget(self.scalarPV.layout)
        self.detectorPV=PVInfo_Widget(parent=self,pvType='Detector')
        self.detectorDock.addWidget(self.detectorPV.layout)
        self.devicePV=PVInfo_Widget(parent=self,pvType='Device')
        self.deviceDock.addWidget(self.devicePV.layout)
Esempio n. 26
0
    def initDialogSummary(self, result, KData=None):
        # 1) creates layouts
        dialog = QtGui.QDialog()
        mainLayout = QtGui.QHBoxLayout()
        rightLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(rightLayout)
        dialog.setLayout(mainLayout)
        dialog.setWindowTitle(('Strategy Results'))

        import os, sys
        xpower = os.path.abspath(
            os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
                         os.pardir, 'midProjects', 'histdataUI'))
        sys.path.append(xpower)

        from Widgets.pgCandleWidgetCross import pgCandleWidgetCross
        from Widgets.pgCrossAddition import pgCrossAddition
        from pyqtgraph.dockarea import DockArea, Dock
        area = DockArea()
        rightLayout.addWidget(area)

        # 2) creates widgets
        #  2.1)candle
        pgCandleView = pgCandleWidgetCross(dataForCandle=KData)
        dCandle = Dock("candles", closable=True,
                       size=(200,
                             300))  ## give this dock the minimum possible size
        area.addDock(dCandle, 'bottom')
        dCandle.addWidget(pgCandleView)
        # 2) creates widgets
        # 2.3)position_cost
        if (True):
            PyqtGraphPositionCost = pgCrossAddition()
            self.availableCashPlot(PyqtGraphPositionCost)
            dAvailableCash = Dock("available_cash",
                                  closable=True,
                                  size=(200, 100))
            area.addDock(dAvailableCash, 'bottom')
            dAvailableCash.addWidget(PyqtGraphPositionCost)
            PyqtGraphPositionCost.setXLink(pgCandleView)
        # 2.3)position_cost
        if (True):
            PyqtGraphPositionCost = pgCrossAddition()
            self.portfolioPlot(PyqtGraphPositionCost)
            dPortfolioValue = Dock("portfolio_value",
                                   closable=True,
                                   size=(200, 100))
            area.addDock(dPortfolioValue, 'bottom')
            dPortfolioValue.addWidget(PyqtGraphPositionCost)
            PyqtGraphPositionCost.setXLink(pgCandleView)
        return dialog
Esempio n. 27
0
    def initDialogSummary(self,result,KData=None):
        # 1) creates layouts
        dialog = QtGui.QDialog()   
        mainLayout = QtGui.QHBoxLayout()
        rightLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(rightLayout)
        dialog.setLayout(mainLayout)        
        dialog.setWindowTitle(('Strategy Results'))

        import os,sys        
        xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdataUI'))
        sys.path.append(xpower)

        from Widgets.pgCandleWidgetCross import pgCandleWidgetCross
        from Widgets.pgCrossAddition import pgCrossAddition
        from pyqtgraph.dockarea import DockArea,Dock 
        area = DockArea()   
        rightLayout.addWidget(area)


        # 2) creates widgets 
        #  2.1)candle        
        pgCandleView = pgCandleWidgetCross(dataForCandle=KData)        
        dCandle = Dock("candles",closable=True, size=(200,300))     ## give this dock the minimum possible size
        area.addDock(dCandle, 'bottom') 
        dCandle.addWidget(pgCandleView)       
        # 2) creates widgets 
        # 2.3)position_cost 
        if(True):
            PyqtGraphPositionCost = pgCrossAddition()
            self.availableCashPlot(PyqtGraphPositionCost)
            dAvailableCash = Dock("available_cash",closable=True, size=(200,100))
            area.addDock(dAvailableCash, 'bottom')        
            dAvailableCash.addWidget(PyqtGraphPositionCost)             
            PyqtGraphPositionCost.setXLink(pgCandleView)         
        # 2.3)position_cost 
        if(True):
            PyqtGraphPositionCost = pgCrossAddition()
            self.portfolioPlot(PyqtGraphPositionCost)
            dPortfolioValue = Dock("portfolio_value",closable=True, size=(200,100))
            area.addDock(dPortfolioValue, 'bottom')        
            dPortfolioValue.addWidget(PyqtGraphPositionCost)             
            PyqtGraphPositionCost.setXLink(pgCandleView) 
        return dialog        
Esempio n. 28
0
    def __init__(self, fit: chisurf.fitting.fit.FitGroup, *args, **kwargs):
        super().__init__(fit=fit, *args, **kwargs)
        # plot control dialog
        self.pltControl = AvPlotControl(self, **kwargs)
        self.layout = QtWidgets.QVBoxLayout(self)

        area = DockArea()
        self.layout.addWidget(area)

        hide_title = chisurf.settings.gui['plot']['hideTitle']
        d1 = Dock("quenching", size=(300, 300), hideTitle=hide_title)
        d2 = Dock("diffusion", size=(300, 300), hideTitle=hide_title)
        d3 = Dock("equilibrium", size=(300, 300), hideTitle=hide_title)

        area.addDock(d1, 'top')
        area.addDock(d2, 'right', d1)
        area.addDock(d3, 'bottom')

        self.quenching_widget = gl.GLViewWidget()
        self.quenching_widget.opts['distance'] = 100

        d1.addWidget(self.quenching_widget)
Esempio n. 29
0
class AnalysisDockWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'designer', 'analysis_dock.ui'), self)

        self.histogram_widget = HistogramWidget(self)
        self.tracks_widget = TracksWidget(self)
        self.intensities_widget = GraphMonitorWidget(self)

        self.dockarea = DockArea()
        self.layout().insertWidget(0, self.dockarea)

        self.histogram_dock = Dock(name='Histogram', closable=False)
        self.histogram_dock.addWidget(self.histogram_widget)
        self.dockarea.addDock(self.histogram_dock)

        self.tracks_dock = Dock(name='Trajectories', closable=False)
        self.tracks_dock.addWidget(self.tracks_widget)
        self.dockarea.addDock(self.tracks_dock)

        self.intensities_dock = Dock(name='Intensities', closable=False)
        self.intensities_dock.addWidget(self.intensities_widget)
        self.dockarea.addDock(self.intensities_dock)
    def setup_widgets(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        # Occupancy Docks
        self.occupancy_images = []

        for plane in range(3):  # Loop over 3 * 2 plot widgets
            # Dock left
            dock_occcupancy = Dock("Occupancy plane %d" % 2 * plane, size=(100, 200))
            dock_area.addDock(dock_occcupancy)
            occupancy_graphics = pg.GraphicsLayoutWidget()  # Plot docks
            occupancy_graphics.show()
            view = occupancy_graphics.addViewBox()
            self.occupancy_images.append(pg.ImageItem(border='w'))
            view.addItem(self.occupancy_images[2 * plane])
            view.setRange(QtCore.QRectF(0, 0, 80, 336))
            dock_occcupancy.addWidget(occupancy_graphics)

            # Dock right
            dock_occcupancy_2 = Dock("Occupancy plane %d" % (2 * plane + 1), size=(100, 200))
            dock_area.addDock(dock_occcupancy_2, 'right', dock_occcupancy)  
            occupancy_graphics = pg.GraphicsLayoutWidget()  # Plot docks
            occupancy_graphics.show()
            view = occupancy_graphics.addViewBox()
            self.occupancy_images.append(pg.ImageItem(border='w'))
            view.addItem(self.occupancy_images[2 * plane + 1])
            view.setRange(QtCore.QRectF(0, 0, 80, 336))
            dock_occcupancy_2.addWidget(occupancy_graphics)

        # dock_event_status = Dock("Event status", size=(400, 400))
        # dock_trigger_status = Dock("Trigger status", size=(400, 400))

        # dock_area.addDock(dock_trigger_status, 'above', dock_service_records)
        # dock_area.addDock(dock_event_status, 'above', dock_trigger_status)
        dock_status = Dock("Status", size=(800, 40))
        dock_area.addDock(dock_status, 'top')

        # Status dock on top
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz")
        self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz")
        self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz")
        self.timestamp_label = QtGui.QLabel("Data Timestamp\n")
        self.plot_delay_label = QtGui.QLabel("Plot Delay\n")
        self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n")
        self.spin_box = Qt.QSpinBox(value=0)
        self.spin_box.setMaximum(1000000)
        self.spin_box.setSuffix(" Readouts")
        self.reset_button = QtGui.QPushButton('Reset')
        self.noisy_checkbox = QtGui.QCheckBox('Mask noisy pixels')
        layout.addWidget(self.timestamp_label, 0, 0, 0, 1)
        layout.addWidget(self.plot_delay_label, 0, 1, 0, 1)
        layout.addWidget(self.rate_label, 0, 2, 0, 1)
        layout.addWidget(self.hit_rate_label, 0, 3, 0, 1)
        layout.addWidget(self.event_rate_label, 0, 4, 0, 1)
        layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1)
        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        layout.addWidget(self.noisy_checkbox, 0, 7, 0, 1)
        layout.addWidget(self.reset_button, 0, 8, 0, 1)
        dock_status.addWidget(cw)

        # Connect widgets
        self.reset_button.clicked.connect(lambda: self.send_command('RESET'))
        self.spin_box.valueChanged.connect(lambda value: self.send_command(str(value)))
        self.noisy_checkbox.stateChanged.connect(lambda value: self.send_command('MASK %d' % value))

#         event_status_widget = pg.PlotWidget()
#         self.event_status_plot = event_status_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
#         event_status_widget.showGrid(y=True)
#         dock_event_status.addWidget(event_status_widget)

#         trigger_status_widget = pg.PlotWidget()
#         self.trigger_status_plot = trigger_status_widget.plot(np.linspace(-0.5, 7.5, 9), np.zeros((8)), stepMode=True)
#         trigger_status_widget.showGrid(y=True)
#         dock_trigger_status.addWidget(trigger_status_widget)

        self.plot_delay = 0
Esempio n. 31
0
class DockAreaTabWidgetBase(QtGui.QWidget):
    
    def __init__(self, *args, **kwargs):
        self.main = kwargs.pop("main")
        tabName = kwargs.pop("tabName")
        QtGui.QWidget.__init__(self, *args, **kwargs)
        self.setObjectName(tabName)
        self._layout = QtGui.QGridLayout(self)
            
    def _InitDocks(self):
        
        # Define docking area
        if hasattr(self, "_dockArea"):
            self._dockArea.setParent(None)
        self._dockArea = DockArea()

        self._plotDocks = self._defaultDockPos.keys()
        
        # Add dock to area
        for dock, pos in self._defaultDockPos.iteritems():
            self._dockArea.addDock(dock, *pos)
        
        self._layout.addWidget(self._dockArea, 0, 0, 1, 1)
    
    def Shown(self):
        self.DrawFrame()
    
    def DrawFrame(self, clear = True):   
        if clear:
            self.ClearPlots()
            
        for dock in self._plotDocks:
            if not dock.automaticDraw:
                continue
            dock.DrawPlot()
        
    def ClearPlots(self):
        for dock in self._plotDocks:
            if not dock.automaticDraw:
                continue
            dock.ClearPlot()
            
    def AutoscalePlots(self):
        for dock in self._plotDocks:
            if not dock.automaticDraw:
                continue
            dock.Autoscale()
            
    def SaveState(self):
        res = {}
        res["dockingState"] = self._dockArea.saveState()
        for dock in self._plotDocks:
            res["dock_" + dock.name()] = dock.SaveState()
        return res
    
    def SetState(self, state):
        try:    
            if "dockingState" in state:
                self._dockArea.restoreState(state["dockingState"])           
        except:
            print "Docking area restore failed, restoring defaults:"
            traceback.print_exc()
            print "Restore defaults"
            self._InitDocks()
 
        for dock in self._plotDocks:
            stateName = "dock_" + dock.name()
            if stateName in state:
                dock.SetState(state[stateName])
Esempio n. 32
0
class MainWindow(QMainWindow, Ui_MainWindow):
    """Where all the action happens."""

    def __init__(self, settings):
        super(MainWindow, self).__init__()
        self.settings = settings
        self.setupUi(self)

        # MainWindow is a collection of widgets in their respective docks.
        # We make DockArea our central widget
        self.dock_area = DockArea()
        self.setCentralWidget(self.dock_area)

        self.createDocks()
        self.initAfterCreatingDockWidgets()
        self.loadSettings()

        self.connectSignalsToSlots()

        # all signals in place, send out the first image
        # self.image_browser.populateAndEmitImageInfo()
        self.image_browser.initialEmit()
        self.roi_editor_h.initialEmit()
        self.roi_editor_v.initialEmit()
        self.roi_editor_int.initialEmit()
        self.roi_editor_err.initialEmit()

        self.loadPlugins()

    def loadPlugins(self):
        """Looks for all plugins and creates menu entries, signals and
           slots for them."""
        self.pluginSignalMapper = QSignalMapper(self)
        for p in plugin_list:
            click_action = QAction(p.name, self)
            self.menuPlugins.addAction(click_action)
            self.connect(click_action, SIGNAL("triggered()"),
                         self.pluginSignalMapper, SLOT("map()"))
            self.pluginSignalMapper.setMapping(click_action, QString(p.name))
        self.connect(self.pluginSignalMapper,
                     SIGNAL("mapped(const QString &)"),
                     self.image_browser.handlePluginClicked)


    def createDocks(self):
        """Create all dock widgets and add them to DockArea."""
        self.image_view = ImageView(self.settings, self)
        self.image_browser = ImageBrowser(self.settings, self)
        self.fitter = Fitter(self.settings, self)

        self.roi_editor_h = RoiEditor(self.settings,
                                      self.image_view, self, name='ROIH',
                                      pen=(1, 9), axis=1)
        self.roi_editor_v = RoiEditor(self.settings,
                                      self.image_view, self, name='ROIV',
                                      pen=(1, 1), axis=0)
        self.roi_editor_int = RoiEditor(self.settings,
                                        self.image_view, self, name='ROI Int',
                                        pen=(1, 2), axis=1)
        self.roi_editor_err = RoiEditor(self.settings,
                                        self.image_view, self, name='ROI Err',
                                        pen=(1, 3), axis=1)
        self.roi_plot_h = Plot1d(parent=self, title='ROI H')
        self.roi_plot_v = Plot1d(parent=self, title='ROI V')

        self.analyzer = Analyzer(self.settings, parent=self)

        # Create docks for all widgets
        self.dock_image_view = Dock('Image View', widget=self.image_view)
        self.dock_image_browser = Dock('Image Browser',
                                       widget=self.image_browser)
        self.dock_fitter = Dock('Fitter', widget=self.fitter)
        self.dock_roi_h = Dock('ROIH', widget=self.roi_editor_h)
        self.dock_roi_v = Dock('ROIV', widget=self.roi_editor_v)
        self.dock_roi_int = Dock('ROI Int', widget=self.roi_editor_int)
        self.dock_roi_err = Dock('ROI Err', widget=self.roi_editor_err)

        self.dock_roi_plot_h = Dock('ROIH Plot', widget=self.roi_plot_h)
        self.dock_roi_plot_v = Dock('ROIV Plot', widget=self.roi_plot_v)
        self.dock_analyzer = Dock('Analyze', widget=self.analyzer)

        self.dock_area.addDock(self.dock_image_view, position='top')
        self.dock_area.addDock(self.dock_image_browser, position='right',
                               relativeTo=self.dock_image_view)
        self.dock_area.addDock(self.dock_fitter, position='left',
                               relativeTo=self.dock_image_view)
        self.dock_area.addDock(self.dock_roi_h, position='bottom',
                               relativeTo=self.dock_fitter)
        self.dock_area.addDock(self.dock_roi_v, position='below',
                               relativeTo=self.dock_roi_h)
        self.dock_area.addDock(self.dock_roi_int, position='below',
                               relativeTo=self.dock_roi_v)
        self.dock_area.addDock(self.dock_roi_err, position='below',
                               relativeTo=self.dock_roi_int)
        self.dock_area.addDock(self.dock_roi_plot_h, position='below',
                               relativeTo=self.dock_image_view)
        self.dock_area.addDock(self.dock_roi_plot_v, position='right',
                               relativeTo=self.dock_roi_plot_h)
        self.dock_area.addDock(self.dock_analyzer, position='top',
                               relativeTo=self.dock_image_browser)

    def initAfterCreatingDockWidgets(self):
        self.setWindowTitle(self.image_browser.current_directory)

    def connectSignalsToSlots(self):
        self.actionOpen_Directory.triggered.connect(self.image_browser.handleOpenDirectoryAction)
        self.actionDark_File.triggered.connect(self.image_browser.handleDarkFileAction)
        self.actionRefresh.triggered.connect(self.image_browser.handleRefreshAction)
        self.actionSave.triggered.connect(self.image_browser.handleSaveAnalysis)

        self.image_browser.windowTitleChanged.connect(self.setWindowTitle)
        # self.image_browser.imageChanged.connect(self.image_view.handleImageChanged)
        self.image_browser.imageChanged.connect(self.fitter.handleImageChanged)
        self.image_browser.imageChanged.connect(self.analyzer.handleImageChanged)

        self.roi_editor_int.roiChanged.connect(self.image_browser.handleRoiChanged)
        self.roi_editor_err.roiChanged.connect(self.image_browser.handleROIErrChanged)
        self.roi_editor_h.roiChanged.connect(self.image_browser.handleROIHChanged)
        self.roi_editor_v.roiChanged.connect(self.image_browser.handleROIVChanged)

        self.roi_editor_h.roiChanged.connect(self.fitter.handleROIHChanged)
        self.roi_editor_h.roiChanged.connect(self.analyzer.handleROIHChanged)
        self.roi_editor_v.roiChanged.connect(self.fitter.handleROIVChanged)
        self.roi_editor_v.roiChanged.connect(self.analyzer.handleROIVChanged)
        self.roi_editor_int.roiChanged.connect(self.fitter.handleROIIntChanged)
        self.roi_editor_int.roiChanged.connect(self.analyzer.handleROIIntChanged)
        self.roi_editor_err.roiChanged.connect(self.fitter.handleROIErrChanged)
        self.roi_editor_err.roiChanged.connect(self.analyzer.handleROIErrChanged)

        self.image_view.doubleClicked.connect(self.roi_editor_h.centerROI)
        self.image_view.doubleClicked.connect(self.roi_editor_v.centerROI)

        self.fitter.imageChanged.connect(self.image_view.handleImageChanged)
        self.fitter.horDataChanged.connect(self.roi_plot_h.handleDataChanged)
        self.fitter.verDataChanged.connect(self.roi_plot_v.handleDataChanged)
        self.fitter.doneFitting.connect(self.analyzer.handleDoneFitting)

    def loadSettings(self):
        """Load window state from self.settings"""

        self.settings.beginGroup('mainwindow')
        geometry = self.settings.value('geometry').toByteArray()
        state = self.settings.value('windowstate').toByteArray()
        dock_string = str(self.settings.value('dockstate').toString())
        if dock_string is not "":
            dock_state = eval(dock_string)
            self.dock_area.restoreState(dock_state)
        self.settings.endGroup()

        self.restoreGeometry(geometry)
        self.restoreState(state)

    def saveSettings(self):
        """Save window state to self.settings."""
        self.settings.beginGroup('mainwindow')
        self.settings.setValue('geometry', self.saveGeometry())
        self.settings.setValue('windowstate', self.saveState())
        dock_state = self.dock_area.saveState()
        # dock_state returned here is a python dictionary. Coundn't find a good
        # way to save dicts in QSettings, hence just using representation
        # of it.
        self.settings.setValue('dockstate', repr(dock_state))
        self.settings.endGroup()

    def closeEvent(self, event):
        self.saveSettings()
        self.image_browser.saveSettings()
        self.roi_editor_int.saveSettings()
        self.roi_editor_err.saveSettings()
        self.roi_editor_v.saveSettings()
        self.roi_editor_h.saveSettings()
        self.analyzer.saveSettings()
        super(MainWindow, self).closeEvent(event)

    def setWindowTitle(self, newTitle=''):
        """Prepend IP-BEC to all window titles."""
        title = 'IP-BEC: ' + newTitle
        super(MainWindow, self).setWindowTitle(title)
from pyqtgraph.dockarea import DockArea, Dock

pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')

app = QtGui.QApplication([])
win = QtGui.QMainWindow()
area = DockArea()
win.setCentralWidget(area)
win.resize(1000,500)
win.setWindowTitle('pyqtgraph example: dockarea')

d1 = Dock("Dock 1", size=(500,300))
d2 = Dock("Dock 2", size=(500,300))

area.addDock(d1, 'left')      ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet)
area.addDock(d2, 'right')   

for e in sorted(dir(pg.PlotWidget().plotItem)):
    print e
    
# p=pg.plot()
# for e in sorted(dir(p)):
#     print e
    
w=pg.PlotWidget()
w.setWindowTitle('pyqtgraph example: PlotSpeedTest')
w.setRange(QtCore.QRectF(0, -20, 5000, 30)) 
w.setLabel('bottom', 'Index', units='B')

curve = w.plot()
Esempio n. 34
0
class GraphArea(pg.QtGui.QWidget):
    def __init__(self, parent=None, src=None):
        super(GraphArea, self).__init__(parent)
        self.src = src

        # TODO: Save defaults
        self.cur_patient = self.src.patient_folders[0]
        self.auto_default_range = settings.auto_default_range

        # Depth control
        if settings.annotation_on:
            self.dc = GUI.DepthControl(vpf=1./40)
        else:
            self.dc = GUI.DepthControl()
        
        self.dc.s.selected_updated.connect(self.depths_updated)
        self.src.s.repaint_dc.connect(self.dc.repaint)
        self.dc.display_hashes = settings.preprocess_hashes

        # Dict of depths with their plot widgets
        self.selected_depths = {}

        # Current link group
        self.cur_link = None

        # Try out other horizontal policies
        # self.setSizePolicy(
        #     pg.QtGui.QSizePolicy.MinimumExpanding,
        #     pg.QtGui.QSizePolicy.Ignored)
        # self.setMinimumWidth(1)

        # Signals for interacting with all children
        self.s = UpdateSignal()

        # Progress bar
        self.pbar = None

        self.init_UI()


    def init_UI(self):
        # Patient selection
        hbox = pg.QtGui.QHBoxLayout()
        self.patient_txt = pg.QtGui.QLabel('Patient: ')
        self.pcombo = pg.ComboBox(
            items=self.src.patient_folders,
            default=self.cur_patient)

        # Connect patient update signal
        self.pcombo.currentIndexChanged.connect(self.patient_update)
        hbox.addWidget(self.patient_txt, stretch=0)
        hbox.addWidget(self.pcombo, stretch=1)

        # Channel selection
        self.channel_txt = pg.QtGui.QLabel('Channel: ')

        '''
        Assuming all channels found in first depth - change later!
        '''
        channels = self.src.get_channels(self.cur_patient, 0)

        self.ccombo = pg.ComboBox(items=channels)

        # Add context menu channel combobox to manage channels
        self.init_channel_menu()
        self.ccombo.setContextMenuPolicy(pg.QtCore.Qt.CustomContextMenu)
        self.ccombo.customContextMenuRequested.connect(self.channel_menu)

        # Connect channel update signal
        self.ccombo.currentIndexChanged.connect(self.update_plots)
        hbox.addWidget(self.channel_txt, stretch=0)
        hbox.addWidget(self.ccombo, stretch=1)

        # Button to toggle annotations
        if settings.annotation_on:
            self.toggle_annotation = QtGui.QPushButton('Annotate')
            self.toggle_annotation.setCheckable(True)
            self.toggle_annotation.setChecked(not settings.hide_annotation)
            hbox.addWidget(self.toggle_annotation, stretch=0)

        ## View controls for all plots ##
        view_hbox = QtGui.QHBoxLayout()
        # view_hbox.addWidget(QtGui.QLabel('Range Controls:'), stretch=0)
        view_hbox.addStretch(1)

        self.update_x_range_button = QtGui.QPushButton('X')
        view_hbox.addWidget(self.update_x_range_button, stretch=0)

        self.x_range_min = QtGui.QLineEdit(str(settings.default_x_range[0]))
        self.x_range_max = QtGui.QLineEdit(str(settings.default_x_range[1]))

        view_hbox.addWidget(QtGui.QLabel('Min (ms):'), stretch=0)
        view_hbox.addWidget(self.x_range_min, stretch=0)
        view_hbox.addWidget(QtGui.QLabel('Max (ms):'), stretch=0)
        view_hbox.addWidget(self.x_range_max, stretch=0)

        self.update_y_range_button = QtGui.QPushButton('Y')
        view_hbox.addWidget(self.update_y_range_button, stretch=0)

        self.y_range_min = QtGui.QLineEdit(str(settings.default_y_range[0]))
        self.y_range_max = QtGui.QLineEdit(str(settings.default_y_range[1]))

        view_hbox.addWidget(QtGui.QLabel('Min (mV):'), stretch=0)
        view_hbox.addWidget(self.y_range_min, stretch=0)
        view_hbox.addWidget(QtGui.QLabel('Max (mV):'), stretch=0)
        view_hbox.addWidget(self.y_range_max, stretch=0)

        # Connect signal
        # self.update_x_range_button.clicked.connect(
        #     lambda: self.s.x_range_updated.emit(
        #         (float(self.x_range_min.text()), float(self.x_range_max.text()))
        #     )
        # )

        # self.update_y_range_button.clicked.connect(
        #     lambda: self.s.y_range_updated.emit(
        #         (float(self.y_range_min.text()), float(self.y_range_max.text()))
        #     )
        # )

        self.update_x_range_button.clicked.connect(self.emit_x_range_updated)
        self.update_y_range_button.clicked.connect(self.emit_y_range_updated)

        # Scroll area
        self.scroll = ScrollArea()

        # Main display
        self.dock_area = DockArea()
        self.min_plot_height = settings.plot_height

        # Scroll widget
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(self.dock_area)

        # Refresh
        self.update_plots()
        self.update_depths()

        # Construct layout
        vbox = pg.QtGui.QVBoxLayout()
        vbox.addLayout(hbox)

        # Hide individual control (Give dynamic option to enable later?)
        # vbox.addLayout(view_hbox)

        # Position depth control and main displays
        hbox2 = pg.QtGui.QHBoxLayout()
        vbox2 = pg.QtGui.QVBoxLayout()
        vbox2.setMargin(0)
        hbox2.setMargin(0)

        # Add horizontal slider
        # self.horizontal_axis = XAxisControl()
        vbox2.addWidget(self.scroll, stretch=9)
        # vbox2.addWidget(self.horizontal_axis, stretch=1)

        # 90% to 10% graph to depth control split; add customizability?
        hbox2.addLayout(vbox2, stretch=9)

        # Set the depth control inside an optional vbox for annotation possibility
        if settings.annotation_on:
            vbox3 = pg.QtGui.QVBoxLayout()
            vbox3.setMargin(0)
            vbox3.setSpacing(2)
            vbox3.setContentsMargins(0,0,0,0)

            # Depth control
            depth_annotate = GUI.AnnotateDepths(self.src, self.dc)
            depth_annotate.s.annotations_updated.connect(self.update_annotations)
            # depth_annotate.hide()
            # depth_annotate.setSizePolicy(pg.QtGui.QSizePolicy.Minimum, pg.QtGui.QSizePolicy.Minimum)
            vbox3.addWidget(self.dc, stretch=10)
            vbox3.addWidget(depth_annotate, stretch=0)
            hbox2.addLayout(vbox3, stretch=1)
        else:
            hbox2.addWidget(self.dc, stretch=1)

        vbox.addLayout(hbox2)
        self.setLayout(vbox)

        '''
        Default settings for channel combo box
        '''
        # Set default checked state based on settings
        only_data = self.src.only_data_channels
        only_spike = self.src.only_spike_channels
        if only_data and not only_spike:
            self.only_data_action.setChecked(True)
            self.only_data()
        if only_spike and not only_data:
            self.only_spike_action.setChecked(True)
            self.only_spike()

        self.show()

    # Initialize channel context menu
    def init_channel_menu(self):
        self.cmenu = pg.QtGui.QMenu(self)
        self.only_data_action = pg.QtGui.QAction('Only Data', self.cmenu, checkable=True)
        # self.only_data_action.setStatusTip('Only display channels with data')
        self.only_data_action.triggered.connect(self.only_data)
        self.only_spike_action = pg.QtGui.QAction('Only Spikes', self.cmenu, checkable=True)
        # self.only_spike_action.setStatusTip('Only display RAW data')
        self.only_spike_action.triggered.connect(self.only_spike)

        # Add to menu
        self.cmenu.addAction(self.only_spike_action)
        self.cmenu.addAction(self.only_data_action)

    # Display channel context menu at right location
    def channel_menu(self, point):
        self.cmenu.exec_(self.ccombo.mapToGlobal(point))

    def only_data(self):
        channels = self.src.get_channels(self.cur_patient, 0)
        only_data = self.only_data_action.isChecked()
        only_spike = self.only_spike_action.isChecked()
        if only_data:
            channels = self.src.parse_data_channels(channels)
            if only_spike:
                # Also toggle off the other filter, since not compatible
                self.only_spike_action.toggle()

        self.ccombo.setItems(channels)

    def only_spike(self):
        channels = self.src.get_channels(self.cur_patient, 0)
        only_data = self.only_data_action.isChecked()
        only_spike = self.only_spike_action.isChecked()
        if only_spike:
            channels = self.src.parse_spike_channels(channels)
            if only_data:
                self.only_data_action.toggle()

        self.ccombo.setItems(channels)

    def update_depths(self):
        # Update depth control
        patient = self.src.patients[self.cur_patient]
        self.dc.updateDepths(patient.depths)

        # Update patient and hashrates if necessary
        if settings.preprocess_hashes:
            self.dc.updatePatient(patient)

        self.dc.updateSelected(None)
        self.dc.repaint()

    def patient_update(self):
        # Update current patient and channel list
        self.cur_patient = self.pcombo.value()

        '''
        Assuming all channels found in first depth
        '''
        channels = self.src.get_channels(self.cur_patient, 0)
        if self.only_data_action.isChecked():
            channels = self.src.parse_data_channels(channels)
        elif self.only_spike_action.isChecked():
            channels = self.src.parse_spike_channels(channels)
        self.ccombo.setItems(channels)

        # Clear and reset various parts of GUI when patient changes
        self.update_depths()

        # Just run an update to notify everything about channel as well
        self.update_plots()

        # Remove all selected depths
        # self.selected_depths.clear()
        for depth in self.selected_depths.keys():
            # Clear docks
            self.selected_depths[depth].close()
            self.selected_depths.pop(depth)

        self.update_layout()
        self.update_plots()

    # @timeit
    def update_plots(self):
        # Update individual plots
        patient = self.src.patients[self.cur_patient]
        channel = self.ccombo.value()
        auto_range = False

        # Notify depth control if necessary
        if settings.preprocess_hashes:
            if channel in settings.spike_channels:
                self.dc.updateChannel(channel)
                self.emit_x_range_updated()
                self.emit_y_range_updated()
            else:
                self.dc.updateChannel(None)
                auto_range = True
            self.dc.repaint()

        # Progress bar update
        if self.pbar is not None:
            self.pbar.set_description('Plotting data')

        # Update all the split dock widgets
        for depth, dock in self.selected_depths.iteritems():
            dock.widgets[0].update(self.src, patient, channel, depth)
            if auto_range:
                dock.widgets[0].auto_range_contents()
            if self.pbar is not None:
                self.pbar.update(1)

    # @timeit
    def depths_updated(self):
        self.dc.repaint()
        previous = set(self.selected_depths.iterkeys())
        updated = set(self.dc.selected)

        # Remove depths in previous not in updated
        purge = previous - updated

        # Add plot items necessary for new depths
        add = updated - previous

        # Instantiate progress bar
        total_length = len(purge) + len(add) + (2 * len(updated))

        if total_length > 0:
            print('\nVisualizing for channel: %s' % self.ccombo.value())
            self.pbar = tqdm.tqdm(total=total_length)

        ### Delete previous docks ###

        # cur = time()

        for depth in purge:
            # Progress bar description
            if self.pbar is not None:
                self.pbar.set_description('Deleting docks')

            # Clear widget
            # Seems bugged - does this actually close the widget?
            self.selected_depths[depth].widgets[0].close()

            ### Disconnect signals ###
            self.s.x_range_updated.disconnect(self.selected_depths[depth].widgets[0].main_widget.set_x_range)
            self.s.y_range_updated.disconnect(self.selected_depths[depth].widgets[0].main_widget.set_y_range)

            if settings.annotation_on:
                self.toggle_annotation.toggled.disconnect(self.selected_depths[depth].widgets[0].toggle_second_widget)

            # Clear docks
            self.selected_depths[depth].close()

            self.selected_depths.pop(depth)

            if self.pbar is not None:
                self.pbar.update(1)


        ### Add new docks ###

        # print('Time to delete: %f' % (time() - cur))
        # cur = time()

        for depth in add:
            # Progress bar update
            if self.pbar is not None:
                self.pbar.set_description('Loading data')

            # Wrap the widget in a dock
            widget =  GUI.DefaultPlotWidget(self.src)
            self.add_plot_dock(depth, widget)

            if self.pbar is not None:
                self.pbar.update(1)

        # print('Time to add: %f' % (time() - cur))
        # cur = time()

        ### Update layout ###
        self.update_layout()

        # print('Time to update layout: %f' % (time() - cur))
        # cur = time()

        ### Update plots ###

        self.update_plots()
        # print('Time to update plots: %f' % (time() - cur))


        # Update annotate toggle
        if settings.annotation_on:
            self.toggle_annotation.setChecked(not settings.hide_annotation)

        # Update views
        # print('updating')
        if self.auto_default_range:
            self.emit_x_range_updated()
            self.emit_y_range_updated()
        # print('updated')

        if self.pbar is not None:
            self.pbar.close()
            self.pbar = None

    # @timeit
    def update_layout(self):
        length = len(self.selected_depths)
        self.dock_area.setMinimumSize(0, length * self.min_plot_height)

        # Progress bar update
        if self.pbar is not None:
            self.pbar.set_description('Populating visual elements')

        for depth in sorted(self.selected_depths.iterkeys(), reverse=True):
            dock = self.selected_depths[depth]
            self.dock_area.addDock(dock, position='bottom')

            if self.pbar is not None:
                self.pbar.update(1)

    def add_plot_dock(self, depth, widget):
        dock = Dock(depth, size=(1,1), closable=False, autoOrientation=False)
        split_dock_widget = SplitDockWidget(widget)

        ### Connect signals ###
        self.s.x_range_updated.connect(widget.set_x_range)
        self.s.y_range_updated.connect(widget.set_y_range)
        widget.s.title_updated.connect(dock.setTitle)

        if settings.annotation_on:
            self.toggle_annotation.toggled.connect(split_dock_widget.toggle_second_widget)

        dock.addWidget(split_dock_widget)
        self.selected_depths[depth] = dock       

    ## Emit the signals necessary to update all the plots ##
    def emit_x_range_updated(self):
        self.s.x_range_updated.emit(
            (float(self.x_range_min.text()), float(self.x_range_max.text()))
        )

    def emit_y_range_updated(self):
        self.s.y_range_updated.emit(
            (float(self.y_range_min.text()), float(self.y_range_max.text()))
        )

    # Update annotations across all the necessary depths for the patient
    def update_annotations(self, update):
        # Update is tuple of form (depths, labels)
        depths, labels = update

        ch_nr = self.src.get_channel_number(self.ccombo.value())
        patient = self.src.patients[self.cur_patient]

        for depth in depths:
            # Update all annotation widgets
            if depth in self.selected_depths:
                dock = self.selected_depths[depth]
                dock.widgets[0].update_annotation(labels)
            # Update patient for depths not currently displayed
            else:
                # Calculate current id
                cur_id = (depth, ch_nr)
                # Check if depth_labels already has labels
                if cur_id not in patient.depth_labels:
                    patient.depth_labels[cur_id] = list(labels)
                else:
                    for label in labels:
                        if label not in patient.depth_labels[cur_id]:
                            patient.depth_labels[cur_id].append(label)
Esempio n. 35
0
class MarkWriteMainWindow(QtGui.QMainWindow):
    sigProjectChanged = QtCore.Signal(object)  # new_project
    sigResetProjectData = QtCore.Signal(object)  # project
    sigSelectedPenDataUpdate = QtCore.Signal(object,
                                             object)  # (smin,smax), segmentdata
    sigSegmentCreated = QtCore.Signal(object)  # new segment
    sigSegmentRemoved = QtCore.Signal(object,
                                      object)  # segment being removed,
                                      # segment index in list
    sigAppSettingsUpdated = QtCore.Signal(object, #dict of app settings that changed
                                          object,) #ful settings dict
    sigActiveObjectChanged = QtCore.Signal(object, object) #new, old active objects
    _mainwin_instance=None
    _appdirs = None
    def __init__(self, qtapp):
        global  SETTINGS
        QtGui.QMainWindow.__init__(self)
        MarkWriteMainWindow._mainwin_instance = self

        self._current_project = None
        self._activeobject = None

        self._predefinedtags = loadPredefinedSegmentTagList(u'default.tag')

        # create qt actions used by menu, toolbar, or both
        self.createGuiActions()

        # init GUI related stuff
        self.setupGUI(qtapp)

        self.sigProjectChanged.connect(self.handleProjectChange)
        self.sigSelectedPenDataUpdate.connect(self.handleSelectedPenDataUpdate)
        self.sigAppSettingsUpdated.connect(self._penDataTimeLineWidget.handleUpdatedSettingsEvent)
        self.sigAppSettingsUpdated.connect(self._penDataSpatialViewWidget.handleUpdatedSettingsEvent)
        self.sigAppSettingsUpdated.connect(self._selectedPenDataViewWidget.handleUpdatedSettingsEvent)

    @staticmethod
    def instance():
        return MarkWriteMainWindow._mainwin_instance

    @property
    def project(self):
        return self._current_project

    @property
    def activeobject(self):
        return self._activeobject

    def setActiveObject(self, timeperioddatatype=None):
        prevactiveobj = self._activeobject

        self._activeobject = timeperioddatatype
        if timeperioddatatype is None:
            self._activeobject = self.project.selectedtimeregion
        #print "Settings active object:",self._activeobject
        if isinstance(self._activeobject,PenDataSegment):
            #print "**Setting region:",self._activeobject
            self._segmenttree.doNotSetActiveObject=True
            self.project.selectedtimeregion.setRegion(self._activeobject.timerange)
            self._segmenttree.doNotSetActiveObject=False
            self.removeSegmentAction.setEnabled(True)
        else:
            self.removeSegmentAction.setEnabled(False)
        self.sigActiveObjectChanged.emit(self._activeobject,prevactiveobj)

        return self._activeobject

    @property
    def predefinedtags(self):
        if self.project:
            return self.project.autodetected_segment_tags + self._predefinedtags
        return self._predefinedtags

    def createGuiActions(self):
        #
        # File Menu / Toolbar Related Actions
        #
        atext = 'Open a supported digitized pen position ' \
                'file format.'
        aicon = 'folder&32.png'
        self.openFileAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            '&Open',
            self)
        self.openFileAction.setShortcut('Ctrl+O')
        self.openFileAction.setEnabled(True)
        self.openFileAction.setStatusTip(atext)
        self.openFileAction.triggered.connect(self.openFile)

        #atext = 'Save Current Project.'
        #aicon = 'save&32.png'
        #self.saveProjectAction = ContextualStateAction(
        #    QtGui.QIcon(getIconFilePath(aicon)),
        #    'Save',
        #    self)
        #self.saveProjectAction.setShortcut('Ctrl+S')
        #self.saveProjectAction.setEnabled(False)
        #self.saveProjectAction.setStatusTip(atext)
        #self.saveProjectAction.triggered.connect(self.saveProject)

        atext = 'Export Pen Sample Level Report to a File.'
        aicon = 'sample_report&32.png'
        self.exportSampleReportAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Sample Report',
            self)
        #self.exportSampleReportAction.setShortcut('Ctrl+S')
        self.exportSampleReportAction.setEnabled(False)
        self.exportSampleReportAction.setStatusTip(atext)
        self.exportSampleReportAction.triggered.connect(
            self.createPenSampleLevelReportFile)

        atext = 'Export Segment Level Report to a File.'
        aicon = 'segment_report&32.png'
        self.exportSegmentReportAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Segment Report',
            self)
        #self.exportSampleReportAction.setShortcut('Ctrl+S')
        self.exportSegmentReportAction.setEnabled(False)
        self.exportSegmentReportAction.setStatusTip(atext)
        self.exportSegmentReportAction.triggered.connect(
            self.createSegmentLevelReportFile)

        self.exportSampleReportAction.enableActionsList.append(self.exportSegmentReportAction)

        atext = 'Open the Application Settings Dialog.'
        aicon = 'settings&32.png'
        self.showProjectSettingsDialogAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            '&Settings',
            self)
        self.showProjectSettingsDialogAction.setShortcut('Alt+S')
        self.showProjectSettingsDialogAction.setEnabled(True)
        self.showProjectSettingsDialogAction.setStatusTip(atext)
        self.showProjectSettingsDialogAction.triggered.connect(
            self.handleDisplayAppSettingsDialogEvent)

        atext = 'Close the MarkWrite Application. Any data segmention will be lost!'
        aicon = 'shut_down&32.png'
        self.exitAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Exit',
            self)
        self.exitAction.setShortcut('Ctrl+Alt+Q')
        self.exitAction.setEnabled(True)
        self.exitAction.setStatusTip(atext)
        self.exitAction.triggered.connect(self.closeEvent)

        #
        # Selection Menu / Toolbar Related Actions
        #

        atext = 'Create a Segment Using Currently Selected Pen Data.'
        aicon = 'accept&32.png'
        self.createSegmentAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Create &New',
            self)
        self.createSegmentAction.setShortcut(QtCore.Qt.Key_Return)
        self.createSegmentAction.setEnabled(False)
        self.createSegmentAction.setStatusTip(atext)
        self.createSegmentAction.triggered.connect(self.createSegment)

        atext = 'Delete the Selected Segment and any of the segments children.'
        aicon = 'delete&32.png'
        self.removeSegmentAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            '&Delete',
            self)
        self.removeSegmentAction.setShortcut('Ctrl+D')
        self.removeSegmentAction.setEnabled(False)
        self.removeSegmentAction.setStatusTip(atext)
        self.removeSegmentAction.triggered.connect(self.removeSegment)

        #
        # Timeline Plot Zoom Related Actions
        #

        atext = 'Increase Timeplot Horizontal Magnification 2x'
        aicon = 'zoom_in&32.png'
        self.zoomInTimelineAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Zoom In 2x',
            self)
        self.zoomInTimelineAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Plus)
        self.zoomInTimelineAction.setEnabled(False)
        self.zoomInTimelineAction.setStatusTip(atext)
        self.zoomInTimelineAction.triggered.connect(self.zoomInTimeline)

        atext = 'Decrease Timeplot Horizontal Magnification 2x'
        aicon = 'zoom_out&32.png'
        self.zoomOutTimelineAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Zoom Out 2x',
            self)
        self.zoomOutTimelineAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Minus)
        self.zoomOutTimelineAction.setEnabled(False)
        self.zoomOutTimelineAction.setStatusTip(atext)
        self.zoomOutTimelineAction.triggered.connect(self.zoomOutTimeline)

        self.exportSampleReportAction.enableActionsList.append(self.zoomInTimelineAction)
        self.exportSampleReportAction.enableActionsList.append(self.zoomOutTimelineAction)

        atext = 'Reposition Views around Selected Time Period'
        aicon = 'target&32.png'
        self.gotoSelectedTimePeriodAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Go To Selected Time Period',
            self)
        self.gotoSelectedTimePeriodAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Home)
        self.gotoSelectedTimePeriodAction.setEnabled(False)
        self.gotoSelectedTimePeriodAction.setStatusTip(atext)
        self.gotoSelectedTimePeriodAction.triggered.connect(self.gotoSelectTimelinePeriod)

        atext = "Move selected time period forward, so that it's start time is one sample after the current selection's end time"
        aicon = 'move_selection_forward&32.png'
        self.forwardSelectionAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Jump Forward',
            self)
        self.forwardSelectionAction.setShortcut(QtCore.Qt.Key_Right)
        self.forwardSelectionAction.setEnabled(False)
        self.forwardSelectionAction.setStatusTip(atext)
        self.forwardSelectionAction.triggered.connect(self.jumpTimeSelectionForward)

        atext = "Move selected time period backward, so that it's end time is one sample prior to the current selection's start time."
        aicon = 'move_selection_backward&32.png'
        self.backwardSelectionAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Jump Backward',
            self)
        self.backwardSelectionAction.setShortcut(QtCore.Qt.Key_Left)
        self.backwardSelectionAction.setEnabled(False)
        self.backwardSelectionAction.setStatusTip(atext)
        self.backwardSelectionAction.triggered.connect(self.jumpTimeSelectionBackward)


        atext = 'Increase Timeline Selection End Time'
        aicon = 'increase_select_endtime&32.png'
        self.increaseSelectionEndPointAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Increase Selection End',
            self)
        self.increaseSelectionEndPointAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Right)
        self.increaseSelectionEndPointAction.setEnabled(False)
        self.increaseSelectionEndPointAction.setStatusTip(atext)
        self.increaseSelectionEndPointAction.triggered.connect(self.increaseSelectionEndPointTime)

        atext = 'Decrease Timeline Selection End Time'
        aicon = 'descrease_select_endtime&32.png'
        self.decreaseSelectionEndPointAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Decrease Selection End',
            self)
        self.decreaseSelectionEndPointAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Left)
        self.decreaseSelectionEndPointAction.setEnabled(False)
        self.decreaseSelectionEndPointAction.setStatusTip(atext)
        self.decreaseSelectionEndPointAction.triggered.connect(self.decreaseSelectionEndPointTime)

        #======================================
        atext = 'Increase Timeline Selection Start Time'
        aicon = 'increase_select_starttime&32.png'
        self.increaseSelectionStartPointAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Increase Selection Start',
            self)
        self.increaseSelectionStartPointAction.setShortcut(QtCore.Qt.ALT + QtCore.Qt.Key_Right)
        self.increaseSelectionStartPointAction.setEnabled(False)
        self.increaseSelectionStartPointAction.setStatusTip(atext)
        self.increaseSelectionStartPointAction.triggered.connect(self.increaseSelectionStartPointTime)

        atext = 'Decrease Timeline Selection Start Time'
        aicon = 'decrease_select_starttime&32.png'
        self.decreaseSelectionStartPointAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'Decrease Selection Start',
            self)
        self.decreaseSelectionStartPointAction.setShortcut(QtCore.Qt.ALT + QtCore.Qt.Key_Left)
        self.decreaseSelectionStartPointAction.setEnabled(False)
        self.decreaseSelectionStartPointAction.setStatusTip(atext)
        self.decreaseSelectionStartPointAction.triggered.connect(self.decreaseSelectionStartPointTime)


        self.exportSampleReportAction.enableActionsList.append(self.zoomInTimelineAction)
        self.exportSampleReportAction.enableActionsList.append(self.zoomOutTimelineAction)
        self.exportSampleReportAction.enableActionsList.append(self.gotoSelectedTimePeriodAction)
        self.exportSampleReportAction.enableActionsList.append(self.decreaseSelectionEndPointAction)
        self.exportSampleReportAction.enableActionsList.append(self.increaseSelectionEndPointAction)
        self.exportSampleReportAction.enableActionsList.append(self.decreaseSelectionStartPointAction)
        self.exportSampleReportAction.enableActionsList.append(self.increaseSelectionStartPointAction)
        self.exportSampleReportAction.enableActionsList.append(self.forwardSelectionAction)
        self.exportSampleReportAction.enableActionsList.append(self.backwardSelectionAction)

        #
        # Help Menu / Toolbar Related Actions
        #

        atext = 'Displays the MarkWrite About Dialog.'
        aicon = 'info&32.png'
        self.aboutAction = ContextualStateAction(
            QtGui.QIcon(getIconFilePath(aicon)),
            'About',
            self)
        self.aboutAction.setEnabled(True)
        self.aboutAction.setStatusTip(atext)
        self.aboutAction.triggered.connect(self.showAboutDialog)

    def setupGUI(self, app):
        '''

        :return:
        '''

        #
        ## Create Main GUI Menu Bar
        #

        menubar = self.menuBar()

        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(self.openFileAction)
        #fileMenu.addAction(self.saveProjectAction)
        fileMenu.addAction(self.showProjectSettingsDialogAction)
        fileMenu.addSeparator()
        exportMenu = fileMenu.addMenu("&Export")
        exportMenu.addAction(self.exportSampleReportAction)
        exportMenu.addAction(self.exportSegmentReportAction)
        exportMenu.addSeparator()
        self.customReportActions=[]
        for custom_report in custom_report_classes:
            a = exportMenu.addAction(custom_report.reportlabel(), lambda: self.exportCustomReport(custom_report))
            a.setEnabled(False)
            self.customReportActions.append(a)
            self.exportSampleReportAction.enableActionsList.append(a)

        fileMenu.addSeparator()
        fileMenu.addAction(self.exitAction)

        segmentMenu = menubar.addMenu('&Segment')
        segmentMenu.addAction(self.createSegmentAction)
        segmentMenu.addAction(self.removeSegmentAction)

        helpMenu = menubar.addMenu('&Help')
        helpMenu.addAction(self.aboutAction)

        self.toolbarFile = self.addToolBar('File')
        self.toolbarFile.addAction(self.openFileAction)
        #self.toolbarFile.addAction(self.saveProjectAction)
        self.toolbarFile.addAction(self.showProjectSettingsDialogAction)
        self.toolbarFile.addAction(self.exportSampleReportAction)
        self.toolbarFile.addAction(self.exportSegmentReportAction)


        self.toolbarsegment = self.addToolBar('Segment')
        self.toolbarsegment.addAction(self.createSegmentAction)
        self.toolbarsegment.addAction(self.removeSegmentAction)

        self.toolbartimelineview = self.addToolBar('Timeline View')
        self.toolbartimelineview.addAction(self.zoomInTimelineAction)
        self.toolbartimelineview.addAction(self.zoomOutTimelineAction)

        self.toolbarsegment = self.addToolBar('Timeline Selection')
        self.toolbarsegment.addAction(self.gotoSelectedTimePeriodAction)
        self.toolbarsegment.addAction(self.decreaseSelectionStartPointAction)
        self.toolbarsegment.addAction(self.increaseSelectionStartPointAction)
        self.toolbarsegment.addAction(self.backwardSelectionAction)
        self.toolbarsegment.addAction(self.forwardSelectionAction)
        self.toolbarsegment.addAction(self.decreaseSelectionEndPointAction)
        self.toolbarsegment.addAction(self.increaseSelectionEndPointAction)

        self.toolbarHelp = self.addToolBar('Help')
        self.toolbarHelp.addAction(self.aboutAction)

        #
        ## Create App Dock Area
        #

        self._dockarea = DockArea()
        self.setCentralWidget(self._dockarea)

        # Enable antialiasing for prettier plots
        pg.setConfigOptions(antialias=True)


        # Create Docking Layout
        def addDock(name, inner_widget=None):
            ww, wh = DEFAULT_WIN_SIZE

            dpos, (dw, dh) = DEFAULT_DOCK_PLACEMENT[name]
            if isinstance(dpos, basestring):
                self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]),
                                       dpos)
            else:
                self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]),
                                       dpos[0], self._dockarea.docks[dpos[1]])

            if inner_widget:
                self._dockarea.docks[name].addWidget(inner_widget)

        from markwrite.gui.selecteddataview import SelectedPointsPlotWidget
        from markwrite.gui.spatialview import PenDataSpatialPlotWidget
        from markwrite.gui.timelineplot import PenDataTemporalPlotWidget
        from markwrite.gui.segmenttree import SegmentInfoDockArea

        self._segmenttree = SegmentInfoDockArea()
        addDock(u"Segment Tree", self._segmenttree)
        self._penDataTimeLineWidget = PenDataTemporalPlotWidget()
        self._penDataSpatialViewWidget = PenDataSpatialPlotWidget()
        addDock(u"Timeline", self._penDataTimeLineWidget)
        addDock(u"Spatial View", self._penDataSpatialViewWidget)
        self._selectedPenDataViewWidget = SelectedPointsPlotWidget()
        addDock(u"Selected Data", self._selectedPenDataViewWidget)

        #
        ## Do Misc. GUI setup.
        #

        self.setWindowIcon(QtGui.QIcon(getIconFilePath('edit&32.png')))

        self.statusBar().showMessage('Ready')
        self.updateAppTitle()

        self.resize(*DEFAULT_WIN_SIZE)

    @property
    def penDataTemporalPlotWidget(self):
        return self._penDataTimeLineWidget

    def updateAppTitle(self):
        if self._current_project is None:
            fileName = u''
        else:
            fileName = self._current_project.name
            fileName = u'{0} : '.format(fileName)

        app_title = u'MarkWrite'
        full_title = u'{0}{1}'.format(fileName, app_title)

        self.setWindowTitle(full_title)

    def showAboutDialog(self):
        QtGui.QMessageBox.about(self, ABOUT_DIALOG_TITLE, ABOUT_DIALOG_TEXT)
        self.sender().enableAndDisableActions()


    def openFile(self):
        file_path = fileOpenDlg()
        if file_path:
            file_path = file_path[0]
            if len(file_path) > 0:
                try:
                    wmproj = MarkWriteProject(file_path=file_path,mwapp=self)
                    self.createSegmentAction.setEnabled(True)
                    self.sigProjectChanged.emit(wmproj)
                    self.sigResetProjectData.emit(wmproj)
                except:
                    import traceback

                    traceback.print_exc()
                    ErrorDialog.info_text = u"An error occurred while " \
                                            u"opening:\n%s\nMarkWrite will " \
                                            u"now close." % (
                    file_path)
                    ErrorDialog().display()
                    self.closeEvent(u'FORCE_EXIT')

    def createPenSampleLevelReportFile(self):
        default_file_name = u"pen_samples_{0}.txt".format(self.project.name)
        file_path = fileSaveDlg(initFileName=default_file_name,
                                prompt="Export Pen Sample Report")
        if file_path:
            PenSampleReportExporter().export(file_path, self.project)

    def createSegmentLevelReportFile(self):
        default_file_name = u"segments_{0}.txt".format(self.project.name)
        file_path = fileSaveDlg(initFileName=default_file_name,
                                prompt="Export Segment Level Report")
        if file_path:
            SegmentLevelReportExporter().export(file_path, self.project)

    def exportCustomReport(self,reportcls):
        default_file_name = u"{}_{}.txt".format(reportcls.outputfileprefix(),self.project.name)
        file_path = fileSaveDlg(initFileName=default_file_name,
                                prompt="Export %s"%(reportcls.reportlabel()))
        if file_path:
            reportcls().export(file_path, self.project)

    def createSegment(self):
        """
        Displays the Create Segment dialog. If dialog is not cancelled and
        segment name length >0, then create a new segment and add to the
        projects segment list.
        :return:
        """
        if self.createSegmentAction.isEnabled():
            # Shrink timeline selection region to fit start and end time
            # of possible segment being created.
            selectedtimeperiod = self.project.selectedtimeperiod[:]


            pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*selectedtimeperiod)
            if len(pendata_ix_range)>0:
                segmenttimeperiod = self.project.pendata['time'][pendata_ix_range]
                self.project.selectedtimeregion.setRegion(segmenttimeperiod)

                tag, ok = showSegmentNameDialog(self.predefinedtags)
                tag = unicode(tag).strip().replace('\t', "#")
                if len(tag) > 0 and ok:
                    psid = self.project.getSelectedDataSegmentIDs()[0]
                    new_segment = self.project.createSegmentFromSelectedPenData(tag, psid)
                    self.handleSelectedPenDataUpdate(None,None)
                    self.sigSegmentCreated.emit(new_segment)
                    self.setActiveObject(new_segment)
                else:
                    # If segment creation was cancelled or failed, then reset
                    # timeline selection region to original time period.
                    self.project.selectedtimeregion.setRegion(selectedtimeperiod)
        else:
            ErrorDialog.info_text = u"Segment Creation Failed.\nNo selected " \
                                    u"pen data."
            ErrorDialog().display()

    def removeSegment(self):
        ConfirmAction.text = 'Delete Segment Confirmation'
        ConfirmAction.info_text = "Are you sure you want to <b>permanently deleted</b> the currently selected segment?" \
                                  "<br><br>" \
                                  "Any children of this segment will also be deleted."
        yes = ConfirmAction.display()
        if not yes:
            return
        segment = self.activeobject
        if segment and segment.parent is not None:
            seg_ix = segment.parent.getChildIndex(segment)
            # Decrement the pendata array 'segment_id' field for elements within
            # the segment being removed so that # of segments that contain each
            # pen point can be tracked
            allpendata = self.project.pendata
            segment_filter = (allpendata['time'] >= segment.starttime) & (
            allpendata['time'] <= segment.endtime)
            allpendata['segment_id'][segment_filter] = segment.parent.id
            self.setActiveObject(self.project.selectedtimeregion)
            self.handleSelectedPenDataUpdate(None,None)
            self.sigSegmentRemoved.emit(segment, seg_ix)

            segment.parent.removeChild(segment)
        else:
            print "   - Remove action IGNORED"
        print "<< removeSegment"

    def handleProjectChange(self, project):
        if self._current_project:
            pass
        self._current_project = project
        self.setActiveObject(self.project.selectedtimeregion)
        self.updateAppTitle()
        #self.saveProjectAction.setEnabled(project.modified)
        self.exportSampleReportAction.setEnabled(True)

    def zoomInTimeline(self):
        # TODO: Move method to _penDataTimeLineWidget
        self._penDataTimeLineWidget.getPlotItem().getViewBox().scaleBy(x=0.5)

    def zoomOutTimeline(self):
        # TODO: Move method to _penDataTimeLineWidget
        self._penDataTimeLineWidget.getPlotItem().getViewBox().scaleBy(x=2.0)#,center=(xmin+xmax)/2)

    def gotoSelectTimelinePeriod(self):
        # TODO: Move method to _penDataTimeLineWidget
        xmin, xmax , selpendat= self._penDataTimeLineWidget.currentSelection.selectedtimerangeanddata
        xpad = (xmax-xmin)/2
        pdat=self.project.pendata
        rx=(max(0,xmin-xpad),min(xmax+xpad,self._penDataTimeLineWidget.maxTime))
        if SETTINGS['timeplot_enable_ymouse']:
            ry = (
                    min(selpendat['x'].min(), selpendat['y'].min()),
                    max(selpendat['x'].max(), selpendat['y'].max()))
        else:
            ry = (0, max(pdat['x'].max(),pdat['y'].max()))
        self._penDataTimeLineWidget.getPlotItem().setRange(xRange=rx, yRange=ry)

    def jumpTimeSelectionForward(self):
        # TODO: Move method to _penDataTimeLineWidget
        xmin, xmax = self.project.selectedtimeregion.getRegion()
        pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax)
        if len(pendata_ix_range):
            nix_min = pendata_ix_range[1]+1
            if self.project.pendata['pressure'][nix_min]==0.0:
                start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix
                next_starts = start_ixs[start_ixs>nix_min]
                if len(next_starts)>0:
                    nix_min=next_starts[0]
                else:
                    infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved forward.<br>Reason: NTs index not available.")
                    return
            nxmin = self.project.pendata['time'][nix_min]
            nxmax = min(nxmin +(xmax-xmin), self.project.pendata['time'][-1])
            if nxmin >= nxmax:
                infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved forward.<br>Reason: End of data reached.")
                return
            self.project.selectedtimeregion.setRegion([nxmin,nxmax])

            (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange()
            if nxmax >= vmax:
                self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmax-vmax)*1.25)

    def jumpTimeSelectionBackward(self):
        # TODO: Move method to _penDataTimeLineWidget
        if 0:
            xmin, xmax = self.project.selectedtimeregion.getRegion()
            nxmax =xmin-0.001
            nxmin = max(nxmax-(xmax-xmin),0.0)
            pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(nxmin,nxmax)
            if len(pendata_ix_range):
                segmenttimeperiod = self.project.pendata['time'][pendata_ix_range]
                self.project.selectedtimeregion.setRegion(segmenttimeperiod)

                (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange()
                if nxmin < vmin:
                    self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25)
        else:
            xmin, xmax = self.project.selectedtimeregion.getRegion()
            pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax)
            if len(pendata_ix_range):
                nix_max = pendata_ix_range[0]-1
                if nix_max<=0:
                    infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: NTe index out of bounds.")
                    return
                if self.project.pendata['pressure'][nix_max]==0.0:
                    start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix
                    prev_stops = stop_ixs[stop_ixs<=nix_max]
                    if len(prev_stops)>0:
                        nix_max=prev_stops[-1]
                    else:
                        infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: NTe index not available.")
                        return
                nxmax = self.project.pendata['time'][nix_max]
                nxmin = max(nxmax -(xmax-xmin), 0.0)
                if nxmin >= nxmax:
                    infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: End of data reached.")
                    return
                self.project.selectedtimeregion.setRegion([nxmin,nxmax])

                (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange()
                if nxmin <= vmin:
                    self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25)

    def increaseSelectionEndPointTime(self):
        # TODO: Move method to _penDataTimeLineWidget
        xmin, xmax = self.project.selectedtimeregion.getRegion()
        ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax)
        if len(ix_bounds)>0:
            min_ix, max_ix = ix_bounds
            start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix
            next_max_ix = stop_ixs[stop_ixs>(max_ix+1)][0]
            #print "org_max_ix, new_max_ix",max_ix,next_max_ix
            #print 'new start , end samples: ',self.project.pendata[[min_ix, next_max_ix]]
            if next_max_ix < self.project.pendata.shape[0]:
                segmenttimeperiod = self.project.pendata['time'][[min_ix, next_max_ix]]
                min_ix, next_max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod)
                self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, next_max_ix]])
                _,nxmax=segmenttimeperiod
                (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange()
                if nxmax >= vmax:
                    self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmax-vmax)*1.25)
            else:
                 infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be extended<br>as it is at the end of the data samples.")


    def decreaseSelectionEndPointTime(self):
        # TODO: Move method to _penDataTimeLineWidget
        xmin, xmax = self.project.selectedtimeregion.getRegion()
        ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax)
        if len(ix_bounds)>0:
            min_ix, max_ix = ix_bounds
            if np.all(self.project.nonzero_pressure_mask[min_ix:max_ix]):
                self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]])
                return
            start_ixs, stop_ixs, lengths=self.project.nonzero_region_ix
            prev_maxs = stop_ixs[stop_ixs<max_ix]
            if prev_maxs.shape[0]>0:
                if prev_maxs[-1] > min_ix:
                    prev_max_ix = prev_maxs[-1]
                    segmenttimeperiod = self.project.pendata['time'][[min_ix, prev_max_ix]]
                    min_ix, max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod)
                    self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]])
                else:
                    infoDlg(title=u"Action Aborted", prompt=u"The end time of the selected time period can not be decreased further<br>without it being equal to the selected periods start time.")

    def increaseSelectionStartPointTime(self):
        # TODO: Move method to _penDataTimeLineWidget
        xmin, xmax = self.project.selectedtimeregion.getRegion()
        ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax)
        if len(ix_bounds)>0:
            min_ix, max_ix = ix_bounds
            if np.all(self.project.nonzero_pressure_mask[min_ix:max_ix]):
                self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]])
                return
            start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix
            higher_starts=start_ixs[start_ixs>(min_ix)]
            if len(higher_starts)==0:
                infoDlg(title=u"Action Aborted", prompt=u"The start time of the selected time period can not be increased<br> any further; it is the last IPS run of the file.")
            elif higher_starts[0]>=max_ix-1:
                infoDlg(title=u"Action Aborted", prompt=u"The start time of the selected time period can not be further increased<br> without it exceeding the selected periods end time.")
            else:
                segmenttimeperiod = self.project.pendata['time'][[higher_starts[0], max_ix]]
                self.project.selectedtimeregion.setRegion(segmenttimeperiod)

    def decreaseSelectionStartPointTime(self):
        # TODO: Move method to _penDataTimeLineWidget
        xmin, xmax = self.project.selectedtimeregion.getRegion()
        ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax)
        if len(ix_bounds)>0:
            min_ix, max_ix = ix_bounds
            start_ixs, stop_ixs, lengths=self.project.nonzero_region_ix
            prev_starts = start_ixs[start_ixs<min_ix]
            if len(prev_starts)>0 and prev_starts[-1] >= 0:
                    prev_start_ix = prev_starts[-1]
                    segmenttimeperiod = self.project.pendata['time'][[prev_start_ix, max_ix]]
                    min_ix, max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod)
                    self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]])
                    nxmin,_=segmenttimeperiod
                    (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange()
                    if nxmin < vmin:
                        self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25)

    def handleSelectedPenDataUpdate(self, timeperiod, pendata):
        #print '>> App.handleSelectedPenDataUpdate:',timeperiod
        self.createSegmentAction.setEnabled(
            self.project and self.project.isSelectedDataValidForNewSegment())
        #print '<< App.handleSelectedPenDataUpdate'

    def handleDisplayAppSettingsDialogEvent(self):
        usersettings = readPickle(self._appdirs.user_config_dir,u'usersettings.pkl')

        updatedsettings, allsettings, savestate, ok = ProjectSettingsDialog.getProjectSettings(self, usersettings)
        if ok is True:
            writePickle(self._appdirs.user_config_dir,u'usersettings.pkl', savestate)
            if self.project and len(updatedsettings)>0:
                self.sigAppSettingsUpdated.emit(updatedsettings, allsettings)

    def closeEvent(self, event):
        if event == u'FORCE_EXIT':
            QtCore.QCoreApplication.instance().quit()
            return

        exitapp = ExitApplication.display()
        if exitapp:
            pass
            if event:
                event.accept()
            else:
                QtCore.QCoreApplication.instance().quit()
        else:
            if event:
                event.ignore()

    def __del__(self):
        pass
Esempio n. 36
0
class H5Plotter(QtGui.QMainWindow):
    def __init__(self, file):
        super(H5Plotter, self).__init__()
        view_box = SearchableH5View(H5File(file))
        self.view = view_box.tree_view
        self.match_model = self.view.model()
        self.model = self.match_model.sourceModel()
        self.dock_area = DockArea()

        self.layout = QtGui.QSplitter(Qt.Horizontal)
        self.setCentralWidget(self.layout)
        self.view.activated.connect(self.load_plot)
        self.layout.addWidget(view_box)
        self.layout.addWidget(self.dock_area)
        self.layout.setStretchFactor(0, 0)
        self.layout.setStretchFactor(1, 1)

        self.setWindowIcon(QtGui.QIcon("icon.ico"))

        QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_N), self,
                        lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveDown))
        QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_P), self,
                        lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveUp))
        QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_F), self,
                        lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveRight))
        QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_B), self,
                        lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveLeft))
        QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_S), self, view_box.search_box.setFocus)

        view_menu = self.menuBar().addMenu("View")

        toggle_attrs_action = QtGui.QAction("Attributes Visible", view_menu)
        toggle_attrs_action.setCheckable(True)
        toggle_attrs_action.triggered.connect(self.match_model.toggle_attrs_visible)
        view_menu.addAction(toggle_attrs_action)

        toggle_junk_action = QtGui.QAction("Junk Visible", view_menu)
        toggle_junk_action.setCheckable(True)
        toggle_junk_action.triggered.connect(self.match_model.toggle_junk_visible)
        view_menu.addAction(toggle_junk_action)

    def move_view_cursor(self, cursor_action):
        self.view.setFocus(Qt.OtherFocusReason)
        self.view.setCurrentIndex(self.view.moveCursor(cursor_action, Qt.NoModifier))


    def load_plot(self, index):
        'given an index referring to an H5Dataset, puts a plot corresponding to that dataset in the plot area'
        source_index = self.match_model.mapToSource(index)
        item = self.model.itemFromIndex(source_index)
        if isinstance(item.row, H5DatasetRow) and item.row.plot is None:
            labels = []
            axes = []
            for d in item.group.dims:
                try:
                    label, ds = d.items()[0]
                    labels.append(label)
                    axes.append(ds[:])
                except IndexError:
                    print 'Could not find axis in item', item
                    labels.append('')
                    axes.append(None)
                except RuntimeError:
                    print 'Mac bug? Probably no axis available'

            dock = self.make_dock(item.name, item.group[:], labels, axes)
            self.dock_area.addDock(dock)
            item.plot = dock
            dock.closeClicked.connect(lambda: item.__setattr__('plot', None))

    def make_dock(self, name, array, labels=None, axes=None):
        'returns a dockable plot widget'
        labels = {pos: l for l, pos in zip(labels, ('bottom', 'left'))}
        if len(array.shape) in (2, 3):
            if len(array.shape) == 2:
                d = CrossSectionDock(name=name, area=self.dock_area)
            if len(array.shape) == 3:
                d = MoviePlotDock(array, name=name, area=self.dock_area)
            pos, scale = None, None
            if axes is not None:
                pos = [0, 0]
                scale = [1, 1]
                if axes[0] is not None:
                    pos[0] = axes[0][0]
                    scale[0] = axes[0][1] - axes[0][0]
                if axes[1] is not None:
                    pos[1] = axes[1][0]
                    scale[1] = axes[1][1] - axes[1][0]
            d.setImage(array, pos=pos, scale=scale)
            if labels is not None:
                d.setLabels(labels['bottom'], labels['left'], name)

        if len(array.shape) == 1:
            w = CrosshairPlotWidget(labels=labels)
            if axes and axes[0] is not None:
                w.plot(axes[0], array)
            else:
                w.plot(array)
            d = CloseableDock(name=name, widget=w, area=self.dock_area)

        return d
Esempio n. 37
0
    def initDialogSymbol(self,results=None,KData=None,bDrawText=False,InKLine = False):
        # 1) creates layouts
        dialog = QtGui.QDialog()   
        mainLayout = QtGui.QHBoxLayout()
        rightLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(rightLayout)
        dialog.setLayout(mainLayout)        
        dialog.setWindowTitle(('Strategy Results'))

        import os,sys        
        xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdataUI'))
        sys.path.append(xpower)

        from Widgets.pgCandleWidgetCross import pgCandleWidgetCross
        from Widgets.pgCrossAddition import pgCrossAddition
        from pyqtgraph.dockarea import DockArea,Dock 
        area = DockArea()   
        rightLayout.addWidget(area)

        # 2) creates widgets 
        #  2.1)candle        
        pgCandleView = pgCandleWidgetCross(dataForCandle=KData)        
        self.pricePlot(pgCandleView) 
        if(InKLine):
            self.indicatorsPlot(pgCandleView) 
        #self.signalPlot(pgCandleView,yBuy = KData.take([1],axis=1),ySell = KData.take([1],axis=1))
        self.signalPlot(pgCandleView)
        dCandle = Dock("candles",closable=True, size=(200,300))     ## give this dock the minimum possible size
        area.addDock(dCandle, 'bottom') 
        dCandle.addWidget(pgCandleView)        

        #  2.2)long_pnl 当前position_pnl曲线
        if(True):
            PyqtGraphPnl = pgCrossAddition()
            self.longPnlPlot(PyqtGraphPnl,bDrawText=bDrawText)
            long_pnl = np.array(self.results.long_pnl)
            self.signalPlot(PyqtGraphPnl,yBuy = long_pnl,ySell = long_pnl)
            dPnl = Dock("long_pnl", closable=True, size=(200,100))
            area.addDock(dPnl, 'bottom')    
            dPnl.addWidget(PyqtGraphPnl)           
            PyqtGraphPnl.setXLink(pgCandleView)
        # 2.3)long_cost 
        if(True):
            PyqtGraphPositionCost = pgCrossAddition()
            self.longCostPlot(PyqtGraphPositionCost)
            dPositionCost = Dock("long_cost",closable=True, size=(200,100))
            area.addDock(dPositionCost, 'bottom')        
            dPositionCost.addWidget(PyqtGraphPositionCost)             
            PyqtGraphPositionCost.setXLink(pgCandleView)         
        
        #  2.2)long_pnl 当前position_pnl曲线
        if(True):
            PyqtGraphPnl = pgCrossAddition()
            self.shortPnlPlot(PyqtGraphPnl,bDrawText=bDrawText)
            short_pnl = np.array(self.results.short_pnl)
            self.signalPlot(PyqtGraphPnl,yBuy = short_pnl,ySell = short_pnl)
            dPnl = Dock("short_pnl", closable=True, size=(200,100))
            area.addDock(dPnl, 'bottom')    
            dPnl.addWidget(PyqtGraphPnl)           
            PyqtGraphPnl.setXLink(pgCandleView)
        # 2.3)long_cost 
        if(True):
            PyqtGraphPositionCost = pgCrossAddition()
            self.shortCostPlot(PyqtGraphPositionCost)
            dPositionCost = Dock("short_cost",closable=True, size=(200,100))
            area.addDock(dPositionCost, 'bottom')        
            dPositionCost.addWidget(PyqtGraphPositionCost)             
            PyqtGraphPositionCost.setXLink(pgCandleView)          
        
        #  2.3)position_volume
        if(False):
            PyqtGraphPosition = pgCrossAddition()
            self.positionVolumePlot(PyqtGraphPosition)
            dPosition = Dock("position_volume",closable=True, size=(200,100))
            area.addDock(dPosition, 'bottom')        
            dPosition.addWidget(PyqtGraphPosition)             
            PyqtGraphPosition.setXLink(pgCandleView)
        #  2.4)portfolio  总资产变动曲线 cash + equity
        if(True):
            PyqtGraphPortfolio = pgCrossAddition()
            self.positionValuePlot(PyqtGraphPortfolio)
            dPortfolio = Dock("portfolio", closable=True,size=(200,100))
            area.addDock(dPortfolio, 'bottom')     
            dPortfolio.addWidget(PyqtGraphPortfolio)        
            PyqtGraphPortfolio.setXLink(pgCandleView)
        #  2.5)indicator
        if(True):
            PyqtGraphindicators = pgCrossAddition()
            self.pricePlot(PyqtGraphindicators)    
            self.indicatorsPlot(PyqtGraphindicators)
            
            self.signalPlot(PyqtGraphindicators)
            
            dIndicator = Dock("indicator",closable=True, size=(200,100))
            dIndicator.addWidget(PyqtGraphindicators)
            area.addDock(dIndicator, 'bottom', dCandle)  
            PyqtGraphindicators.setXLink(pgCandleView)
        #  2.2)position_pnl 当前position_pnl曲线
        if(False):
            PyqtGraphPortfolioInstruments = pgCrossAddition()
            self.instrumentPnlPlot(PyqtGraphPortfolioInstruments,bDrawText=bDrawText)
            position_pnl = np.array(self.results.position_pnl)
            self.signalPlot(PyqtGraphPortfolioInstruments,yBuy = position_pnl,ySell = position_pnl)
            dPnl = Dock("instrumentsPNL", closable=True, size=(200,100))
            area.addDock(dPnl, 'bottom',dPositionCost)    
            dPnl.addWidget(PyqtGraphPortfolioInstruments)           
            PyqtGraphPortfolioInstruments.setXLink(pgCandleView)            
        return dialog
Esempio n. 38
0
class InstrumentLoggingUi(WidgetContainerBase, WidgetContainerForm):
    levelNameList = ["debug", "info", "warning", "error", "critical"]
    levelValueList = [
        logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
        logging.CRITICAL
    ]
    plotConfigurationChanged = QtCore.pyqtSignal(object)

    def __init__(self, project, config):
        super(InstrumentLoggingUi, self).__init__()
        self.config = config
        self.project = project
        self.dockWidgetList = list()
        self.plotDict = dict()
        self.instrument = ""
        self.loggingLevel = config.get('Settings.loggingLevel', logging.INFO)
        self.consoleMaximumLines = config.get(
            'Settings.consoleMaximumLinesNew', 100)
        self.consoleEnable = config.get('Settings.consoleEnable', False)
        self.printMenu = None
        if self.loggingLevel not in self.levelValueList:
            self.loggingLevel = logging.INFO

    def __enter__(self):
        return self

    def __exit__(self, excepttype, value, traceback):
        return False

    def setupUi(self, parent):
        super(InstrumentLoggingUi, self).setupUi(parent)

        self.dockWidgetConsole.hide()
        self.loggerUi = LoggerLevelsUi(self.config)
        self.loggerUi.setupUi(self.loggerUi)
        self.loggerDock = QtWidgets.QDockWidget("Logging")
        self.loggerDock.setWidget(self.loggerUi)
        self.loggerDock.setObjectName("_LoggerDock")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.loggerDock)
        self.loggerDock.hide()

        logger = logging.getLogger()
        self.toolBar.addWidget(ExceptionLogButton())

        # Setup Console Dockwidget
        self.levelComboBox.addItems(self.levelNameList)
        self.levelComboBox.currentIndexChanged[int].connect(
            self.setLoggingLevel)
        self.levelComboBox.setCurrentIndex(
            self.levelValueList.index(self.loggingLevel))
        self.consoleClearButton.clicked.connect(self.onClearConsole)
        self.linesSpinBox.valueChanged.connect(
            self.onConsoleMaximumLinesChanged)
        self.linesSpinBox.setValue(self.consoleMaximumLines)
        self.checkBoxEnableConsole.stateChanged.connect(self.onEnableConsole)
        self.checkBoxEnableConsole.setChecked(self.consoleEnable)

        self.parent = parent
        self.tabDict = SequenceDict()

        self.setupPlots()

        self.preferencesUi = PreferencesUi(config, self)
        self.preferencesUi.setupUi(self.preferencesUi)
        self.preferencesUiDock = QtWidgets.QDockWidget("Print Preferences")
        self.preferencesUiDock.setWidget(self.preferencesUi)
        self.preferencesUiDock.setObjectName("_preferencesUi")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.preferencesUiDock)

        # Traceui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, "Main",
                                       self.plotDict)
        self.traceui.setupUi(self.traceui)
        setattr(self.traceui, 'autoSaveTraces',
                self.config.get('autoSaveTraces', False))
        self.traceui.autoSaveAction = QtWidgets.QAction(
            'Autosave traces', self.traceui)
        self.traceui.autoSaveAction.setCheckable(True)
        self.traceui.autoSaveAction.setChecked(self.traceui.autoSaveTraces)
        self.traceui.autoSaveAction.triggered.connect(
            lambda checked: setattr(self.traceui, 'autoSaveTraces', checked))
        self.traceui.addAction(self.traceui.autoSaveAction)
        traceuiDock = self.setupAsDockWidget(self.traceui, "Traces",
                                             QtCore.Qt.LeftDockWidgetArea)

        # new fit widget
        self.fitWidget = FitUi(self.traceui, self.config, "Main")
        self.fitWidget.setupUi(self.fitWidget)
        self.fitWidgetDock = self.setupAsDockWidget(
            self.fitWidget,
            "Fit",
            QtCore.Qt.LeftDockWidgetArea,
            stackBelow=traceuiDock)

        self.instrumentLoggingHandler = InstrumentLoggingHandler(
            self.traceui, self.plotDict, self.config, 'externalInput')

        self.ExternalParametersSelectionUi = InstrumentLoggingSelection(
            self.config,
            classdict=LoggingInstruments,
            plotNames=list(self.plotDict.keys()),
            instrumentLoggingHandler=self.instrumentLoggingHandler)
        self.ExternalParametersSelectionUi.setupUi(
            self.ExternalParametersSelectionUi)
        self.ExternalParameterSelectionDock = QtWidgets.QDockWidget(
            "Params Selection")
        self.ExternalParameterSelectionDock.setObjectName(
            "_ExternalParameterSelectionDock")
        self.ExternalParameterSelectionDock.setWidget(
            self.ExternalParametersSelectionUi)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.ExternalParameterSelectionDock)
        self.instrumentLoggingHandler.paramTreeChanged.connect(
            self.ExternalParametersSelectionUi.refreshParamTree)
        self.instrumentLoggingHandler.setInputChannels(
            self.ExternalParametersSelectionUi.inputChannels())
        self.ExternalParametersSelectionUi.inputChannelsChanged.connect(
            self.instrumentLoggingHandler.setInputChannels)

        self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config)
        self.instrumentLoggingDisplay.setupUi(
            self.ExternalParametersSelectionUi.inputChannels(),
            self.instrumentLoggingDisplay)
        self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget(
            "Params Reading")
        self.instrumentLoggingDisplayDock.setObjectName(
            "_ExternalParameterDisplayDock")
        self.instrumentLoggingDisplayDock.setWidget(
            self.instrumentLoggingDisplay)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.instrumentLoggingDisplayDock)
        self.ExternalParametersSelectionUi.inputChannelsChanged.connect(
            self.instrumentLoggingDisplay.setupParameters)
        self.instrumentLoggingHandler.newData.connect(
            self.instrumentLoggingDisplay.update)

        self.instrumentLoggingQueryUi = InstrumentLoggerQueryUi(
            self.config, self.traceui, self.plotDict)
        self.instrumentLoggingQueryUi.setupUi(self.instrumentLoggingQueryUi)
        self.instrumentLoggingQueryUiDock = self.setupAsDockWidget(
            self.instrumentLoggingQueryUi, "Query",
            QtCore.Qt.LeftDockWidgetArea)

        self.addPlot = QtWidgets.QAction(
            QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)

        self.removePlot = QtWidgets.QAction(
            QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot",
            self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtWidgets.QAction(
            QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot",
            self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        self.setWindowTitle("Instrument Logger ({0})".format(self.project))
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        try:
            if 'pyqtgraph-dockareastate' in self.config:
                self.area.restoreState(self.config['pyqtgraph-dockareastate'])
        except Exception as e:
            logger.error(
                "Cannot restore dock state in experiment {0}. Exception occurred: "
                .format(self.experimentName) + str(e))
        self.initMenu()
        self.actionProject.triggered.connect(self.onProjectSelection)
        self.actionExit.triggered.connect(self.onClose)

    def onProjectSelection(self):
        ui = ProjectInfoUi(self.project)
        ui.show()
        ui.exec_()

    def onEnableConsole(self, state):
        self.consoleEnable = state == QtCore.Qt.Checked

    def onClearConsole(self):
        self.textEditConsole.clear()

    def onConsoleMaximumLinesChanged(self, maxlines):
        self.consoleMaximumLines = maxlines
        self.textEditConsole.document().setMaximumBlockCount(maxlines)

    def setLoggingLevel(self, index):
        self.loggingLevel = self.levelValueList[index]

    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = dict()
        # initialize all the plot windows we want
        plotNames = self.config.get('PlotNames', ['Scan'])
        if len(plotNames) < 1:
            plotNames.append('Scan')
        for name in plotNames:
            dock = Dock(name)
            widget = DateTimePlotWidget(self, name=name)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {
                "dock": dock,
                "widget": widget,
                "view": view
            }

    def setupAsDockWidget(self,
                          widget,
                          name,
                          area=QtCore.Qt.RightDockWidgetArea,
                          stackAbove=None,
                          stackBelow=None):
        dock = QtWidgets.QDockWidget(name)
        dock.setObjectName(name)
        dock.setWidget(widget)
        self.addDockWidget(area, dock)
        self.dockWidgetList.append(dock)
        if stackAbove is not None:
            self.tabifyDockWidget(stackAbove, dock)
        elif stackBelow is not None:
            self.tabifyDockWidget(dock, stackBelow)
        return dock

    def onAddPlot(self):
        name, ok = QtWidgets.QInputDialog.getText(
            self, 'Plot Name', 'Please enter a plot name: ')
        if ok:
            name = str(name)
            dock = Dock(name)
            widget = DateTimePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {
                "dock": dock,
                "widget": widget,
                "view": view
            }
            self.plotConfigurationChanged.emit(self.plotDict)

    def onRemovePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(
                self,
                "Select Plot",
                "Please select which plot to remove: ",
                list(self.plotDict.keys()),
                editable=False)
            if ok:
                name = str(name)
                self.plotDict[name]["dock"].close()
                del self.plotDict[name]
                self.plotConfigurationChanged.emit(self.plotDict)
        else:
            logger.info("There are no plots which can be removed")

    def onRenamePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(
                self,
                "Select Plot",
                "Please select which plot to rename: ",
                list(self.plotDict.keys()),
                editable=False)
            if ok:
                newName, newOk = QtWidgets.QInputDialog.getText(
                    self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk:
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(str(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    del self.plotDict[name]
                    self.plotConfigurationChanged.emit(self.plotDict)
        else:
            logger.info("There are no plots which can be renamed")

    def onSave(self):
        logger = logging.getLogger(__name__)
        logger.info("Saving config")
        filename, _ = DataDirectory.DataDirectory().sequencefile(
            "InstrumentLogger-configuration.db")
        self.saveConfig()
        self.config.saveConfig(filename)

    def onClose(self):
        self.parent.close()

    def onMessageWrite(self, message, level=logging.DEBUG):
        if self.consoleEnable and level >= self.loggingLevel:
            cursor = self.textEditConsole.textCursor()
            cursor.movePosition(QtGui.QTextCursor.End)
            if level < logging.ERROR:
                self.textEditConsole.setTextColor(QtCore.Qt.black)
            else:
                self.textEditConsole.setTextColor(QtCore.Qt.red)
            cursor.insertText(message)
            self.textEditConsole.setTextCursor(cursor)
            self.textEditConsole.ensureCursorVisible()

    def closeEvent(self, e):
        logger = logging.getLogger(__name__)
        logger.info("Close Event")
        logger = logging.getLogger("")
        logger.debug("Saving Configuration")
        self.saveConfig()

    def saveConfig(self):
        self.config['MainWindow.State'] = self.parent.saveState()
        for tab in list(self.tabDict.values()):
            tab.saveConfig()
        self.config['MainWindow.pos'] = self.pos()
        self.config['MainWindow.size'] = self.size()
        self.config['PlotNames'] = list(self.plotDict.keys())
        self.config['pyqtgraph-dockareastate'] = self.area.saveState()
        self.config['Settings.loggingLevel'] = self.loggingLevel
        self.config[
            'Settings.consoleMaximumLinesNew'] = self.consoleMaximumLines
        self.config['Settings.consoleEnable'] = self.consoleEnable
        self.config['autoSaveTraces'] = self.traceui.autoSaveTraces
        self.ExternalParametersSelectionUi.saveConfig()
        self.instrumentLoggingHandler.saveConfig()
        self.instrumentLoggingQueryUi.saveConfig()
        self.preferencesUi.saveConfig()

    def onPrint(self, target):
        printer = QtPrintSupport.QPrinter(
            mode=QtPrintSupport.QPrinter.ScreenResolution)
        if self.preferencesUi.preferences().printPreferences.doPrint:
            dialog = QtPrintSupport.QPrintDialog(printer, self)
            dialog.setWindowTitle("Print Document")
            if dialog.exec_() != QtWidgets.QDialog.Accepted:
                return
        printer.setResolution(
            self.preferencesUi.preferences().printPreferences.printResolution)

        pdfPrinter = QtPrintSupport.QPrinter()
        pdfPrinter.setOutputFormat(QtPrintSupport.QPrinter.PdfFormat)
        pdfPrinter.setOutputFileName(
            DataDirectory.DataDirectory().sequencefile(target + ".pdf")[0])
        self.doPrint(target, printer, pdfPrinter,
                     self.preferencesUi.preferences().printPreferences)

    def doPrint(self, target, printer, pdfPrinter, preferences):
        widget = self.plotDict[target]['widget']
        if preferences.savePdf:
            with SceneToPrint(widget):
                painter = QtGui.QPainter(pdfPrinter)
                widget.render(painter)
                del painter

        # create an exporter instance, as an argument give it
        # the item you wish to export
        with SceneToPrint(widget, preferences.gridLinewidth,
                          preferences.curveLinewidth):
            exporter = ImageExporter(widget._graphicsView.scene())

            # set export parameters if needed
            pageWidth = printer.pageRect().width()
            pageHeight = printer.pageRect().height()
            exporter.parameters(
            )['width'] = pageWidth * preferences.printWidth  # (note this also affects height parameter)

            # save to file
            png = exporter.export(toBytes=True)
            if preferences.savePng:
                png.save(DataDirectory.DataDirectory().sequencefile(target +
                                                                    ".png")[0])

            if preferences.doPrint:
                painter = QtGui.QPainter(printer)
                painter.drawImage(
                    QtCore.QPoint(pageWidth * preferences.printX,
                                  pageHeight * preferences.printY), png)

    def initMenu(self):
        """Initialize print menu and view menu"""
        #View menu
        self.menuView.clear()
        dockList = self.findChildren(QtWidgets.QDockWidget)
        for dock in dockList:
            self.menuView.addAction(dock.toggleViewAction())

        # Print menu
        if self.printMenu is not None:
            self.printMenu.clear()
        else:
            self.printMenu = self.menuFile.addMenu("Print")
        for plot in list(self.plotDict.keys()):
            action = self.printMenu.addAction(plot)
            action.triggered.connect(partial(self.onPrint, plot))
Esempio n. 39
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowTitle("Liveplot")
        self.dockarea = DockArea()
        self.setCentralWidget(self.dockarea)
        self.namelist = NameList(self)
        self.addDockWidget(QtConst.LeftDockWidgetArea, self.namelist)
        self.ctx = zmq.Context()
        sock = self.ctx.socket(zmq.SUB)
        sock.bind('tcp://127.0.0.1:7755')
        sock.setsockopt(zmq.SUBSCRIBE, '')
        self.conn = ZMQSocket(sock)
        self.conn.readyRead.connect(lambda: self.read_from(self.conn))
        self.bytes = bytearray()
        self.target_size = 0
        self.meta = None
        self.insert_dock_right = True
        self.conns = []


    def accept(self):
        logging.debug('connection accepted')
        conn = self.listener.nextPendingConnection()
        if hasattr(socket, 'fromfd'):
            socket.fromfd(conn.socketDescriptor(), socket.AF_INET, socket.SOCK_STREAM).setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**22)
        self.conns.append(conn)
        conn.readyRead.connect(lambda: self.read_from(conn))

    # noinspection PyNoneFunctionAssignment
    def read_from(self, conn):
        logging.debug('reading data')
        if not self.target_size:
            self.meta = conn._socket.recv_json()
            self.target_size = self.meta['arrsize']
        if self.target_size > 0:
            n = self.target_size - len(self.bytes)
            data = bytearray(conn.read(n))
            self.bytes.extend(data)
        if len(self.bytes) == self.target_size:
            self.process_bytes()
        if conn.bytesAvailable():
            self.read_from(conn)

    def process_bytes(self):
        self.target_size = 0
        if len(self.bytes) > 0:
            arr = np.frombuffer(buffer(self.bytes), dtype=self.meta['dtype'])
            try:
                arr.resize(self.meta['shape'])
            except ValueError:
                arr = arr.reshape(self.meta['shape'])
        else:
            arr = None
        self.bytes = bytearray()
        self.do_operation(arr)

    def do_operation(self, arr=None):
        def clear(name):
            self.namelist[name].clear()

        def close(name):
            self.namelist[name].close()

        def remove(name):
            del self.namelist[name]

        meta = self.meta
        operation = meta['operation']
        name = meta['name']

        if name in self.namelist:
            pw = self.namelist[name]
            if pw.closed:
                pw.closed = False
                self.dockarea.addDock(pw)

        else:
            if name != "*" and operation != "remove" and ("rank" in meta):
                pw = self.add_new_plot(meta['rank'], name)
                return

            if operation == 'clear' and name == "*":
                map(clear, self.namelist.keys())
            if operation == 'close' and name == "*":
                map(close, self.namelist.keys())
            if operation == 'remove' and name == "*":
                map(remove, self.namelist.keys())
            return

        if operation == 'clear':
            pw.clear()
        if operation == 'close':
            pw.close()
        if operation == 'remove':
            del self.namelist[name]

        elif operation == 'plot_y':
            start_step = meta['start_step']
            if start_step is not None:
                x0, dx = start_step
                nx = len(arr)
                xs = np.linspace(x0, x0 + (nx-1)*dx, nx)
                pw.plot(xs, arr)
            else:
                pw.plot(arr)
        elif operation == 'plot_xy':
            pw.plot(arr[0], arr[1], parametric=True)
        elif operation == 'plot_z':
            start_step = meta['start_step']
            if start_step is not None:
                (x0, dx), (y0, dy) = start_step
                pw.setImage(arr, pos=(x0, y0), scale=(dx, dy))
            else:
                pw.setImage(arr)
        elif operation == 'append_y':
            xs, ys = pw.get_data()
            new_ys = list(ys)
            new_ys.append(meta['value'])
            start_step = meta['start_step']
            if start_step is not None:
                x0, dx = start_step
                nx = len(new_ys)
                xs = np.linspace(x0, x0 + (nx-1)*dx, nx)
                pw.plot(xs, new_ys)
            else:
                pw.plot(new_ys)
        elif operation == 'append_xy':
            xs, ys = pw.get_data()
            xn, yn = meta['value']
            new_xs = list(xs)
            new_xs.append(xn)
            new_ys = list(ys)
            new_ys.append(yn)
            pw.plot(new_xs, new_ys, parametric=True)

        elif operation == 'append_z':
            image = pw.get_data()
            if image is None:
                image = np.array([arr])
            else:
                try:
                    image = np.vstack((image, [arr]))
                except ValueError:
                    image = np.array([arr])
            start_step = meta['start_step']
            if start_step is not None:
                (x0, dx), (y0, dy) = start_step
                pw.setImage(image, pos=(x0, y0), scale=(dx, dy))
            else:
                pw.setImage(image)

    def add_new_plot(self, rank, name):
        pw = widgets.get_widget(rank, name)
        self.add_plot(pw)
        self.namelist[name] = pw
        return pw

    def add_plot(self, pw):
        self.insert_dock_right = not self.insert_dock_right
        self.dockarea.addDock(pw, position=['bottom', 'right'][self.insert_dock_right])

    def sizeHint(self):
        return QtCore.QSize(1000, 600)
Esempio n. 40
0
    def setup_widgets(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        # Docks
        dock_occcupancy = Dock("Occupancy", size=(400, 400))
        dock_tot = Dock("Time over threshold values (TOT)", size=(200, 200))
        dock_hit_timing = Dock("Hit count histogram", size=(200, 200))
        dock_status = Dock("Status", size=(800, 40))

        dock_area.addDock(dock_occcupancy, 'top')

        dock_area.addDock(dock_tot, 'right', dock_occcupancy)
        dock_area.addDock(dock_hit_timing, 'bottom', dock_tot)

        dock_area.addDock(dock_status, 'top')

        # Status dock on top
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz")
        self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz")
        self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz")
        self.timestamp_label = QtGui.QLabel("Data Timestamp\n")
        self.plot_delay_label = QtGui.QLabel("Plot Delay\n")
        self.scan_parameter_label = QtGui.QLabel("Parameter ID\n")
        self.spin_box = Qt.QSpinBox(value=0)
        self.spin_box.setMaximum(1000000)
        self.spin_box.setSuffix(" Readouts")
        self.reset_button = QtGui.QPushButton('Reset')
        layout.addWidget(self.timestamp_label, 0, 0, 0, 1)
        layout.addWidget(self.plot_delay_label, 0, 1, 0, 1)
        layout.addWidget(self.rate_label, 0, 2, 0, 1)
        layout.addWidget(self.hit_rate_label, 0, 3, 0, 1)
        layout.addWidget(self.event_rate_label, 0, 4, 0, 1)
        layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1)
        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        layout.addWidget(self.reset_button, 0, 7, 0, 1)
        dock_status.addWidget(cw)

        # Connect widgets
        self.reset_button.clicked.connect(lambda: self.send_command('RESET'))
        self.spin_box.valueChanged.connect(
            lambda value: self.send_command(str(value)))

        # Different plot docks
        occupancy_graphics = pg.GraphicsLayoutWidget()
        occupancy_graphics.show()
        view = occupancy_graphics.addViewBox()
        view.invertY(True)
        self.occupancy_img = pg.ImageItem(border='w')
        # Set colormap from matplotlib
        lut = generatePgColormap("viridis").getLookupTable(0.0, 1.0, 256)

        self.occupancy_img.setLookupTable(lut, update=True)
        # view.addItem(self.occupancy_img)
        plot = pg.PlotWidget(viewBox=view,
                             labels={
                                 'bottom': 'Column',
                                 'left': 'Row'
                             })
        plot.addItem(self.occupancy_img)

        dock_occcupancy.addWidget(plot)

        tot_plot_widget = pg.PlotWidget(background="w")
        self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17),
                                             np.zeros((16)),
                                             stepMode=True)
        tot_plot_widget.showGrid(y=True)
        dock_tot.addWidget(tot_plot_widget)

        hit_timing_widget = pg.PlotWidget()
        self.hist_hit_count = hit_timing_widget.plot(np.linspace(
            -0.5, 100.5, 101),
                                                     np.zeros((100)),
                                                     stepMode=True)
        hit_timing_widget.showGrid(y=True)
        dock_hit_timing.addWidget(hit_timing_widget)

        self.plot_delay = 0
Esempio n. 41
0
class OnlineMonitorApplication(QtGui.QMainWindow):
    def __init__(self, socket_addr):
        super(OnlineMonitorApplication, self).__init__()
        self.setup_plots()
        self.add_widgets()
        self.fps = 0  # data frames per second
        self.hps = 0  # hits per second
        self.eps = 0  # events per second
        self.plot_delay = 0
        self.updateTime = ptime.time()
        self.total_hits = 0
        self.total_events = 0
        self.setup_data_worker_and_start(socket_addr)
        self.reset_plots()

    def closeEvent(self, event):
        super(OnlineMonitorApplication, self).closeEvent(event)
        # wait for thread
        self.worker.stop()
        self.thread.wait(
            2
        )  # fixes message: QThread: Destroyed while thread is still running

    def setup_data_worker_and_start(self, socket_addr):
        self.thread = QtCore.QThread()  # no parent
        self.worker = DataWorker()  # no parent
        self.worker.meta_data.connect(self.on_meta_data)
        self.worker.interpreted_data.connect(self.on_interpreted_data)
        self.worker.run_start.connect(self.on_run_start)
        self.worker.run_config_data.connect(self.on_run_config_data)
        self.worker.global_config_data.connect(self.on_global_config_data)
        self.worker.filename.connect(self.on_filename)
        self.spin_box.valueChanged.connect(
            self.worker.on_set_integrate_readouts)
        self.reset_button.clicked.connect(self.on_reset)
        self.worker.moveToThread(self.thread)
        self.worker.connect(socket_addr)
        #         self.aboutToQuit.connect(self.worker.stop)  # QtGui.QApplication
        self.thread.started.connect(self.worker.process_data)
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)
        self.thread.start()

    def setup_plots(self):
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')

    def add_widgets(self):
        # Main window with dock area
        self.dock_area = DockArea()
        self.setCentralWidget(self.dock_area)

        # Docks
        dock_occcupancy = Dock("Occupancy", size=(400, 400))
        dock_run_config = Dock("Run configuration", size=(400, 400))
        dock_global_config = Dock("Global configuration", size=(400, 400))
        dock_tot = Dock("ToT", size=(400, 400))
        dock_tdc = Dock("TDC", size=(400, 400))
        dock_tdc_distance = Dock("TDC distance", size=(400, 400))
        dock_event_status = Dock("Event status", size=(400, 400))
        dock_trigger_status = Dock("Trigger status", size=(400, 400))
        dock_service_records = Dock("Service records", size=(400, 400))
        dock_hit_timing = Dock("Hit timing (rel. BCID)", size=(400, 400))
        dock_status = Dock("Status", size=(800, 40))
        self.dock_area.addDock(dock_global_config, 'left')
        self.dock_area.addDock(dock_run_config, 'above', dock_global_config)
        self.dock_area.addDock(dock_occcupancy, 'above', dock_run_config)
        self.dock_area.addDock(dock_tdc_distance, 'right', dock_occcupancy)
        self.dock_area.addDock(dock_tdc, 'above', dock_tdc_distance)
        self.dock_area.addDock(dock_tot, 'above', dock_tdc)
        self.dock_area.addDock(dock_service_records, 'bottom', dock_occcupancy)
        self.dock_area.addDock(dock_trigger_status, 'above',
                               dock_service_records)
        self.dock_area.addDock(dock_event_status, 'above', dock_trigger_status)
        self.dock_area.addDock(dock_hit_timing, 'bottom', dock_tot)
        self.dock_area.addDock(dock_status, 'top')

        # Status widget
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz")
        self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz")
        self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz")
        self.timestamp_label = QtGui.QLabel("Data Timestamp\n")
        self.plot_delay_label = QtGui.QLabel("Plot Delay\n")
        self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n")
        self.spin_box = Qt.QSpinBox(value=1)
        self.spin_box.setMaximum(1000000)
        self.spin_box.setSuffix(" Readouts")
        self.reset_button = QtGui.QPushButton('Reset')
        layout.addWidget(self.timestamp_label, 0, 0, 0, 1)
        layout.addWidget(self.plot_delay_label, 0, 1, 0, 1)
        layout.addWidget(self.rate_label, 0, 2, 0, 1)
        layout.addWidget(self.hit_rate_label, 0, 3, 0, 1)
        layout.addWidget(self.event_rate_label, 0, 4, 0, 1)
        layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1)
        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        layout.addWidget(self.reset_button, 0, 7, 0, 1)
        dock_status.addWidget(cw)

        # Run config dock
        self.run_conf_list_widget = Qt.QListWidget()
        dock_run_config.addWidget(self.run_conf_list_widget)

        # Global config dock
        self.global_conf_list_widget = Qt.QListWidget()
        dock_global_config.addWidget(self.global_conf_list_widget)

        # Different plot docks
        occupancy_graphics = pg.GraphicsLayoutWidget()
        occupancy_graphics.show()
        view = occupancy_graphics.addViewBox()
        self.occupancy_img = pg.ImageItem(border='w')
        view.addItem(self.occupancy_img)
        view.setRange(QtCore.QRectF(0, 0, 80, 336))
        dock_occcupancy.addWidget(occupancy_graphics)

        tot_plot_widget = pg.PlotWidget(background="w")
        self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5,
                                                         15.5,
                                                         17,
                                                         endpoint=True),
                                             np.zeros((16)),
                                             stepMode=True)
        tot_plot_widget.showGrid(y=True)
        dock_tot.addWidget(tot_plot_widget)

        tdc_plot_widget = pg.PlotWidget(background="w")
        self.tdc_plot = tdc_plot_widget.plot(np.linspace(-0.5,
                                                         4095.5,
                                                         4097,
                                                         endpoint=True),
                                             np.zeros((4096)),
                                             stepMode=True)
        tdc_plot_widget.showGrid(y=True)
        tdc_plot_widget.setXRange(0, 800, update=True)
        dock_tdc.addWidget(tdc_plot_widget)

        tdc_distance_plot_widget = pg.PlotWidget(background="w")
        self.tdc_distance_plot = tdc_distance_plot_widget.plot(np.linspace(
            -0.5, 255.5, 257, endpoint=True),
                                                               np.zeros((256)),
                                                               stepMode=True)
        tdc_distance_plot_widget.showGrid(y=True)
        tdc_distance_plot_widget.setXRange(0, 800, update=True)
        dock_tdc_distance.addWidget(tdc_distance_plot_widget)

        event_status_widget = pg.PlotWidget()
        self.event_status_plot = event_status_widget.plot(np.linspace(
            -0.5, 15.5, 17, endpoint=True),
                                                          np.zeros((16)),
                                                          stepMode=True)
        event_status_widget.showGrid(y=True)
        dock_event_status.addWidget(event_status_widget)

        trigger_status_widget = pg.PlotWidget()
        self.trigger_status_plot = trigger_status_widget.plot(np.linspace(
            -0.5, 7.5, 9, endpoint=True),
                                                              np.zeros((8)),
                                                              stepMode=True)
        trigger_status_widget.showGrid(y=True)
        dock_trigger_status.addWidget(trigger_status_widget)

        service_record_widget = pg.PlotWidget()
        self.service_record_plot = service_record_widget.plot(np.linspace(
            -0.5, 31.5, 33, endpoint=True),
                                                              np.zeros((32)),
                                                              stepMode=True)
        service_record_widget.showGrid(y=True)
        dock_service_records.addWidget(service_record_widget)

        hit_timing_widget = pg.PlotWidget()
        self.hit_timing_plot = hit_timing_widget.plot(np.linspace(
            -0.5, 15.5, 17, endpoint=True),
                                                      np.zeros((16)),
                                                      stepMode=True)
        hit_timing_widget.showGrid(y=True)
        dock_hit_timing.addWidget(hit_timing_widget)

    def on_reset(self):
        self.worker.reset()
        self.total_hits = 0
        self.total_events = 0
        self.reset_plots()
        self.update_rate(0, 0, 0, 0, 0)

    def on_run_start(self):
        # clear config data widgets
        self.run_conf_list_widget.clear()
        self.global_conf_list_widget.clear()
        self.setWindowTitle('Online Monitor')

    def on_run_config_data(self, config_data):
        self.setup_run_config_text(**config_data)

    def on_global_config_data(self, config_data):
        self.setup_global_config_text(**config_data)

    def on_filename(self, config_data):
        self.setup_filename(**config_data)

    def setup_run_config_text(self, conf):
        for key, value in sorted(conf.iteritems()):
            item = Qt.QListWidgetItem("%s: %s" % (key, value))
            self.run_conf_list_widget.addItem(item)

    def setup_global_config_text(self, conf):
        for key, value in sorted(conf.iteritems()):
            item = Qt.QListWidgetItem("%s: %s" % (key, value))
            self.global_conf_list_widget.addItem(item)

    def setup_filename(self, conf):
        self.setWindowTitle('Online Monitor - %s' % conf)

    def on_interpreted_data(self, interpreted_data):
        self.update_plots(**interpreted_data)

    def reset_plots(self):
        self.update_plots(np.zeros((80, 336, 1), dtype=np.uint8),
                          np.zeros((16, ), dtype=np.uint8),
                          np.zeros((4096, ), dtype=np.uint8),
                          np.zeros((256, ), dtype=np.uint8),
                          np.zeros((16, ), dtype=np.uint8),
                          np.zeros((32, ), dtype=np.uint8),
                          np.zeros((8, ), dtype=np.uint8),
                          np.zeros((16, ), dtype=np.uint8))

    def update_plots(self, occupancy, tot_hist, tdc_counters, tdc_distance,
                     error_counters, service_records_counters,
                     trigger_error_counters, rel_bcid_hist):
        self.occupancy_img.setImage(occupancy[:, ::-1, 0], autoDownsample=True)
        self.tot_plot.setData(x=np.linspace(-0.5, 15.5, 17, endpoint=True),
                              y=tot_hist,
                              fillLevel=0,
                              brush=(0, 0, 255, 150),
                              stepMode=True)
        self.tdc_plot.setData(x=np.linspace(-0.5, 4095.5, 4097, endpoint=True),
                              y=tdc_counters,
                              fillLevel=0,
                              brush=(0, 0, 255, 150),
                              stepMode=True)
        self.tdc_distance_plot.setData(x=np.linspace(-0.5,
                                                     255.5,
                                                     257,
                                                     endpoint=True),
                                       y=tdc_distance,
                                       fillLevel=0,
                                       brush=(0, 0, 255, 150),
                                       stepMode=True)
        self.event_status_plot.setData(x=np.linspace(-0.5,
                                                     15.5,
                                                     17,
                                                     endpoint=True),
                                       y=error_counters,
                                       fillLevel=0,
                                       brush=(0, 0, 255, 150),
                                       stepMode=True)
        self.service_record_plot.setData(x=np.linspace(-0.5,
                                                       31.5,
                                                       33,
                                                       endpoint=True),
                                         y=service_records_counters,
                                         fillLevel=0,
                                         brush=(0, 0, 255, 150),
                                         stepMode=True)
        self.trigger_status_plot.setData(x=np.linspace(-0.5,
                                                       7.5,
                                                       9,
                                                       endpoint=True),
                                         y=trigger_error_counters,
                                         fillLevel=0,
                                         brush=(0, 0, 255, 150),
                                         stepMode=True)
        self.hit_timing_plot.setData(x=np.linspace(-0.5,
                                                   15.5,
                                                   17,
                                                   endpoint=True),
                                     y=rel_bcid_hist[:16],
                                     fillLevel=0,
                                     brush=(0, 0, 255, 150),
                                     stepMode=True)

    def on_meta_data(self, meta_data):
        self.update_monitor(**meta_data)

    def update_monitor(self, timestamp_start, timestamp_stop, readout_error,
                       scan_parameters, n_hits, n_events):
        self.timestamp_label.setText(
            "Data Timestamp\n%s" %
            time.asctime(time.localtime(timestamp_stop)))
        self.scan_parameter_label.setText(
            "Scan Parameters\n%s" %
            ', '.join('%s: %s' % (str(key), str(val))
                      for key, val in scan_parameters.iteritems()))
        now = ptime.time()
        recent_total_hits = n_hits
        recent_total_events = n_events
        self.plot_delay = self.plot_delay * 0.9 + (now - timestamp_stop) * 0.1
        self.plot_delay_label.setText(
            "Plot Delay\n%s" %
            ((time.strftime('%H:%M:%S', time.gmtime(self.plot_delay)))
             if abs(self.plot_delay) > 5 else "%1.2f ms" %
             (self.plot_delay * 1.e3)))
        recent_fps = 1.0 / (now - self.updateTime)  # calculate FPS
        recent_hps = (recent_total_hits - self.total_hits) / (now -
                                                              self.updateTime)
        recent_eps = (recent_total_events -
                      self.total_events) / (now - self.updateTime)
        self.updateTime = now
        self.total_hits = recent_total_hits
        self.total_events = recent_total_events
        self.fps = self.fps * 0.7 + recent_fps * 0.3
        self.hps = self.hps + (recent_hps - self.hps) * 0.3 / self.fps
        self.eps = self.eps + (recent_eps - self.eps) * 0.3 / self.fps
        self.update_rate(self.fps, self.hps, recent_total_hits, self.eps,
                         recent_total_events)

    def update_rate(self, fps, hps, recent_total_hits, eps,
                    recent_total_events):
        self.rate_label.setText("Readout Rate\n%d Hz" % fps)
        if self.spin_box.value(
        ) == 0:  # show number of hits, all hits are integrated
            self.hit_rate_label.setText("Total Hits\n%d" %
                                        int(recent_total_hits))
        else:
            self.hit_rate_label.setText("Hit Rate\n%d Hz" % int(hps))
        if self.spin_box.value() == 0:  # show number of events
            self.event_rate_label.setText("Total Events\n%d" %
                                          int(recent_total_events))
        else:
            self.event_rate_label.setText("Event Rate\n%d Hz" % int(eps))
Esempio n. 42
0
class GUIBuilder(QMainWindow):
    def __init__(self, instance):
        super(GUIBuilder, self).__init__()
        self.setCentralWidget(QWidget())
        layout = QVBoxLayout(self.centralWidget())
        self.plots_layout = DockArea()
        layout.addWidget(self.plots_layout)
        self.form_layout = QFormLayout()
        self.form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        layout.addLayout(self.form_layout)
        self.buttons_layout = QHBoxLayout()
        layout.addLayout(self.buttons_layout)

        self.instance = instance
        self.plot_widgets = {}
        self.plot_data_items = {}
        self.plot_color_generators = {}

        seen_form_items = []
        seen_plot_items = []

        for node in ast.walk(ast.parse(getsource(type(instance)))):
            if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
                if node.func.id.startswith('gb_get_') or node.func.id.startswith('gb_set_'):
                    segs = node.func.id.split('_')
                    caster = __builtins__[segs[2]]
                    name = "_".join(segs[3:])

                    if name in seen_form_items:
                        continue
                    seen_form_items.append(name)

                    if caster is bool:
                        editor = QCheckBox()
                        if node.func.id.startswith('gb_get_') and node.args:
                            editor.setChecked(node.args[0].id == 'True')
                        get_fn = lambda e=editor: e.isChecked()
                        set_fn = lambda v, e=editor: e.setChecked(v)
                    else:
                        editor = QLineEdit()
                        if node.func.id.startswith('gb_get_') and node.args:
                            if isinstance(node.args[0], ast.Num):
                                init = node.args[0].n
                            else:
                                init = node.args[0].s
                            editor.setText(str(caster(init)))
                        get_fn = lambda e=editor, c=caster: c(e.text())
                        set_fn = lambda val, e=editor: e.setText(str(val))

                    base_name = "_".join(segs[2:])
                    get_name = "gb_get_" + base_name
                    set_name = "gb_set_" + base_name
                    __builtins__[get_name] = lambda init=0, get_fn=get_fn: get_fn()
                    __builtins__[set_name] = lambda val, set_fn=set_fn: set_fn(val)

                    self.form_layout.addRow(prettify(name), editor)

                if node.func.id.startswith('gb_plot_'):
                    segs = node.func.id.split("_")
                    plot_type = segs[2]
                    plot_name = segs[3]
                    if len(segs) >= 5:
                        data_item_name = "_".join(segs[4:])
                    else:
                        data_item_name = ""

                    if (plot_name, data_item_name) in seen_plot_items:
                        continue
                    seen_plot_items.append((plot_name, data_item_name))

                    if plot_name not in self.plot_widgets:
                        if plot_type in ['y', 'xy']:
                            pw = PlotWidget()
                            self.plot_widgets[plot_name] = pw
                            self.plot_color_generators[plot_name] = itertools.cycle('rgb')
                            pw.addLegend()
                        else:
                            raise ValueError("Unknown plot type in {}: {}".format(node.func.id, plot_type))
                        dock = Dock(name=prettify(plot_name), widget=pw)
                        self.plots_layout.addDock(dock, 'above')

                    self.add_plot_item(node.func.id, plot_name, data_item_name)

            if isinstance(node, ast.FunctionDef):
                if node.name.endswith("_gb_button"):
                    name = "_".join(node.name.split("_")[:-2])
                    button = QPushButton(prettify(name))
                    button.clicked.connect(getattr(instance, node.name))
                    self.buttons_layout.addWidget(button)


    def add_plot_item(self, fn_name, plot_name, data_item_name):
        plot_widget = self.plot_widgets[plot_name]
        color_generator = self.plot_color_generators[plot_name]
        plot_type = fn_name.split("_")[2]
        if plot_type == "xy":
            def plot_fn(x, y):
                if data_item_name in self.plot_data_items:
                    self.plot_data_items[data_item_name].setData(x, y)
                else:
                    self.plot_data_items[data_item_name] = plot_widget.plot(
                        x, y, name=prettify(data_item_name), pen=color_generator.next()
                    )
        elif plot_type == "y":
            def plot_fn(y):
                if data_item_name in self.plot_data_items:
                    self.plot_data_items[data_item_name].setData(y)
                else:
                    self.plot_data_items[data_item_name] = plot_widget.plot(
                        y, name=prettify(data_item_name), pen=color_generator.next()
                    )
        else:
            raise ValueError("Unknown plot type in {}: {}".format(fn_name, plot_type))


        __builtins__[fn_name] = plot_fn
Esempio n. 43
0
    def __init__(self, scanZ, recWidget=None, *args, **kwargs):

        super().__init__(*args, **kwargs)
        self.setMinimumSize(2, 350)

        self.mainRec = recWidget

        self.webcam = instruments.Webcam()

        self.z = scanZ
        self.z.zHostPosition = 'left'
        self.z.zobject.HostBackLashEnable = False

        self.setPoint = 0

        self.V = Q_(1, 'V')
        self.um = Q_(1, 'um')
        self.nm = Q_(1, 'nm')

        self.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Raised)

        self.scansPerS = 10
        self.ProcessData = ProcessData(self.webcam)

        # Focus lock widgets
        self.kpEdit = QtGui.QLineEdit('4')
        self.kpEdit.setFixedWidth(60)
        self.kpEdit.textChanged.connect(self.unlockFocus)
        self.kpLabel = QtGui.QLabel('kp')
        self.kiEdit = QtGui.QLineEdit('0.01')
        self.kiEdit.setFixedWidth(60)
        self.kiEdit.textChanged.connect(self.unlockFocus)
        self.kiLabel = QtGui.QLabel('ki')
        self.lockButton = QtGui.QPushButton('Lock')
        self.lockButton.setCheckable(True)
        self.lockButton.clicked.connect(self.toggleFocus)
        self.lockButton.setSizePolicy(QtGui.QSizePolicy.Preferred,
                                      QtGui.QSizePolicy.Expanding)
        moveLabel = QtGui.QLabel('Move [nm]')
        moveLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.moveEdit = QtGui.QLineEdit('0')
        self.moveEdit.setFixedWidth(60)
        self.moveEdit.returnPressed.connect(self.zMoveEdit)

        self.focusDataBox = QtGui.QCheckBox('Save focus data')
        self.focusPropertiesDisplay = QtGui.QLabel(' st_dev = 0  max_dev = 0')

        self.graph = FocusLockGraph(self, self.mainRec)

        self.focusTime = 1000 / self.scansPerS
        self.focusTimer = QtCore.QTimer()
        self.focusTimer.timeout.connect(self.update)
        self.focusTimer.start(self.focusTime)

        self.locked = False
        self.n = 1
        self.max_dev = 0

        self.focusCalib = FocusCalibration(self)
        self.focusCalibThread = QtCore.QThread(self)
        self.focusCalib.moveToThread(self.focusCalibThread)
        self.focusCalibButton = QtGui.QPushButton('Calibrate')
        self.focusCalibButton.clicked.connect(self.focusCalib.start)
        self.focusCalibThread.start()

        try:
            prevCal = np.around(np.loadtxt('calibration')[0]/10)
            text = '1 px --> {} nm'.format(prevCal)
            self.calibrationDisplay = QtGui.QLineEdit(text)
        except:
            self.calibrationDisplay = QtGui.QLineEdit('0 px --> 0 nm')

        self.calibrationDisplay.setReadOnly(False)

        self.webcamgraph = WebcamGraph(self)

        dockArea = DockArea()
        graphDock = Dock("Focus laser graph", size=(400, 200))
        graphDock.addWidget(self.graph)
        dockArea.addDock(graphDock)
        webcamDock = Dock("Focus laser view", size=(200, 200))
        webcamDock.addWidget(self.webcamgraph)
        dockArea.addDock(webcamDock, 'right', graphDock)

        # GUI layout
        grid = QtGui.QGridLayout()
        self.setLayout(grid)
        grid.addWidget(dockArea, 0, 0, 1, 6)
        grid.addWidget(self.focusCalibButton, 1, 0)
        grid.addWidget(self.calibrationDisplay, 2, 0)
        grid.addWidget(self.focusDataBox, 1, 1)
        grid.addWidget(moveLabel, 1, 2)
        grid.addWidget(self.moveEdit, 2, 2)
        grid.addWidget(self.kpLabel, 1, 3)
        grid.addWidget(self.kpEdit, 1, 4)
        grid.addWidget(self.kiLabel, 2, 3)
        grid.addWidget(self.kiEdit, 2, 4)
        grid.addWidget(self.lockButton, 1, 5, 2, 1)
        grid.setColumnMinimumWidth(5, 170)
Esempio n. 44
0
class DockWin(QtGui.QMainWindow):
    docklist = []
    def __init__(self):
        logging.debug('Creating main window.')
        QtGui.QMainWindow.__init__(self)
        self.setWindowTitle("colorgraphs dock")
        self.dockarea = DockArea()
        self.setCentralWidget(self.dockarea)
        self.resize(*_MAIN_WINDOW_SIZE)
        self.initUI()
        self.show()
        self.raise_()

    def initUI(self):
        palette = QtGui.QPalette()
        palette.setColor(QtGui.QPalette.Background,QtCore.Qt.white)
        
        self.setPalette(palette)
        # loadAction = QtGui.QAction(QtGui.QIcon(os.path.join(_IMG_PATH,'load.png')), '&Load', self)
        # loadAction.setShortcut('Ctr+O')
        # loadAction.setStatusTip('Load dataset')
        # loadAction.triggered.connect(load_action)

        # saveAction = QtGui.QAction(QtGui.QIcon(os.path.join(_IMG_PATH,'save.png')), '&Save', self)
        # saveAction.setShortcut('Ctr+S')
        # saveAction.setStatusTip('Save dataset')
        # saveAction.triggered.connect(save_action)

        # self.statusBar()

        # toolbar = self.addToolBar('Load')
        # toolbar.addAction(loadAction)
        # toolbar.addAction(saveAction)

    def create_dock(self, name='', loc='right', widget=None):
        if name == '':
            name = 'Graph%s' %len(self.docklist)
        if name in [dock.name() for dock in self.docklist]:
            dock = {dock.name(): dock for dock in self.docklist}[name]
            dock.close()
            self.docklist.remove(dock)
        dock = Dock(name)
        if widget:
            self.dockarea.addDock(dock, loc, widget)
        else:
            self.dockarea.addDock(dock, loc)
        DockWin.docklist.append(dock)
        return dock

    def add_widget(self, w, loc='right'):
        '''
        Add widget to the dock.
        w = widget, loc = location ('right', 'left', 'behind', etc.)
        '''
        dock = self.create_dock(w.name, loc)
        dock.addWidget(w)
        w.show()

    def add_widgets(self, wlist):
        '''
        Add a number of widgets to the dock.
        Spread evenly.
        '''
        for w in wlist:
            dock = self.create_dock(w.name, loc)
        for dock in docklist:
            dock.addWidget(w)

    def close_all(self):
        docklist = self.docklist
        for dock in docklist:
            dock.close()
            docklist.remove(dock)
            del(dock)

    def plot(self, *args, **kwargs):
        w = plotwidget(*args, **kwargs)
        self.add_widget(w)

    def _repr_png_(self):
        for d in self.dockarea.docks.values():
            display(d.widgets[0])

    def close(self):
        logging.debug('Close')
Esempio n. 45
0
class OnlineMonitorApplication(QtGui.QMainWindow):

    def __init__(self, socket_addr):
        super(OnlineMonitorApplication, self).__init__()
        self.setup_plots()
        self.add_widgets()
        self.fps = 0  # data frames per second
        self.hps = 0  # hits per second
        self.eps = 0  # events per second
        self.plot_delay = 0
        self.updateTime = ptime.time()
        self.total_hits = 0
        self.total_events = 0
        self.setup_data_worker_and_start(socket_addr)

    def closeEvent(self, event):
        super(OnlineMonitorApplication, self).closeEvent(event)
        # wait for thread
        self.worker.stop()
#         self.thread.wait()

    def setup_data_worker_and_start(self, socket_addr):
        self.thread = QtCore.QThread()  # no parent
        self.worker = DataWorker()  # no parent
        self.worker.meta_data.connect(self.on_meta_data)
        self.worker.interpreted_data.connect(self.on_interpreted_data)
        self.worker.run_start.connect(self.on_run_start)
        self.worker.config_data.connect(self.on_config_data)
        self.spin_box.valueChanged.connect(self.worker.on_set_integrate_readouts)
        self.worker.moveToThread(self.thread)
        self.worker.connect(socket_addr)
#         self.aboutToQuit.connect(self.worker.stop)  # QtGui.QApplication
        self.thread.started.connect(self.worker.process_data)
        self.worker.finished.connect(self.thread.quit)
#         self.worker.finished.connect(self.worker.deleteLater)
#         self.thread.finished.connect(self.thread.deleteLater)
        self.thread.start()

    def setup_plots(self):
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')

    def add_widgets(self):
        # Main window with dock area
        self.dock_area = DockArea()
        self.setCentralWidget(self.dock_area)

        # Docks
        dock_occcupancy = Dock("Occupancy", size=(400, 400))
        dock_run_config = Dock("Configuration", size=(400, 400))
        dock_tot = Dock("Time over threshold values (TOT)", size=(400, 400))
        dock_tdc = Dock("Time digital converter values (TDC)", size=(400, 400))
        dock_event_status = Dock("Event status", size=(400, 400))
        dock_trigger_status = Dock("Trigger status", size=(400, 400))
        dock_service_records = Dock("Service records", size=(400, 400))
        dock_hit_timing = Dock("Hit timing (rel. BCID)", size=(400, 400))
        dock_status = Dock("Status", size=(800, 40))
        self.dock_area.addDock(dock_run_config, 'left')
        self.dock_area.addDock(dock_occcupancy, 'above', dock_run_config)
        self.dock_area.addDock(dock_tdc, 'right', dock_occcupancy)
        self.dock_area.addDock(dock_tot, 'above', dock_tdc)
        self.dock_area.addDock(dock_service_records, 'bottom', dock_occcupancy)
        self.dock_area.addDock(dock_trigger_status, 'above', dock_service_records)
        self.dock_area.addDock(dock_event_status, 'above', dock_trigger_status)
        self.dock_area.addDock(dock_hit_timing, 'bottom', dock_tot)
        self.dock_area.addDock(dock_status, 'top')

        # Status widget
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz")
        self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz")
        self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz")
        self.timestamp_label = QtGui.QLabel("Data Timestamp\n")
        self.plot_delay_label = QtGui.QLabel("Plot Delay\n")
        self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n")
        self.spin_box = Qt.QSpinBox(value=1)
        layout.addWidget(self.timestamp_label, 0, 0, 0, 1)
        layout.addWidget(self.plot_delay_label, 0, 1, 0, 1)
        layout.addWidget(self.rate_label, 0, 2, 0, 1)
        layout.addWidget(self.hit_rate_label, 0, 3, 0, 1)
        layout.addWidget(self.event_rate_label, 0, 4, 0, 1)
        layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1)
        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        dock_status.addWidget(cw)

        # Config dock
        self.run_conf_list_widget = Qt.QListWidget()
        dock_run_config.addWidget(self.run_conf_list_widget)

        # Different plot docks

        occupancy_graphics = pg.GraphicsLayoutWidget()
        occupancy_graphics.show()
        view = occupancy_graphics.addViewBox()
        self.occupancy_img = pg.ImageItem(border='w')
        view.addItem(self.occupancy_img)
        view.setRange(QtCore.QRectF(0, 0, 80, 336))
        dock_occcupancy.addWidget(occupancy_graphics)

        tot_plot_widget = pg.PlotWidget(background="w")
        self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
        tot_plot_widget.showGrid(y=True)
        dock_tot.addWidget(tot_plot_widget)

        tdc_plot_widget = pg.PlotWidget(background="w")
        self.tdc_plot = tdc_plot_widget.plot(np.linspace(-0.5, 4095.5, 4097), np.zeros((4096)), stepMode=True)
        tdc_plot_widget.showGrid(y=True)
        tdc_plot_widget.setXRange(0, 800, update=True)
        dock_tdc.addWidget(tdc_plot_widget)

        event_status_widget = pg.PlotWidget()
        self.event_status_plot = event_status_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
        event_status_widget.showGrid(y=True)
        dock_event_status.addWidget(event_status_widget)

        trigger_status_widget = pg.PlotWidget()
        self.trigger_status_plot = trigger_status_widget.plot(np.linspace(-0.5, 7.5, 9), np.zeros((8)), stepMode=True)
        trigger_status_widget.showGrid(y=True)
        dock_trigger_status.addWidget(trigger_status_widget)

        service_record_widget = pg.PlotWidget()
        self.service_record_plot = service_record_widget.plot(np.linspace(-0.5, 31.5, 33), np.zeros((32)), stepMode=True)
        service_record_widget.showGrid(y=True)
        dock_service_records.addWidget(service_record_widget)

        hit_timing_widget = pg.PlotWidget()
        self.hit_timing_plot = hit_timing_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
        hit_timing_widget.showGrid(y=True)
        dock_hit_timing.addWidget(hit_timing_widget)

    @pyqtSlot()
    def on_run_start(self):
        # clear config data widget
        self.run_conf_list_widget.clear()
        self.run_conf_list_widget.addItem(Qt.QListWidgetItem("No run configuration"))

    @pyqtSlot(dict)
    def on_config_data(self, config_data):
        self.setup_config_text(**config_data)

    def setup_config_text(self, conf):
        for key, value in conf.iteritems():
            item = Qt.QListWidgetItem("%s: %s" % (key, value))
            self.run_conf_list_widget.addItem(item)

    @pyqtSlot(dict)
    def on_interpreted_data(self, interpreted_data):
        self.update_plots(**interpreted_data)

    def update_plots(self, occupancy, tot_hist, tdc_counters, error_counters, service_records_counters, trigger_error_counters, rel_bcid_hist):
        self.occupancy_img.setImage(occupancy[:, ::-1, 0], autoDownsample=True)
        self.tot_plot.setData(x=np.linspace(-0.5, 15.5, 17), y=tot_hist, fillLevel=0, brush=(0, 0, 255, 150))
        self.tdc_plot.setData(x=np.linspace(-0.5, 4096.5, 4097), y=tdc_counters, fillLevel=0, brush=(0, 0, 255, 150))
        self.event_status_plot.setData(x=np.linspace(-0.5, 15.5, 17), y=error_counters, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150))
        self.service_record_plot.setData(x=np.linspace(-0.5, 31.5, 33), y=service_records_counters, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150))
        self.trigger_status_plot.setData(x=np.linspace(-0.5, 7.5, 9), y=trigger_error_counters, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150))
        self.hit_timing_plot.setData(x=np.linspace(-0.5, 15.5, 17), y=rel_bcid_hist, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150))

    @pyqtSlot(dict)
    def on_meta_data(self, meta_data):
        self.update_monitor(**meta_data)

    def update_monitor(self, timestamp_start, timestamp_stop, readout_error, scan_parameters, n_hits, n_events):
        self.timestamp_label.setText("Data Timestamp\n%s" % time.asctime(time.localtime(timestamp_stop)))
        self.scan_parameter_label.setText("Scan Parameters\n%s" % ', '.join('%s: %s' % (str(key), str(val)) for key, val in scan_parameters.iteritems()))
        now = ptime.time()
        recent_total_hits = n_hits
        recent_total_events = n_events
        self.plot_delay = self.plot_delay * 0.9 + (now - timestamp_stop) * 0.1
        self.plot_delay_label.setText("Plot Delay\n%s" % ((time.strftime('%H:%M:%S', time.gmtime(self.plot_delay))) if self.plot_delay > 5 else "%1.2f ms" % (self.plot_delay * 1.e3)))
        recent_fps = 1.0 / (now - self.updateTime)  # calculate FPS
        recent_hps = (recent_total_hits - self.total_hits) / (now - self.updateTime)
        recent_eps = (recent_total_events - self.total_events) / (now - self.updateTime)
        self.updateTime = now
        self.total_hits = recent_total_hits
        self.total_events = recent_total_events
        self.fps = self.fps * 0.7 + recent_fps * 0.3
        self.hps = self.hps + (recent_hps - self.hps) * 0.3 / self.fps
        self.eps = self.eps + (recent_eps - self.eps) * 0.3 / self.fps
        self.rate_label.setText("Readout Rate\n%d Hz" % self.fps)
        if self.spin_box.value() == 0:  # show number of hits, all hits are integrated
            self.hit_rate_label.setText("Total Hits\n%d" % int(recent_total_hits))
        else:
            self.hit_rate_label.setText("Hit Rate\n%d Hz" % int(self.hps))
        if self.spin_box.value() == 0:  # show number of events
            self.event_rate_label.setText("Total Events\n%d" % int(recent_total_events))
        else:
            self.event_rate_label.setText("Event Rate\n%d Hz" % int(self.eps))
Esempio n. 46
0
class OnlineMonitorApplication(QtGui.QMainWindow):

    def __init__(self, socket_addr):
        super(OnlineMonitorApplication, self).__init__()
        self.setup_plots()
        self.add_widgets()
        self.fps = 0
        self.eps = 0  # events per second
        self.total_events = 0
        self.total_readouts = 0
        self.last_total_events = 0
        self.updateTime = ptime.time()
        self.setup_data_worker_and_start(socket_addr)
        self.cpu_load = max(psutil.cpu_percent(percpu=True))

    def closeEvent(self, event):
        super(OnlineMonitorApplication, self).closeEvent(event)
        # wait for thread
        self.worker.stop()
        self.thread.wait(1) # fixes message: QThread: Destroyed while thread is still running

    def setup_data_worker_and_start(self, socket_addr):
        self.thread = QtCore.QThread()  # no parent
        self.worker = DataWorker()  # no parent
        self.worker.interpreted_data.connect(self.on_interpreted_data)
        self.worker.run_start.connect(self.on_run_start)
        self.worker.config_data.connect(self.on_config_data)
        self.spin_box.valueChanged.connect(self.worker.on_set_integrate_readouts)
        self.worker.moveToThread(self.thread)
        self.worker.connect(socket_addr)
        self.thread.started.connect(self.worker.process_data)
        self.worker.finished.connect(self.thread.quit)
        self.thread.start()

    def setup_plots(self):
        pg.setConfigOption('background', 'w')
        pg.setConfigOption('foreground', 'k')

    def add_widgets(self):
        # Main window with dock area
        self.dock_area = DockArea()
        self.setCentralWidget(self.dock_area)

        # Docks
        dock_waveform = Dock("Waveform", size=(600, 400))
        dock_histogram = Dock("Histogram", size=(600, 400))
        dock_status = Dock("Status", size=(1200, 40))
        self.dock_area.addDock(dock_waveform, 'left')
        self.dock_area.addDock(dock_histogram, 'right', dock_waveform)
        self.dock_area.addDock(dock_status, 'top')

        # Status widget
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        layout.setColumnStretch(2, 1)
        cw.setLayout(layout)
        self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz")
        self.total_events_label = QtGui.QLabel("Total Events\n0")
        self.spin_box = Qt.QSpinBox(value=20, maximum=1000)
        self.reset_button = Qt.QPushButton('Reset', self)
        self.reset_button.clicked.connect(self.reset_plots)
        layout.addWidget(self.event_rate_label, 0, 1, 1, 1)
        layout.addWidget(self.total_events_label, 1, 1, 1, 1)
        layout.addWidget(self.spin_box, 0, 3, 1, 1)
        layout.addWidget(self.reset_button, 1, 3, 1, 1)
        
        dock_status.addWidget(cw)

        # Different plot docks
        waveform_widget = pg.PlotWidget(background="w")
        self.waveform_plot = waveform_widget.plot(range(0, 200), np.zeros(shape=(200)))
        self.thr_line = pg.InfiniteLine(pos=1000, angle=0, pen={'color':0.0, 'style':QtCore.Qt.DashLine})
        waveform_widget.addItem(self.thr_line)
        dock_waveform.addWidget(waveform_widget)

        histogram_widget = pg.PlotWidget(background="w")
        self.histogram_plot = histogram_widget.plot(range(0, 2**14 + 1), np.zeros(shape=(2**14)), stepMode=True)
        histogram_widget.showGrid(y=True)
        self.thr_line_hist = pg.InfiniteLine(pos=1000, angle=90, pen={'color':0.0, 'style':QtCore.Qt.DashLine})
        histogram_widget.addItem(self.thr_line_hist)
        dock_histogram.addWidget(histogram_widget)
 

    @pyqtSlot()
    def on_run_start(self):
        pass

    @pyqtSlot(dict)
    def on_config_data(self, config_data):
        pass

    def setup_config_text(self, conf):
        pass

    @pyqtSlot(dict)
    def on_interpreted_data(self, interpreted_data):
        self.update_plots(**interpreted_data)

    def update_plots(self, waveform, bin_edges, histogram, threshold, n_actual_events):
        self.total_events += n_actual_events
        self.total_readouts += 1
        actual_cpu_load = max(psutil.cpu_percent(percpu=True))
        self.cpu_load = 0.95 * self.cpu_load + 0.05 * actual_cpu_load
        if self.cpu_load < 55 and self.spin_box.value() > 0 and self.total_readouts % self.spin_box.value() == 0:  # only refresh plot every spin_box.value() readout 
            self.waveform_plot.setData(waveform, fillLevel=0, brush=(0, 0, 255, 150))
            self.histogram_plot.setData(x=bin_edges, y=histogram, fillLevel=0, brush=(0, 0, 255, 150))
            self.thr_line.setValue(threshold)
            self.thr_line_hist.setValue(threshold)
            self.update_monitor()

    def update_monitor(self):
        now = ptime.time()
        recent_eps = (self.total_events - self.last_total_events) / (now - self.updateTime)
        self.last_total_events = self.total_events
        self.updateTime = now
        self.eps = self.eps * 0.98 + recent_eps * 0.02
        if self.spin_box.value() == 0:  # show number of events
            self.event_rate_label.setText("Total Events\n%d" % int(self.total_events))
        else:
            self.event_rate_label.setText("Event Rate\n%d Hz" % int(self.eps))
            
        self.total_events_label.setText("Total Events\n%d" % int(self.total_events))
            
            
    def reset_plots(self):
        self.worker.reset_hist()
        
        self.total_events  = 0
        self.total_readouts = 0
        self.last_total_events = 0
        self.updateTime = ptime.time()
        self.fps = 0
        self.eps = 0  # events per second
        
        self.waveform_plot.setData(x=range(0, 200), y=np.zeros(200), fillLevel=0, brush=(0, 0, 255, 150))
        self.histogram_plot.setData(x=range(0, 2**14+1), y=np.zeros(2**14), fillLevel=0, brush=(0, 0, 255, 150))
        self.thr_line.setValue(1000)
        self.thr_line_hist.setValue(1000)
        self.update_monitor()
    def setup_widgets(self, parent, name):
        dock_area = DockArea()
        parent.addTab(dock_area, name)

        # Docks
        dock_occcupancy = Dock("Occupancy", size=(400, 400))
        dock_run_config = Dock("Run configuration", size=(400, 400))
        dock_global_config = Dock("Global configuration", size=(400, 400))
        dock_tot = Dock("Time over threshold values (TOT)", size=(400, 400))
        dock_tdc = Dock("Time digital converter values (TDC)", size=(400, 400))
        dock_event_status = Dock("Event status", size=(400, 400))
        dock_trigger_status = Dock("Trigger status", size=(400, 400))
        dock_service_records = Dock("Service records", size=(400, 400))
        dock_hit_timing = Dock("Hit timing (rel. BCID)", size=(400, 400))
        dock_status = Dock("Status", size=(800, 40))
        dock_area.addDock(dock_global_config, 'left')
        dock_area.addDock(dock_run_config, 'above', dock_global_config)
        dock_area.addDock(dock_occcupancy, 'above', dock_run_config)
        dock_area.addDock(dock_tdc, 'right', dock_occcupancy)
        dock_area.addDock(dock_tot, 'above', dock_tdc)
        dock_area.addDock(dock_service_records, 'bottom', dock_occcupancy)
        dock_area.addDock(dock_trigger_status, 'above', dock_service_records)
        dock_area.addDock(dock_event_status, 'above', dock_trigger_status)
        dock_area.addDock(dock_hit_timing, 'bottom', dock_tot)
        dock_area.addDock(dock_status, 'top')

        # Status dock on top
        cw = QtGui.QWidget()
        cw.setStyleSheet("QWidget {background-color:white}")
        layout = QtGui.QGridLayout()
        cw.setLayout(layout)
        self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz")
        self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz")
        self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz")
        self.timestamp_label = QtGui.QLabel("Data Timestamp\n")
        self.plot_delay_label = QtGui.QLabel("Plot Delay\n")
        self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n")
        self.spin_box = Qt.QSpinBox(value=0)
        self.spin_box.setMaximum(1000000)
        self.spin_box.setSuffix(" Readouts")
        self.reset_button = QtGui.QPushButton('Reset')
        layout.addWidget(self.timestamp_label, 0, 0, 0, 1)
        layout.addWidget(self.plot_delay_label, 0, 1, 0, 1)
        layout.addWidget(self.rate_label, 0, 2, 0, 1)
        layout.addWidget(self.hit_rate_label, 0, 3, 0, 1)
        layout.addWidget(self.event_rate_label, 0, 4, 0, 1)
        layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1)
        layout.addWidget(self.spin_box, 0, 6, 0, 1)
        layout.addWidget(self.reset_button, 0, 7, 0, 1)
        dock_status.addWidget(cw)

        # Connect widgets
        self.reset_button.clicked.connect(lambda: self.send_command('RESET'))
        self.spin_box.valueChanged.connect(lambda value: self.send_command(str(value)))

        # Run config dock
        self.run_conf_list_widget = Qt.QListWidget()
        dock_run_config.addWidget(self.run_conf_list_widget)

        # Global config dock
        self.global_conf_list_widget = Qt.QListWidget()
        dock_global_config.addWidget(self.global_conf_list_widget)

        # Different plot docks
        occupancy_graphics = pg.GraphicsLayoutWidget()
        occupancy_graphics.show()
        view = occupancy_graphics.addViewBox()
        self.occupancy_img = pg.ImageItem(border='w')
        view.addItem(self.occupancy_img)
        view.setRange(QtCore.QRectF(0, 0, 80, 336))
        dock_occcupancy.addWidget(occupancy_graphics)

        tot_plot_widget = pg.PlotWidget(background="w")
        self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
        tot_plot_widget.showGrid(y=True)
        dock_tot.addWidget(tot_plot_widget)

        tdc_plot_widget = pg.PlotWidget(background="w")
        self.tdc_plot = tdc_plot_widget.plot(np.linspace(-0.5, 4095.5, 4097), np.zeros((4096)), stepMode=True)
        tdc_plot_widget.showGrid(y=True)
        tdc_plot_widget.setXRange(0, 800, update=True)
        dock_tdc.addWidget(tdc_plot_widget)

        event_status_widget = pg.PlotWidget()
        self.event_status_plot = event_status_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
        event_status_widget.showGrid(y=True)
        dock_event_status.addWidget(event_status_widget)

        trigger_status_widget = pg.PlotWidget()
        self.trigger_status_plot = trigger_status_widget.plot(np.linspace(-0.5, 7.5, 9), np.zeros((8)), stepMode=True)
        trigger_status_widget.showGrid(y=True)
        dock_trigger_status.addWidget(trigger_status_widget)

        service_record_widget = pg.PlotWidget()
        self.service_record_plot = service_record_widget.plot(np.linspace(-0.5, 31.5, 33), np.zeros((32)), stepMode=True)
        service_record_widget.showGrid(y=True)
        dock_service_records.addWidget(service_record_widget)

        hit_timing_widget = pg.PlotWidget()
        self.hit_timing_plot = hit_timing_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True)
        hit_timing_widget.showGrid(y=True)
        dock_hit_timing.addWidget(hit_timing_widget)

        self.plot_delay = 0
Esempio n. 48
0
class InstrumentLoggingUi(WidgetContainerBase, WidgetContainerForm):
    plotConfigurationChanged = QtCore.pyqtSignal(object)

    def __init__(self, project, config):
        super(InstrumentLoggingUi, self).__init__()
        self.config = config
        self.project = project
        self.dockWidgetList = list()
        self.plotDict = dict()
        self.instrument = ""

    def __enter__(self):
        return self

    def __exit__(self, excepttype, value, traceback):
        return False

    def setupUi(self, parent):
        super(InstrumentLoggingUi, self).setupUi(parent)

        logger = logging.getLogger()

        self.parent = parent
        self.tabList = list()
        self.tabDict = dict()

        self.setupPlots()
        # Traceui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, "Main",
                                       self.plotDict)
        self.traceui.setupUi(self.traceui)
        self.setupAsDockWidget(self.traceui, "Traces",
                               QtCore.Qt.LeftDockWidgetArea)

        # new fit widget
        self.fitWidget = FitUi(self.traceui, self.config, "Main")
        self.fitWidget.setupUi(self.fitWidget)
        self.fitWidgetDock = self.setupAsDockWidget(
            self.fitWidget, "Fit", QtCore.Qt.LeftDockWidgetArea)

        self.instrumentLoggingHandler = InstrumentLoggingHandler(
            self.traceui, self.plotDict, self.config, 'externalInput')

        self.ExternalParametersSelectionUi = InstrumentLoggingSelection(
            self.config,
            classdict=LoggingInstruments,
            newDataSlot=self.instrumentLoggingHandler.addData,
            plotNames=list(self.plotDict.keys()),
            instrumentLoggingHandler=self.instrumentLoggingHandler)
        self.ExternalParametersSelectionUi.setupUi(
            self.ExternalParametersSelectionUi)
        self.ExternalParameterSelectionDock = QtWidgets.QDockWidget(
            "Params Selection")
        self.ExternalParameterSelectionDock.setObjectName(
            "_ExternalParameterSelectionDock")
        self.ExternalParameterSelectionDock.setWidget(
            self.ExternalParametersSelectionUi)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.ExternalParameterSelectionDock)
        self.instrumentLoggingHandler.paramTreeChanged.connect(
            self.ExternalParametersSelectionUi.refreshParamTree)

        self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config)
        self.instrumentLoggingDisplay.setupUi(
            self.ExternalParametersSelectionUi.enabledParametersObjects,
            self.instrumentLoggingDisplay)
        self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget(
            "Params Reading")
        self.instrumentLoggingDisplayDock.setObjectName(
            "_ExternalParameterDisplayDock")
        self.instrumentLoggingDisplayDock.setWidget(
            self.instrumentLoggingDisplay)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea,
                           self.instrumentLoggingDisplayDock)
        self.ExternalParametersSelectionUi.selectionChanged.connect(
            self.instrumentLoggingDisplay.setupParameters)
        self.instrumentLoggingHandler.newData.connect(
            self.instrumentLoggingDisplay.update)

        self.instrumentLoggingQueryUi = InstrumentLoggerQueryUi(
            self.config, self.traceui, self.plotDict)
        self.instrumentLoggingQueryUi.setupUi(self.instrumentLoggingQueryUi)
        self.instrumentLoggingQueryUiDock = self.setupAsDockWidget(
            self.instrumentLoggingQueryUi, "Query",
            QtCore.Qt.LeftDockWidgetArea)

        self.addPlot = QtWidgets.QAction(
            QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)

        self.removePlot = QtWidgets.QAction(
            QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot",
            self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtWidgets.QAction(
            QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot",
            self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        self.setWindowTitle("Instrument Logger ({0})".format(self.project))
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        try:
            if 'pyqtgraph-dockareastate' in self.config:
                self.area.restoreState(self.config['pyqtgraph-dockareastate'])
        except Exception as e:
            logger.warning(
                "Cannot restore dock state in experiment {0}. Exception occurred: "
                .format(self.experimentName) + str(e))
        QtCore.QTimer.singleShot(60000, self.onCommitConfig)

    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = dict()
        # initialize all the plot windows we want
        plotNames = self.config.get('PlotNames', ['Scan'])
        if len(plotNames) < 1:
            plotNames.append('Scan')
        for name in plotNames:
            dock = Dock(name)
            widget = DateTimePlotWidget(self, name=name)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {
                "dock": dock,
                "widget": widget,
                "view": view
            }

    def setupAsDockWidget(self,
                          widget,
                          name,
                          area=QtCore.Qt.RightDockWidgetArea,
                          stackAbove=None,
                          stackBelow=None):
        dock = QtWidgets.QDockWidget(name)
        dock.setObjectName(name)
        dock.setWidget(widget)
        self.addDockWidget(area, dock)
        self.dockWidgetList.append(dock)
        if stackAbove is not None:
            self.tabifyDockWidget(stackAbove, dock)
        elif stackBelow is not None:
            self.tabifyDockWidget(dock, stackBelow)
        return dock

    def onAddPlot(self):
        name, ok = QtWidgets.QInputDialog.getText(
            self, 'Plot Name', 'Please enter a plot name: ')
        if ok:
            name = str(name)
            dock = Dock(name)
            widget = DateTimePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {
                "dock": dock,
                "widget": widget,
                "view": view
            }
            self.plotConfigurationChanged.emit(self.plotDict)

    def onRemovePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(
                self,
                "Select Plot",
                "Please select which plot to remove: ",
                list(self.plotDict.keys()),
                editable=False)
            if ok:
                name = str(name)
                self.plotDict[name]["dock"].close()
                del self.plotDict[name]
                self.plotConfigurationChanged.emit(self.plotDict)
        else:
            logger.info("There are no plots which can be removed")

    def onRenamePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(
                self,
                "Select Plot",
                "Please select which plot to rename: ",
                list(self.plotDict.keys()),
                editable=False)
            if ok:
                newName, newOk = QtWidgets.QInputDialog.getText(
                    self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk:
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(str(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    del self.plotDict[name]
                    self.plotConfigurationChanged.emit(self.plotDict)
        else:
            logger.info("There are no plots which can be renamed")

    def onSave(self):
        logger = logging.getLogger(__name__)
        logger.info("Saving config")
        filename, _ = DataDirectory.DataDirectory().sequencefile(
            "InstrumentLogger-configuration.db")
        self.saveConfig()
        self.config.saveConfig(filename)

    def onClose(self):
        self.parent.close()

    def closeEvent(self, e):
        logger = logging.getLogger(__name__)
        logger.info("Close Event")
        logger = logging.getLogger("")
        logger.debug("Saving Configuration")
        self.saveConfig()

    def saveConfig(self):
        self.config['MainWindow.State'] = self.parent.saveState()
        for tab in self.tabList:
            tab.saveConfig()
        self.config['MainWindow.pos'] = self.pos()
        self.config['MainWindow.size'] = self.size()
        self.config['PlotNames'] = list(self.plotDict.keys())
        self.config['pyqtgraph-dockareastate'] = self.area.saveState()
        self.ExternalParametersSelectionUi.saveConfig()
        self.instrumentLoggingHandler.saveConfig()
        self.instrumentLoggingQueryUi.saveConfig()
        self.instrumentLoggingDisplay.saveConfig()

    def onCommitConfig(self):
        self.saveConfig()
        QtCore.QTimer.singleShot(60000, self.onCommitConfig)
Esempio n. 49
0
class PicoampMeterUi(WidgetContainerBase, WidgetContainerForm):
    levelNameList = ["debug", "info", "warning", "error", "critical"]
    levelValueList = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]
    plotConfigurationChanged = QtCore.pyqtSignal( object )
    def __init__(self, config):
        self.config = config
        super(PicoampMeterUi, self).__init__()
        self.loggingLevel = config.get('Settings.loggingLevel', logging.INFO)
        self.consoleMaximumLines = config.get('Settings.consoleMaximumLines', 0)
        self.dockWidgetList = list()
        if self.loggingLevel not in self.levelValueList: self.loggingLevel = logging.INFO
        self.plotDict = dict()
        self.meter = None
        self.instrument = ""
        
    def __enter__(self):
        self.meter = PicoampMeter()
        self.meter_2 = PicoampMeter()
        self.meter_3 = PicoampMeter()
        return self
    
    def __exit__(self, excepttype, value, traceback):
        self.meter.close()
        self.meter_2.close()
        self.meter_3.close()
        return False
    
    def setupUi(self, parent):
        super(PicoampMeterUi, self).setupUi(parent)
        self.dockWidgetConsole.hide()
        self.loggerUi = LoggerLevelsUi(self.config)
        self.loggerUi.setupUi(self.loggerUi)
        self.setupAsDockWidget(self.loggerUi, "Logging", QtCore.Qt.NoDockWidgetArea)
                
        logger = logging.getLogger()        
        self.toolBar.addWidget(ExceptionLogButton())
            
        self.parent = parent
        self.tabList = list()
        self.tabDict = dict()
               
        self.setupPlots()       
        # Traceui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, "Main", self.plotDict)
        self.traceui.setupUi(self.traceui)
        self.setupAsDockWidget(self.traceui, "Traces", QtCore.Qt.LeftDockWidgetArea)

        # PicoampMeter Control
        self.meterControl = PicoampMeterControl(self.config, self.traceui, self.plotDict, self.parent, self.meter, self.meter_2, self.meter_3)
        self.meterControl.setupUi(self.meterControl)
        self.setupAsDockWidget(self.meterControl, "Control", QtCore.Qt.RightDockWidgetArea)
    
        self.actionSave.triggered.connect(self.onSave)
        #self.actionSettings.triggered.connect(self.onSettings)
        self.actionExit.triggered.connect(self.onClose)
        self.actionProject.triggered.connect( self.onProjectSelection)
        
        self.actionStart.triggered.connect(self.meterControl.onScan)
        self.actionStop.triggered.connect(self.meterControl.onStop)

        self.addPlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)
        
        self.removePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        self.setWindowTitle("Digital Lock ({0})".format(project) )
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        self.initMenu()
        try:
            if 'pyqtgraph-dockareastate' in self.config:
                self.area.restoreState(self.config['pyqtgraph-dockareastate'])
        except Exception as e:
            logger.error("Cannot restore dock state in experiment {0}. Exception occurred: ".format(self.experimentName) + str(e))
       
        
    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = dict()
        # initialize all the plot windows we want
        plotNames = self.config.get( 'PlotNames', ['Scan'] )
        if len(plotNames)<1:
            plotNames.append('Scan')
        for name in plotNames:
            dock = Dock(name)
            widget = CoordinatePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
        
    def setupAsDockWidget(self, widget, name, area=QtCore.Qt.RightDockWidgetArea, stackAbove=None, stackBelow=None ):
        dock = QtWidgets.QDockWidget(name)
        dock.setObjectName(name)
        dock.setWidget( widget )
        self.addDockWidget(area, dock )
        self.dockWidgetList.append( dock )
        if stackAbove is not None:
            self.tabifyDockWidget( stackAbove, dock )
        elif stackBelow is not None:
            self.tabifyDockWidget( dock, stackBelow )
        return dock           

    def onAddPlot(self):
        name, ok = QtWidgets.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ')
        if ok:
            name = str(name)
            dock = Dock(name)
            widget = CoordinatePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
            self.plotConfigurationChanged.emit( self.plotDict )
            
    def onRemovePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", list(self.plotDict.keys()), editable=False)
            if ok:
                name = str(name)
                self.plotDict[name]["dock"].close()
                del self.plotDict[name]
                self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be removed")
                
    def onRenamePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", list(self.plotDict.keys()), editable=False)
            if ok:
                newName, newOk = QtWidgets.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk:
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(str(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    del self.plotDict[name]
                    self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be renamed")

    def onProjectSelection(self):
        ProjectSelectionUi.GetProjectSelection()

    def onSettings(self):
        self.settingsDialog.show()
        
    def onSave(self):
        logger = logging.getLogger(__name__)
        logger.info( "Saving config" )
        filename, _ = DataDirectory.DataDirectory().sequencefile("digitalLock-configuration.db")
        self.saveConfig()
        self.config.saveConfig(filename)
    
    def onMessageWrite(self,message,level=logging.DEBUG):
        if level>= self.loggingLevel:
            cursor = self.textEditConsole.textCursor()
            cursor.movePosition(QtGui.QTextCursor.End)
            if level < logging.ERROR:
                self.textEditConsole.setTextColor(QtCore.Qt.black)
            else:
                self.textEditConsole.setTextColor(QtCore.Qt.red)
            cursor.insertText(message)
            self.textEditConsole.setTextCursor(cursor)
            self.textEditConsole.ensureCursorVisible()

    def onClose(self):
        self.parent.close()
        
    def closeEvent(self, e):
        logger = logging.getLogger("")
        logger.debug( "Saving Configuration" )
        self.saveConfig()

    def initMenu(self):
        self.menuView.clear()
        for dock in self.dockWidgetList:
            self.menuView.addAction(dock.toggleViewAction())

    def saveConfig(self):
        self.config['MainWindow.State'] = self.parent.saveState()
        for tab in self.tabList:
            tab.saveConfig()
        self.config['MainWindow.pos'] = self.pos()
        self.config['MainWindow.size'] = self.size()
        self.config['Settings.loggingLevel'] = self.loggingLevel
        self.config['Settings.consoleMaximumLines'] = self.consoleMaximumLines
        self.config['PlotNames'] = list(self.plotDict.keys())
        self.config['pyqtgraph-dockareastate'] = self.area.saveState()
        self.loggerUi.saveConfig()
        self.meterControl.saveConfig()
Esempio n. 50
0
class DedicatedCounters(DedicatedCountersForm, DedicatedCountersBase ):
    dataAvailable = QtCore.pyqtSignal( object )
    OpStates = enum.enum('idle', 'running', 'paused')

    def __init__(self, config, dbConnection, pulserHardware, globalVariablesUi, shutterUi, externalInstrumentObservable, parent=None):
        DedicatedCountersForm.__init__(self)
        DedicatedCountersBase.__init__(self, parent)
        self.curvesDict = {}
        self.dataSlotConnected = False
        self.config = config
        self.configName = 'DedicatedCounter'
        self.pulserHardware = pulserHardware
        self.state = self.OpStates.idle
        self.xData = [numpy.array([])]*20
        self.yData = [numpy.array([])]*20
        self.refValue = [None] * 20
        self.integrationTime = 0
        self.integrationTimeLookup = dict()
        self.tick = 0
        self.analogCalbrations = None
        self.globalVariablesUi = globalVariablesUi
        self.shutterUi = shutterUi
        self.externalInstrumentObservable = externalInstrumentObservable
        self.dbConnection = dbConnection
        self.plotDict = dict()

        self.area = None
#        [
#            AnalogInputCalibration.PowerDetectorCalibration(),
#            AnalogInputCalibration.PowerDetectorCalibrationTwo(),
#            AnalogInputCalibration.AnalogInputCalibration(),
#            AnalogInputCalibration.AnalogInputCalibration() ]

    @property
    def settings(self):
        return self.settingsUi.settings

    def setupUi(self, parent):
        DedicatedCountersForm.setupUi(self, parent)
        self.setupPlots()
        self.actionSave.triggered.connect( self.onSave )
        self.actionClear.triggered.connect( self.onClear )
        self.actionStart.triggered.connect( self.onStart )
        self.actionStop.triggered.connect( self.onStop )
        self.settingsUi = DedicatedCountersSettings.DedicatedCountersSettings(self.config,self.plotDict)
        self.settingsUi.setupUi(self.settingsUi)
        self.settingsDock.setWidget( self.settingsUi )
        self.settingsUi.valueChanged.connect( self.onSettingsChanged )

        #Plot buttons
        self.addPlot = QtGui.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)

        self.removePlot = QtGui.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtGui.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        # Input Calibrations        
        self.calibrationUi = InputCalibrationUi.InputCalibrationUi(self.config, 4)
        self.calibrationUi.setupUi(self.calibrationUi)
        self.calibrationDock = QtWidgets.QDockWidget("Input Calibration")
        self.calibrationDock.setObjectName("Input Calibration")
        self.calibrationDock.setWidget( self.calibrationUi )
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.calibrationDock)
        self.analogCalbrations = self.calibrationUi.calibrations

        # Display Channels 0-3
        self.displayUi = DedicatedDisplay.DedicatedDisplay(self.config, "Channel 0-3")
        self.displayUi.setupUi(self.displayUi)
        self.displayDock = QtWidgets.QDockWidget("Channel 0-3")
        self.displayDock.setObjectName("Channel 0-3")
        self.displayDock.setWidget( self.displayUi )
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.displayDock)

        # Display Channel 4-7
        self.displayUi2 = DedicatedDisplay.DedicatedDisplay(self.config, "Channel 4-7")
        self.displayUi2.setupUi(self.displayUi2)
        self.displayDock2 = QtWidgets.QDockWidget("Channel 4-7")
        self.displayDock2.setObjectName("Channel 4-7")
        self.displayDock2.setWidget(self.displayUi2)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.displayDock2)

        # Display ADC 0-3
        self.displayUiADC = DedicatedDisplay.DedicatedDisplay(self.config, "Analog Channels")
        self.displayUiADC.setupUi(self.displayUiADC)
        self.displayDockADC = QtWidgets.QDockWidget("Analog Channels")
        self.displayDockADC.setObjectName("Analog Channels")
        self.displayDockADC.setWidget(self.displayUiADC)
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.displayDockADC)

        # Arrange the dock widgets
        self.tabifyDockWidget( self.displayDockADC, self.displayDock2)
        self.tabifyDockWidget( self.displayDock2, self.displayDock )
        self.tabifyDockWidget( self.calibrationDock, self.settingsDock )
        self.calibrationDock.hide()        

        # AutoLoad
        self.autoLoad = AutoLoad.AutoLoad(self.config, self.dbConnection, self.pulserHardware, self.dataAvailable, self.globalVariablesUi,self.shutterUi, self.externalInstrumentObservable)
        self.autoLoad.setupUi(self.autoLoad)
        self.autoLoadDock = QtWidgets.QDockWidget("Auto Loader")
        self.autoLoadDock.setObjectName("Auto Loader")
        self.autoLoadDock.setWidget( self.autoLoad )
        self.autoLoad.valueChanged.connect( self.onSettingsChanged )
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.autoLoadDock)

        # external Status display
        self.statusDisplay = StatusDisplay(self.config, self.pulserHardware.pulserConfiguration())
        self.statusDisplay.setupUi(self.statusDisplay)
        self.statusDock = QtWidgets.QDockWidget("Status display")
        self.statusDock.setObjectName("Status display")
        self.statusDock.setWidget( self.statusDisplay )
        self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.statusDock)

        if self.configName+'.MainWindow.State' in self.config:
            QtGui.QMainWindow.restoreState(self,self.config[self.configName+'.MainWindow.State'])
        self.onSettingsChanged()

    def onSettingsChanged(self):
        self.integrationTimeLookup[ self.pulserHardware.getIntegrationTimeBinary(self.settings.integrationTime) & 0xffffff] = self.settings.integrationTime
        self.pulserHardware.integrationTime = self.settings.integrationTime
        self.autoLoadCounterMask = self.autoLoad.settings.counterMask
        self.plotCounterMask = self.settingsUi.settings.counterMask
        self.counterDisplayData = self.autoLoad.settings.counterDisplayData
        self.plotDisplayData = self.settingsUi.settings.plotDisplayData
        self.countDict = self.settingsUi.settings.counterDict
        self.adcDict = self.settingsUi.settings.adcDict
        if self.state == self.OpStates.running:
            mask = 0
            mask += self.autoLoadCounterMask | self.plotCounterMask
            self.pulserHardware.counterMask = mask
            self.pulserHardware.adcMask = self.settings.adcMask
            for windowName, dataSourceNames in self.plotDisplayData.items():
                if windowName in self.plotDict:
                    self.curvesDict.setdefault(windowName, dict())
                    counterIndexList = [self.countDict[n] for n in dataSourceNames if n in self.countDict]
                    adcIndexList = [self.adcDict[n] for n in dataSourceNames if n in self.adcDict]
                    mycurves = self.curvesDict[windowName]
                    for cIdx in counterIndexList:
                        mycurves.setdefault(cIdx, self.plotDict[windowName]['view'].plot(pen=penList[cIdx + 1][0]))
                    for aIdx in adcIndexList:
                        mycurves.setdefault(aIdx + 16, self.plotDict[windowName]['view'].plot(pen=penList[cIdx + 1][0]))
                    for eIdx in set(mycurves) - set(counterIndexList) - set(i + 16 for i in adcIndexList):
                        curve = mycurves.pop(eIdx)
                        self.plotDict[windowName]['view'].removeItem(curve)
                        self.xData[eIdx] = numpy.array([])
                        self.yData[eIdx] = numpy.array([])

    def saveConfig(self):
        self.config[self.configName+'.pos'] = self.pos()
        self.config[self.configName+'.size'] = self.size()
        self.config[self.configName+'.Settings'] = self.settings
        self.config[self.configName+'.MainWindow.State'] = QtWidgets.QMainWindow.saveState(self)
        self.config[self.configName+'.PlotNames'] = list(self.plotDict.keys())
        self.displayUi.saveConfig()
        self.displayUi2.saveConfig()
        self.displayUiADC.saveConfig()
        self.autoLoad.saveConfig()
        self.calibrationUi.saveConfig()
        self.settingsUi.saveConfig()
        self.statusDisplay.saveConfig()

    def onClose(self):
        self.autoLoad.onClose()

    def closeEvent(self, e):
        self.onClose()
        
    def reject(self):
        self.config[self.configName+'.pos'] = self.pos()
        self.config[self.configName+'.size'] = self.size()
        self.pulserHardware.dedicatedDataAvailable.disconnect( self.onData )
        self.hide()
        
    def show(self):
        if self.configName+'.pos' in self.config:
            self.move(self.config[self.configName+'.pos'])
        if self.configName+'.size' in self.config:
            self.resize(self.config[self.configName+'.size'])
        super(DedicatedCounters,self).show()
        if not self.dataSlotConnected:
            self.pulserHardware.dedicatedDataAvailable.connect( self.onData )
            self.dataSlotConnected = True
        
    def onStart(self):
        self.pulserHardware.counterMask = self.settings.counterMask
        self.pulserHardware.adcMask = self.settings.adcMask
        self.state = self.OpStates.running
        self.onSettingsChanged()

    def onStop(self):
        self.pulserHardware.counterMask = 0
        self.pulserHardware.adcMask = 0
        self.state = self.OpStates.idle
        self.onSettingsChanged()
                
    def onSave(self):
        logger = logging.getLogger(__name__)
        self.plotDisplayData = self.settingsUi.settings.plotDisplayData
        for plotName in self.plotDisplayData.keys():
            for n in range(20):
                if len(self.xData[n])>0 and len(self.yData[n])>0:
                    trace = TraceCollection()
                    trace.x = self.xData[n]
                    trace.y = self.yData[n]
                    if n < 16:
                        trace.description["counter"] = str(plotName)
                    else:
                        trace.description["ADC"] = str(plotName)
                    filename, _ = DataDirectory().sequencefile("DedicatedCounter_{0}.txt".format(n))
                    trace.addTracePlotting( TracePlotting(name="Counter {0}".format(n)) )
                    trace.save()
        logger.info("saving dedicated counters")
    
    def onClear(self):
        self.xData = [numpy.array([])]*20
        self.yData = [numpy.array([])]*20
        self.tick = 0
        for name, subdict in self.curvesDict.items():
            for n in list(subdict.keys()):
                subdict[n].setData(self.xData[n], self.yData[n])

    def onData(self, data):
        self.tick += 1
        self.displayUi.values = data.data[0:4]
        self.displayUi2.values = data.data[4:8]
        self.displayUiADC.values = self.convertAnalog(data.analog())
        data.analogValues = self.displayUiADC.values
        # if data.data[16] is not None and data.data[16] in self.integrationTimeLookup:
        #     self.dataIntegrationTime = self.integrationTimeLookup[ data.data[16] ]
        # else:
        self.dataIntegrationTime = self.settings.integrationTime
        data.integrationTime = self.dataIntegrationTime
        self.plotDisplayData = self.settingsUi.settings.plotDisplayData
        msIntegrationTime = self.dataIntegrationTime.m_as('ms')
        for index, value in enumerate(data.data[:16]):
            if value is not None:
                y = self.settings.displayUnit.convert(value, msIntegrationTime)
                self.yData[index] = rollingUpdate(self.yData[index], y, self.settings.pointsToKeep)
                self.xData[index] = rollingUpdate(self.xData[index], data.timestamp, self.settings.pointsToKeep)
        for index, value in enumerate(data.analogValues):
            if value is not None:
                myindex = 16 + index
                refValue = self.refValue[myindex]
                if is_Q(value):
                    if refValue is not None and refValue.dimensionality == value.dimensionality:
                        y = value.m_as(refValue)
                    else:
                        self.refValue[myindex] = value
                        y = value.m
                else:
                    y = value
                self.yData[myindex] = rollingUpdate(self.yData[myindex], y, self.settings.pointsToKeep)
                self.xData[myindex] = rollingUpdate(self.xData[myindex], data.timestamp, self.settings.pointsToKeep)
        for name, plotwin in self.curvesDict.items():
            if plotwin:
                with BlockAutoRange(next(iter(plotwin.values()))):
                    for index, plotdata in plotwin.items():
                        plotdata.setData(self.xData[index], self.yData[index])
        self.statusDisplay.setData(data)
        self.dataAvailable.emit(data)
        # logging.getLogger(__name__).info("Max bytes read {0}".format(data.maxBytesRead))
        self.statusDisplay.setData(data)
        self.dataAvailable.emit(data)
 
    def convertAnalog(self, data):
        converted = list()
        for channel, cal in enumerate(self.analogCalbrations):
            converted.append( cal.convertMagnitude(data[channel]) )
        return converted

    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = SequenceDict()
        # initialize all the plot windows we want
        plotNames = self.config.get(self.configName+'.PlotNames', ['Plot'])
        if len(plotNames) < 1:
            plotNames.append('Plot')
        if 'Autoload' not in plotNames:
            plotNames.append('Autoload')
        for name in plotNames:
            dock = Dock(name)
            widget = DateTimePlotWidget(self, name=name)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}

    def onAddPlot(self):
        name, ok = QtGui.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ')
        if ok and name!= 'Autoload':
            name = str(name)
            dock = Dock(name)
            widget = DateTimePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}

    def onRemovePlot(self):
        self.editablePlots = {}
        self.editablePlots.update(self.plotDict)
        if 'Autoload' in self.editablePlots:
            self.editablePlots.pop('Autoload')
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtGui.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", self.editablePlots.keys(), editable=False)
            if ok and name != 'Autoload':
                if ok:
                    name = str(name)
                    self.plotDict[name]["dock"].close()
                    del self.plotDict[name]
        else:
            logger.info("There are no plots which can be removed")

    def onRenamePlot(self):
        self.plotDisplayData = self.settingsUi.settings.plotDisplayData
        self.editablePlots = {}
        self.editablePlots.update(self.plotDict)
        if 'Autoload' in self.editablePlots:
            self.editablePlots.pop('Autoload')
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtGui.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", self.editablePlots.keys(), editable=False)
            if ok and name != 'Autoload':
                newName, newOk = QtGui.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk and newName != 'Autoload':
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(QtCore.QString(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    for plotName in list(self.plotDisplayData.keys()):
                        plotString = str(plotName)
                        if name == plotString:
                            plotIndex = self.plotDisplayData.index(plotName)
                            self.plotDisplayData.renameAt(plotIndex, newName)
                    del self.plotDict[name]
                    self.onSettingsChanged()
        else:
            logger.info("There are no plots which can be renamed")
Esempio n. 51
0
class AWGUi(AWGForm, AWGBase):
    varDictChanged = QtCore.pyqtSignal(object)
    def __init__(self, deviceClass, config, globalDict, parent=None):
        AWGBase.__init__(self, parent)
        AWGForm.__init__(self)
        self.config = config
        self.configname = 'AWGUi.' + deviceClass.displayName
        self.globalDict = globalDict
        self.autoSave = self.config.get(self.configname+'.autoSave', True)
        self.waveformCache = OrderedDict()
        self.settingsDict = self.config.get(self.configname+'.settingsDict', dict())
        self.settingsName = self.config.get(self.configname+'.settingsName', '')
        # self.settingsDict=dict()
        # self.settingsName=''
        self.recentFiles = self.config.get(self.configname+'.recentFiles', dict()) #dict of form {basename: filename}, where filename has path and basename doesn't
        self.lastDir = self.config.get(self.configname+'.lastDir', getProject().configDir)
        Settings.deviceProperties = deviceClass.deviceProperties
        Settings.saveIfNecessary = self.saveIfNecessary
        Settings.replot = self.replot
        for settings in list(self.settingsDict.values()): #make sure all pickled settings are consistent with device, in case it changed
            for channel in range(deviceClass.deviceProperties['numChannels']):
                if channel >= len(settings.channelSettingsList): #create new channels if it's necessary
                    settings.channelSettingsList.append({
                        'segmentDataRoot':AWGSegmentNode(None),
                        'segmentTreeState':None,
                        'plotEnabled':True,
                        'plotStyle':Settings.plotStyles.lines})
                else:
                    settings.channelSettingsList[channel].setdefault('segmentDataRoot', AWGSegmentNode(None))
                    settings.channelSettingsList[channel].setdefault('segmentTreeState', None)
                    settings.channelSettingsList[channel].setdefault('plotEnabled', True)
                    settings.channelSettingsList[channel].setdefault('plotStyle', Settings.plotStyles.lines)
        self.settings = Settings() #we always run settings through the constructor
        if self.settingsName in self.settingsDict:
            self.settings.update(self.settingsDict[self.settingsName])
        self.device = deviceClass(self.settings)

    def setupUi(self, parent):
        logger = logging.getLogger(__name__)
        AWGForm.setupUi(self, parent)
        self.setWindowTitle(self.device.displayName)

        self._varAsOutputChannelDict = dict()
        self.area = DockArea()
        self.splitter.insertWidget(0, self.area)
        self.awgChannelUiList = []
        for channel in range(self.device.deviceProperties['numChannels']):
            awgChannelUi = AWGChannelUi(channel, self.settings, self.globalDict, self.waveformCache, parent=self)
            awgChannelUi.setupUi(awgChannelUi)
            awgChannelUi.dependenciesChanged.connect(self.onDependenciesChanged)
            self.awgChannelUiList.append(awgChannelUi)
            dock = Dock("AWG Channel {0}".format(channel))
            dock.addWidget(awgChannelUi)
            self.area.addDock(dock, 'right')
            self.device.waveforms[channel] = awgChannelUi.waveform
        self.refreshVarDict()

        # Settings control
        self.saveButton.clicked.connect( self.onSave )
        self.removeButton.clicked.connect( self.onRemove )
        self.reloadButton.clicked.connect( self.onReload )
        self.settingsModel = QtCore.QStringListModel()
        self.settingsComboBox.setModel(self.settingsModel)
        self.settingsModel.setStringList( sorted(self.settingsDict.keys()) )
        self.settingsComboBox.setCurrentIndex( self.settingsComboBox.findText(self.settingsName) )
        self.settingsComboBox.currentIndexChanged[str].connect( self.onLoad )
        self.settingsComboBox.lineEdit().editingFinished.connect( self.onComboBoxEditingFinished )
        self.autoSaveCheckBox.setChecked(self.autoSave)
        self.saveButton.setEnabled( not self.autoSave )
        self.saveButton.setVisible( not self.autoSave )
        self.reloadButton.setEnabled( not self.autoSave )
        self.reloadButton.setVisible( not self.autoSave )
        self.autoSaveCheckBox.stateChanged.connect(self.onAutoSave)

        #programming options table
        self.programmingOptionsTable.setupUi(globalDict=self.globalDict, parameterDict=self.device.parameters())
        self.programmingOptionsTable.valueChanged.connect( self.device.update )

        # Table
        self.tableModel = AWGTableModel(self.settings, self.globalDict)
        self.tableView.setModel(self.tableModel)
        self.tableModel.valueChanged.connect(self.onValue)
        self.delegate = MagnitudeSpinBoxDelegate(self.globalDict)
        self.tableView.setItemDelegateForColumn(self.tableModel.column.value, self.delegate)

        #File
        self.filenameModel = QtCore.QStringListModel()
        self.filenameComboBox.setModel(self.filenameModel)
        self.filenameModel.setStringList( [basename for basename, filename in list(self.recentFiles.items()) if os.path.exists(filename)] )
        self.filenameComboBox.setCurrentIndex(self.filenameComboBox.findText(os.path.basename(self.settings.filename)))
        self.filenameComboBox.currentIndexChanged[str].connect(self.onFilename)
        self.removeFileButton.clicked.connect(self.onRemoveFile)
        self.newFileButton.clicked.connect(self.onNewFile)
        self.openFileButton.clicked.connect(self.onOpenFile)
        self.saveFileButton.clicked.connect(self.onSaveFile)
        self.reloadFileButton.clicked.connect(self.onReloadFile)

        #cache
        self.cacheDepthSpinBox.setValue(self.settings.cacheDepth)
        self.cacheDepthSpinBox.valueChanged.connect(self.onCacheDepth)
        self.clearCacheButton.clicked.connect(self.onClearCache)

        #status bar
        self.label = QtGui.QLabel('Sample Rate: {0}'.format(self.settings.deviceProperties['sampleRate']))
        self.statusbar.addWidget(self.label)

        #Restore GUI state
        state = self.config.get(self.configname+'.state')
        pos = self.config.get(self.configname+'.pos')
        size = self.config.get(self.configname+'.size')
        isMaximized = self.config.get(self.configname+'.isMaximized')
        dockAreaState = self.config.get(self.configname+'.dockAreaState')
        guiState = self.config.get(self.configname+".guiState")
        restoreGuiState(self, guiState)
        try:
            if pos:
                self.move(pos)
            if size:
                self.resize(size)
            if isMaximized:
                self.showMaximized()
            if state:
                self.restoreState(state)
            for awgChannelUi in self.awgChannelUiList:
                channelGuiState = self.config[self.configname+"channel{0}.guiState".format(awgChannelUi.channel)]
                restoreGuiState(awgChannelUi, channelGuiState)
        except Exception as e:
            logger.warning("Error on restoring state in AWGUi {0}. Exception occurred: {1}".format(self.device.displayName, e))
        try:
            if dockAreaState:
                self.area.restoreState(dockAreaState)
        except Exception as e:
            logger.warning("Cannot restore dock state in AWGUi {0}. Exception occurred: {1}".format(self.device.displayName, e))
            self.area.deleteLater()
            self.area = DockArea()
            self.splitter.insertWidget(0, self.area)
            for channelUi in self.awgChannelUiList:
                dock = Dock("AWG Channel {0}".format(channel))
                dock.addWidget(channelUi)
                self.area.addDock(dock, 'right')
        self.saveIfNecessary()

    def onCacheDepth(self, newVal):
        self.settings.cacheDepth = newVal
        self.saveIfNecessary()

    def onClearCache(self):
        self.waveformCache.clear()

    def onComboBoxEditingFinished(self):
        """a settings name is typed into the combo box"""
        currentText = str(self.settingsComboBox.currentText())
        if self.settingsName != currentText:
            self.settingsName = currentText
            if self.settingsName not in self.settingsDict:
                self.settingsDict[self.settingsName] = copy.deepcopy(self.settings)
            self.onLoad(self.settingsName)

    def saveIfNecessary(self):
        """save the current settings if autosave is on and something has changed"""
        currentText = str(self.settingsComboBox.currentText())
        if self.settingsDict.get(self.settingsName)!=self.settings or currentText!=self.settingsName:
            if self.autoSave:
                self.onSave()
            else:
                self.saveButton.setEnabled(True)

    def replot(self):
        """plot all channels"""
        for channelUi in self.awgChannelUiList:
            channelUi.replot()

    def onSave(self):
        """save current settings"""
        self.settingsName = str(self.settingsComboBox.currentText())
        self.settingsDict[self.settingsName] = copy.deepcopy(self.settings)
        with BlockSignals(self.settingsComboBox) as w:
            self.settingsModel.setStringList( sorted(self.settingsDict.keys()) )
            w.setCurrentIndex(w.findText(self.settingsName))
        self.saveButton.setEnabled(False)

    def saveConfig(self):
        """save GUI configuration to config"""
        self.config[self.configname+".guiState"] = saveGuiState(self)
        for awgChannelUi in self.awgChannelUiList:
            self.config[self.configname+"channel{0}.guiState".format(awgChannelUi.channel)] = saveGuiState(awgChannelUi)
            self.settings.channelSettingsList[awgChannelUi.channel]['segmentTreeState'] = awgChannelUi.segmentView.saveTreeState()
        self.config[self.configname+'.state'] = self.saveState()
        self.config[self.configname+'.pos'] = self.pos()
        self.config[self.configname+'.size'] = self.size()
        self.config[self.configname+'.isMaximized'] = self.isMaximized()
        self.config[self.configname+'.isVisible'] = self.isVisible()
        self.config[self.configname+'.dockAreaState'] = self.area.saveState()
        self.config[self.configname+'.settingsDict'] = self.settingsDict
        self.config[self.configname+'.settingsName'] = self.settingsName
        self.config[self.configname+'.autoSave'] = self.autoSave
        self.config[self.configname+'.recentFiles'] = self.recentFiles
        self.config[self.configname+'.lastDir'] = self.lastDir

    def onRemove(self):
        """Remove current settings from combo box"""
        name = str(self.settingsComboBox.currentText())
        if name in self.settingsDict:
            self.settingsDict.pop(name)
            self.settingsName = list(self.settingsDict.keys())[0] if self.settingsDict else ''
            with BlockSignals(self.settingsComboBox) as w:
                self.settingsModel.setStringList( sorted(self.settingsDict.keys()) )
                w.setCurrentIndex(w.findText(self.settingsName))
            self.onLoad(self.settingsName)

    def onReload(self):
        """Reload settings"""
        name = str(self.settingsComboBox.currentText())
        self.onLoad(name)
       
    def onLoad(self, name):
        """load settings"""
        for channelUi in self.awgChannelUiList:
            self.settings.channelSettingsList[channelUi.channel]['segmentTreeState'] = channelUi.segmentView.saveTreeState()
        name = str(name)
        if name in self.settingsDict:
            self.settingsName = name
            self.tableModel.beginResetModel()
            [channelUi.segmentModel.beginResetModel() for channelUi in self.awgChannelUiList]
            self.settings.update(self.settingsDict[self.settingsName])
            self.programmingOptionsTable.setParameters( self.device.parameters() )
            self.saveButton.setEnabled(False)
            with BlockSignals(self.filenameComboBox) as w:
                w.setCurrentIndex(w.findText(os.path.basename(self.settings.filename)))
            with BlockSignals(self.cacheDepthSpinBox) as w:
                w.setValue(self.settings.cacheDepth)
            for channelUi in self.awgChannelUiList:
                channelUi.waveform.updateDependencies()
                channelUi.plotCheckbox.setChecked(self.settings.channelSettingsList[channelUi.channel]['plotEnabled'])
                with BlockSignals(channelUi.styleComboBox) as w:
                    w.setCurrentIndex(self.settings.channelSettingsList[channelUi.channel]['plotStyle'])
                channelUi.segmentModel.root = self.settings.channelSettingsList[channelUi.channel]['segmentDataRoot']
                channelUi.replot()
            self.onDependenciesChanged()
            self.saveButton.setEnabled(False)
            self.tableModel.endResetModel()
            [channelUi.segmentModel.endResetModel() for channelUi in self.awgChannelUiList]
            for channelUi in self.awgChannelUiList:
                channelUi.segmentView.restoreTreeState(self.settings.channelSettingsList[channelUi.channel]['segmentTreeState'])

    def onAutoSave(self, checked):
        """autosave is changed"""
        self.autoSave = checked
        self.saveButton.setEnabled( not checked )
        self.saveButton.setVisible( not checked )
        self.reloadButton.setEnabled( not checked )
        self.reloadButton.setVisible( not checked )
        if checked:
            self.onSave()

    def onValue(self, var=None, value=None):
        """variable value is changed in the table"""
        self.saveIfNecessary()
        self.replot()

    def evaluate(self, name):
        """re-evaluate the text in the tableModel (happens when a global changes)"""
        self.tableModel.evaluate(name)
        self.programmingOptionsTable.evaluate(name)

    def refreshVarDict(self):
        """refresh the variable dictionary by checking all waveform dependencies"""
        allDependencies = set()
        [channelUi.waveform.updateDependencies() for channelUi in self.awgChannelUiList]
        [allDependencies.update(channelUi.waveform.dependencies) for channelUi in self.awgChannelUiList]
        default = lambda varname:{'value':Q(1, 'us'), 'text':None} if varname.startswith('Duration') else {'value':Q(0), 'text':None}
        deletions = [varname for varname in self.settings.varDict if varname not in allDependencies]
        [self.settings.varDict.pop(varname) for varname in deletions] #remove all values that aren't dependencies anymore
        [self.settings.varDict.setdefault(varname, default(varname)) for varname in allDependencies] #add missing values
        self.settings.varDict.sort(key = lambda val: -1 if val[0].startswith('Duration') else ord( str(val[0])[0] ))
        self.varDictChanged.emit(self.varAsOutputChannelDict)
        for channelUi in self.awgChannelUiList:
            channelUi.replot()

    def onDependenciesChanged(self, channel=None):
        """When dependencies change, refresh all variables"""
        self.tableModel.beginResetModel()
        self.refreshVarDict()
        self.tableModel.endResetModel()
        self.saveIfNecessary()

    def onFilename(self, basename):
        """filename combo box is changed. Open selected file"""
        basename = str(basename)
        filename = self.recentFiles[basename]
        if os.path.isfile(filename) and filename!=self.settings.filename:
            self.openFile(filename)

    def onRemoveFile(self):
        """Remove file button is clicked. Remove filename from combo box."""
        text = str(self.filenameComboBox.currentText())
        index = self.filenameComboBox.findText(text)
        if text in self.recentFiles:
            self.recentFiles.pop(text)
        with BlockSignals(self.filenameComboBox) as w:
            self.filenameModel.setStringList(list(self.recentFiles.keys()))
            w.setCurrentIndex(-1)
            self.onFilename(w.currentText())

    def onNewFile(self):
        """New button is clicked. Pop up dialog asking for new name, and create file."""
        filename, _ = QtWidgets.QFileDialog.getSaveFileName(self, 'New File', self.lastDir, 'YAML (*.yml)')
        if filename:
            self.lastDir, basename = os.path.split(filename)
            self.recentFiles[basename] = filename
            self.settings.filename = filename
            with BlockSignals(self.filenameComboBox) as w:
                self.filenameModel.setStringList(list(self.recentFiles.keys()))
                w.setCurrentIndex(w.findText(basename))
            self.onSaveFile()

    def onOpenFile(self):
        """Open file button is clicked. Pop up dialog asking for filename."""
        filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Select File', self.lastDir, 'YAML (*.yml)')
        if filename:
            self.openFile(filename)

    def openFile(self, filename):
        """Open the file 'filename'"""
        if os.path.exists(filename):
            self.lastDir, basename = os.path.split(filename)
            self.recentFiles[basename] = filename
            self.settings.filename = filename
            with BlockSignals(self.filenameComboBox) as w:
                self.filenameModel.setStringList(list(self.recentFiles.keys()))
                w.setCurrentIndex(w.findText(basename))
            with open(filename, 'r') as f:
                yamldata = yaml.load(f)
            variables = yamldata.get('variables')
            channelData = yamldata.get('channelData')
            self.tableModel.beginResetModel()
            [channelUi.segmentModel.beginResetModel() for channelUi in self.awgChannelUiList]
            if channelData:
                for channelUi in self.awgChannelUiList:
                    if channelUi.channel < len(channelData):
                        self.settings.channelSettingsList[channelUi.channel]['segmentDataRoot'] = self.convertListToNodes(channelData[channelUi.channel], isRoot=True)
                        channelUi.segmentModel.root = self.settings.channelSettingsList[channelUi.channel]['segmentDataRoot']
            if variables:
                for varname, vardata in list(variables.items()):
                    self.settings.varDict.setdefault(varname, dict())
                    self.settings.varDict[varname]['value'] = Q(vardata['value'], vardata['unit'])
                    self.settings.varDict[varname]['text'] = vardata['text']
            for channelUi in self.awgChannelUiList:
                channelUi.waveform.updateDependencies()
                channelUi.replot()
            self.onDependenciesChanged()
            self.tableModel.endResetModel()
            [channelUi.segmentModel.endResetModel() for channelUi in self.awgChannelUiList]
            [channelUi.segmentView.expandAll() for channelUi in self.awgChannelUiList]
        else:
            logging.getLogger(__name__).warning("file '{0}' does not exist".format(filename))
            if filename in self.recentFiles:
                del self.recentFiles[filename]
                with BlockSignals(self.filenameComboBox) as w:
                    self.filenameModel.setStringList(list(self.recentFiles.keys()))
                    w.setCurrentIndex(-1)

    def convertNodeToList(self, node):
        nodeList = []
        for childNode in node.children:
            if childNode.nodeType==nodeTypes.segment:
                nodeList.append( {'equation':childNode.equation,
                                  'duration':childNode.duration,
                                  'enabled':childNode.enabled}
                                 )
            elif childNode.nodeType==nodeTypes.segmentSet:
                nodeList.append( {'repetitions':childNode.repetitions,
                                  'enabled':childNode.enabled,
                                  'segments':self.convertNodeToList(childNode)}
                                 )
        return nodeList

    def convertListToNodes(self, data, parent=None, enabled=True, repetitions=None, isRoot=False):
        node = AWGSegmentNode(parent=None) if isRoot else AWGSegmentSet(parent=parent, enabled=enabled, repetitions=repetitions)
        for segment in data:
            if 'duration' in segment:
                childNode = AWGSegment(parent=node,
                                       equation=segment['equation'],
                                       duration=segment['duration'],
                                       enabled=segment['enabled'])
                node.children.append(childNode)
            elif 'repetitions' in segment:
                segmentSet = self.convertListToNodes(segment['segments'], parent=node, enabled=segment['enabled'], repetitions=segment['repetitions'])
                node.children.append(segmentSet)
            else:
                logging.getLogger(__name__).error("Unable to convert list to nodes")
        return node

    def onSaveFile(self):
        """Save button is clicked. Save data to segment file"""
        channelData = []
        for channelSettings in self.settings.channelSettingsList:
            segmentData = self.convertNodeToList(channelSettings['segmentDataRoot'])
            channelData.append(segmentData)
        yamldata = {'channelData': channelData}
        variables={varname:
                             {'value':float(varValueTextDict['value'].toStringTuple()[0]),
                              'unit':varValueTextDict['value'].toStringTuple()[1],
                              'text':varValueTextDict['text']}
                         for varname, varValueTextDict in list(self.settings.varDict.items())}
        yamldata.update({'variables':variables})
        with open(self.settings.filename, 'w') as f:
            yaml.dump(yamldata, f, default_flow_style=False)

    def onReloadFile(self):
        self.openFile(self.settings.filename)

    @QtCore.pyqtProperty(dict)
    def varAsOutputChannelDict(self):
        """dict of output channels, for use in scans"""
        for varname in self.settings.varDict:
            if varname not in self._varAsOutputChannelDict:
                self._varAsOutputChannelDict[varname] = VarAsOutputChannel(self, varname, self.globalDict)
        deletions = [varname for varname in self._varAsOutputChannelDict if varname not in self.settings.varDict]
        [self._varAsOutputChannelDict.pop(varname) for varname in deletions] #remove all values that aren't dependencies anymore
        return self._varAsOutputChannelDict

    def close(self):
        self.saveConfig()
        numTempAreas = len(self.area.tempAreas)
        for i in range(numTempAreas):
            if len(self.area.tempAreas) > 0:
                self.area.tempAreas[0].win.close()
        super(AWGUi, self).close()
class InstrumentLoggingUi(WidgetContainerBase, WidgetContainerForm):
    plotConfigurationChanged = QtCore.pyqtSignal( object )
    def __init__(self, project, config):
        super(InstrumentLoggingUi, self).__init__()
        self.config = config
        self.project = project
        self.dockWidgetList = list()
        self.plotDict = dict()
        self.instrument = ""
        
    def __enter__(self):
        return self
    
    def __exit__(self, excepttype, value, traceback):
        return False
    
    def setupUi(self, parent):
        super(InstrumentLoggingUi, self).setupUi(parent)
                
        logger = logging.getLogger()        
            
        self.parent = parent
        self.tabList = list()
        self.tabDict = dict()
               
        self.setupPlots()       
        # Traceui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, "Main", self.plotDict )
        self.traceui.setupUi(self.traceui)
        self.setupAsDockWidget(self.traceui, "Traces", QtCore.Qt.LeftDockWidgetArea)

        # new fit widget
        self.fitWidget = FitUi(self.traceui, self.config, "Main")
        self.fitWidget.setupUi(self.fitWidget)
        self.fitWidgetDock = self.setupAsDockWidget(self.fitWidget, "Fit", QtCore.Qt.LeftDockWidgetArea)

        self.instrumentLoggingHandler = InstrumentLoggingHandler(self.traceui, self.plotDict, self.config, 'externalInput')

        self.ExternalParametersSelectionUi = InstrumentLoggingSelection(self.config, classdict=LoggingInstruments, newDataSlot=self.instrumentLoggingHandler.addData, plotNames=list(self.plotDict.keys()),
                                                                        instrumentLoggingHandler=self.instrumentLoggingHandler )
        self.ExternalParametersSelectionUi.setupUi( self.ExternalParametersSelectionUi )
        self.ExternalParameterSelectionDock = QtWidgets.QDockWidget("Params Selection")
        self.ExternalParameterSelectionDock.setObjectName("_ExternalParameterSelectionDock")
        self.ExternalParameterSelectionDock.setWidget(self.ExternalParametersSelectionUi)
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.ExternalParameterSelectionDock)
        self.instrumentLoggingHandler.paramTreeChanged.connect( self.ExternalParametersSelectionUi.refreshParamTree)
    
        self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config)
        self.instrumentLoggingDisplay.setupUi( self.ExternalParametersSelectionUi.enabledParametersObjects, self.instrumentLoggingDisplay )
        self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget("Params Reading")
        self.instrumentLoggingDisplayDock.setObjectName("_ExternalParameterDisplayDock")
        self.instrumentLoggingDisplayDock.setWidget(self.instrumentLoggingDisplay)
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.instrumentLoggingDisplayDock)
        self.ExternalParametersSelectionUi.selectionChanged.connect( self.instrumentLoggingDisplay.setupParameters )
        self.instrumentLoggingHandler.newData.connect( self.instrumentLoggingDisplay.update )
    
        self.instrumentLoggingQueryUi = InstrumentLoggerQueryUi(self.config, self.traceui, self.plotDict )
        self.instrumentLoggingQueryUi.setupUi( self.instrumentLoggingQueryUi )
        self.instrumentLoggingQueryUiDock = self.setupAsDockWidget(self.instrumentLoggingQueryUi, "Query", QtCore.Qt.LeftDockWidgetArea)
    
        self.addPlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)
        
        self.removePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        self.setWindowTitle("Instrument Logger ({0})".format(self.project) )
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        try:
            if 'pyqtgraph-dockareastate' in self.config:
                self.area.restoreState(self.config['pyqtgraph-dockareastate'])
        except Exception as e:
            logger.warning("Cannot restore dock state in experiment {0}. Exception occurred: ".format(self.experimentName) + str(e))
        QtCore.QTimer.singleShot(60000, self.onCommitConfig )      

                    
    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = dict()
        # initialize all the plot windows we want
        plotNames = self.config.get( 'PlotNames', ['Scan'] )
        if len(plotNames)<1:
            plotNames.append('Scan')
        for name in plotNames:
            dock = Dock(name)
            widget = DateTimePlotWidget(self, name=name)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
        
    def setupAsDockWidget(self, widget, name, area=QtCore.Qt.RightDockWidgetArea, stackAbove=None, stackBelow=None ):
        dock = QtWidgets.QDockWidget(name)
        dock.setObjectName(name)
        dock.setWidget( widget )
        self.addDockWidget(area, dock )
        self.dockWidgetList.append( dock )
        if stackAbove is not None:
            self.tabifyDockWidget( stackAbove, dock )
        elif stackBelow is not None:
            self.tabifyDockWidget( dock, stackBelow )
        return dock           

    def onAddPlot(self):
        name, ok = QtWidgets.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ')
        if ok:
            name = str(name)
            dock = Dock(name)
            widget = DateTimePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
            self.plotConfigurationChanged.emit( self.plotDict )
            
    def onRemovePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", list(self.plotDict.keys()), editable=False)
            if ok:
                name = str(name)
                self.plotDict[name]["dock"].close()
                del self.plotDict[name]
                self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be removed")
                
    def onRenamePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", list(self.plotDict.keys()), editable=False)
            if ok:
                newName, newOk = QtWidgets.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk:
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(str(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    del self.plotDict[name]
                    self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be renamed")

    def onSave(self):
        logger = logging.getLogger(__name__)
        logger.info( "Saving config" )
        filename, _ = DataDirectory.DataDirectory().sequencefile("InstrumentLogger-configuration.db")
        self.saveConfig()
        self.config.saveConfig(filename)
    
    def onClose(self):
        self.parent.close()
        
    def closeEvent(self, e):
        logger = logging.getLogger(__name__)
        logger.info( "Close Event" )
        logger = logging.getLogger("")
        logger.debug( "Saving Configuration" )
        self.saveConfig()

    def saveConfig(self):
        self.config['MainWindow.State'] = self.parent.saveState()
        for tab in self.tabList:
            tab.saveConfig()
        self.config['MainWindow.pos'] = self.pos()
        self.config['MainWindow.size'] = self.size()
        self.config['PlotNames'] = list(self.plotDict.keys())
        self.config['pyqtgraph-dockareastate'] = self.area.saveState()
        self.ExternalParametersSelectionUi.saveConfig()
        self.instrumentLoggingHandler.saveConfig()
        self.instrumentLoggingQueryUi.saveConfig()
        self.instrumentLoggingDisplay.saveConfig()
        
    def onCommitConfig(self):
        self.saveConfig()
        QtCore.QTimer.singleShot(60000, self.onCommitConfig )      
Esempio n. 53
0
class AWGOptimizer(Form, Base):
    def __init__(self, deviceClass, config, parent=None):
        Base.__init__(self, parent)
        Form.__init__(self)
        Form.setupUi(self, self)
        self.config = config
        self.configname = "AWGOptimizer"
        self.setWindowTitle("AWG Optimizer")
        guiState = self.config.get(self.configname + ".guiState")
        state = self.config.get(self.configname + '.state')
        pos = self.config.get(self.configname + '.pos')
        size = self.config.get(self.configname + '.size')
        isMaximized = self.config.get(self.configname + '.isMaximized')
        restoreGuiState(self, self.config.get(self.configname + ".guiState"))
        if state: self.restoreState(state)
        if pos: self.move(pos)
        if size: self.resize(size)
        if isMaximized: self.showMaximized()

        self.show()
        self.awgUi = AWGUi(deviceClass, config, dict())
        self.awgUi.setupUi(self.awgUi)
        self.splitter.insertWidget(1, self.awgUi)

        #oscilloscope plot window
        name = "Oscilloscope Trace"
        self.scopeDock = Dock(name)
        self.scopePlot = CoordinatePlotWidget(self, name=name)
        self.scopeView = self.scopePlot._graphicsView
        self.scopeDock.addWidget(self.scopePlot)
        self.area = DockArea()
        self.area.addDock(self.scopeDock)
        self.plotDict = {
            name: {
                "dock": self.scopeDock,
                "widget": self.scopePlot,
                "view": self.scopeView
            }
        }
        self.verticalLayout.insertWidget(0, self.area)

        #trace ui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons,
                                       self.config,
                                       self.configname,
                                       self.plotDict,
                                       hasMeasurementLog=False,
                                       highlightUnsaved=False)
        self.traceui.setupUi(self.traceui)
        traceDock = Dock("Traces")
        traceDock.addWidget(self.traceui)
        self.area.addDock(traceDock, 'left')
        self.device = self.awgUi.device

        self.measureWaveformButton.clicked.connect(self.onMeasureWaveform)
        self.optimizeButton.clicked.connect(self.onOptimize)

        dockAreaState = self.config.get(self.configname + '.dockAreaState')
        try:
            if dockAreaState: self.area.restoreState(dockAreaState)
        except Exception as e:
            print(e)

    def saveConfig(self):
        self.config[self.configname + ".guiState"] = saveGuiState(self)
        self.config[self.configname + '.state'] = self.saveState()
        self.config[self.configname + '.pos'] = self.pos()
        self.config[self.configname + '.size'] = self.size()
        self.config[self.configname + '.isMaximized'] = self.isMaximized()
        self.config[self.configname + '.dockAreaState'] = self.area.saveState()
        self.awgUi.saveConfig()

    def closeEvent(self, e):
        self.saveConfig()

    def onMeasureWaveform(self):
        pass

    def onOptimize(self):
        pass
Esempio n. 54
0
    def initDialog(self,results=None,KData=None,bDrawText=False):
        '''
        orders,记录当日00:00前一日开盘时间发送的交易命令
        trasactions,记录当日00:00前一日已执行的orders
        positions,记录当日00:00时,各个symbols的positions
        所以,这三个量都是数组,且大小不定,所以,不宜图形方式展示,适宜table方式展示
        其他单值参数都可以考虑图形化方式
        特别是pnl,cash,portfolio等
        perf的生成时点是00:00,其内容为00:00前一天的活动
        perf转化记录入result时,需要设置Index,
        此Index的值为生成记录时点后的一天的收盘时间。
        
        例如:
        有三个交易日:2015-12-01,12-02,12-03
        开收盘时间:Asia/Shanghai:09:30--15:00 (utc:01:30--07:00)
        使用instant_fill==True方式执行订单
        每日开盘时Buy(1)
        
        有如下Events列表会生成并被处理
        1)2015-12-01 00:00 utc
        生成perf
                perf内容:由于是第一交易日的开始时间(非开市时间),无内容可记
        记录入result:
                记录Index:result.index = 2015-12-01 07:00
        2)2015-12-01 01:30 utc
        生成order,生成transaction,生成position
        3)2015-12-02 00:00 utc
        生成perf
                perf内容:2015-12-01 00:00 utc 至 2015-12-02 00:00 utc期间发生的交易事项及内容
        记录入result:
                记录Index:result.index = 2015-12-02 07:00
        
        之后的4)5)6)同上
        
        不合逻辑的地方需特别注意:
	1)perf的生成时间和记录时间不一致,00:00生成(当日开始(非开市)),07:00记录(当日收市)
	2)perf记录的是00:00之前一日的交易,记录时点却是当日收盘(当日收盘时间的记录,给人直观的理解应是记录当日开盘到收盘期间发生的业务)
        '''
        # 1) creates layouts
        dialog = QtGui.QDialog()   
        mainLayout = QtGui.QHBoxLayout()
        rightLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(rightLayout)
        dialog.setLayout(mainLayout)        
        dialog.setWindowTitle(('Strategy Results'))
        # 2) creates widgets 
        #  2.1)candle
        import os,sys        
        xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdataUI'))
        sys.path.append(xpower)
    
        from Widgets.pgCandleWidgetCross import pgCandleWidgetCross
        from Widgets.pgCrossAddition import pgCrossAddition
        pgCandleView = pgCandleWidgetCross(dataForCandle=KData)        
        self.pricePlot(pgCandleView) 
        #  2.2)Pnl
        PyqtGraphPnl = pgCrossAddition()
        self.pnlPlot(PyqtGraphPnl,bDrawText=bDrawText)
        #  2.3)Position
        #PyqtGraphPosition = pgCrossAddition()
        #self.positionPlot(PyqtGraphPosition)
        #  2.4)portfolio
        PyqtGraphPortfolio = pgCrossAddition()
        self.portfolioPlot(PyqtGraphPortfolio)
        #  2.5)price
        PyqtGraphindicators = pgCrossAddition()
        self.pricePlot(PyqtGraphindicators)    
        self.indicatorsPlot(PyqtGraphindicators)
        #  2.6)order
        #PyqtGraphOrder = pgCrossAddition()
        #self.orderPlot(PyqtGraphOrder)
        #self.pricePlot(PyqtGraphOrder)
        from pyqtgraph.dockarea import DockArea,Dock 
        area = DockArea()
        ## Create docks, place them into the window one at a time.
        ## Note that size arguments are only a suggestion; docks will still have to
        ## fill the entire dock area and obey the limits of their internal widgets.
        d1 = Dock("candles", size=(200,300))     ## give this dock the minimum possible size
        d2 = Dock("pnl", closable=True, size=(200,100))
        #d3 = Dock("position", size=(200,100))
        d4 = Dock("portfolio", size=(200,100))
        d5 = Dock("price", size=(200,100))
        #d6 = Dock("order time,amount",size=(200,100))

        area.addDock(d1, 'bottom') 
        area.addDock(d2, 'bottom')    
        #area.addDock(d3, 'bottom')
        area.addDock(d4, 'bottom')     
        area.addDock(d5, 'bottom', d1)  
        #area.addDock(d6, 'bottom', d1)
        rightLayout.addWidget(area)

        d1.addWidget(pgCandleView)        
        d2.addWidget(PyqtGraphPnl)     
        #d3.addWidget(PyqtGraphPosition)             
        d4.addWidget(PyqtGraphPortfolio)        
        d5.addWidget(PyqtGraphindicators)
        #d6.addWidget(PyqtGraphOrder)
        
        PyqtGraphPnl.setXLink(pgCandleView)
        #PyqtGraphPosition.setXLink(pgCandleView)
        PyqtGraphPortfolio.setXLink(pgCandleView)
        PyqtGraphindicators.setXLink(pgCandleView)
        #PyqtGraphOrder.setXLink(pgCandleView)
        return dialog
Esempio n. 55
0
class DigitalLockUi(WidgetContainerBase, WidgetContainerForm):
    levelNameList = ["debug", "info", "warning", "error", "critical"]
    levelValueList = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]
    plotConfigurationChanged = QtCore.pyqtSignal( object )
    def __init__(self, config, project):
        self.config = config
        self.project = project
        super(DigitalLockUi, self).__init__()
        self.settings = SettingsDialog.Settings()
        self.deviceSerial = config.get('Settings.deviceSerial')
        self.deviceDescription = config.get('Settings.deviceDescription')
        self.loggingLevel = config.get('Settings.loggingLevel', logging.INFO)
        self.consoleMaximumLines = config.get('Settings.consoleMaximumLines', 0)
        self.dockWidgetList = list()
        if self.loggingLevel not in self.levelValueList: self.loggingLevel = logging.INFO
        self.plotDict = dict()
        
    def __enter__(self):
        self.pulser = Controller()
        return self
    
    def __exit__(self, excepttype, value, traceback):
        self.pulser.shutdown()
        return False
    
    def setupUi(self, parent):
        super(DigitalLockUi, self).setupUi(parent)
        self.dockWidgetConsole.hide()
        self.loggerUi = LoggerLevelsUi(self.config)
        self.loggerUi.setupUi(self.loggerUi)
        self.setupAsDockWidget(self.loggerUi, "Logging", QtCore.Qt.NoDockWidgetArea)
                
        logger = logging.getLogger()        
        self.toolBar.addWidget(ExceptionLogButton())
        
        # Setup Console Dockwidget
        self.levelComboBox.addItems(self.levelNameList)
#        self.levelComboBox.currentIndexChanged[int].connect( self.setLoggingLevel )            
        self.levelComboBox.setCurrentIndex( self.levelValueList.index(self.loggingLevel) )
#        self.consoleClearButton.clicked.connect( self.onClearConsole )
#        self.linesSpinBox.valueChanged.connect( self.onConsoleMaximumLinesChanged )
        
        self.parent = parent
        self.tabList = list()
        self.tabDict = dict()
               
        # initialize FPGA settings
        self.settingsDialog = SettingsDialog.SettingsDialog(self.pulser, self.config, self.parent)
        self.settingsDialog.setupUi()
        self.settings = self.settingsDialog.settings

        try:
            configFile = os.path.splitext(self.settings.bitfile)[0] + '.yml'
            with open(configFile, 'r') as f:
                lockConfig = yaml.load(f)
            self.settings.onBoardADCEncoding = lockConfig['onBoardADCEncoding']
        except Exception as e:
            logger.error('unable to load config file: {0}'.format(e))
            self.settings.onBoardADCEncoding = None

        self.setupPlots()

        # Traceui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, "Main", self.plotDict)
        self.traceui.setupUi(self.traceui)
        self.setupAsDockWidget(self.traceui, "Traces", QtCore.Qt.LeftDockWidgetArea)

        # lock status
        self.lockStatus = LockStatus(self.pulser, self.config, self.traceui, self.plotDict, self.settings, self.parent)
        self.lockStatus.setupUi()
        self.setupAsDockWidget(self.lockStatus, "Status", QtCore.Qt.RightDockWidgetArea)
        self.plotConfigurationChanged.connect( self.lockStatus.onPlotConfigurationChanged )

        # Trace control
        self.traceControl = TraceControl(self.pulser, self.config, self.traceui, self.plotDict, self.parent)
        self.traceControl.setupUi()
        self.setupAsDockWidget(self.traceControl, "Trace Control", QtCore.Qt.RightDockWidgetArea)
        self.plotConfigurationChanged.connect( self.traceControl.onPlotConfigurationChanged )

        # Lock control
        self.lockControl = LockControl(self.pulser, self.config, self.settings, self.parent)
        self.lockControl.dataChanged.connect( self.lockStatus.onControlChanged )
        self.lockControl.dataChanged.connect( self.traceControl.onControlChanged )
        self.lockControl.setupUi() 
        self.lockStatus.newDataAvailable.connect( self.lockControl.onStreamData )
        self.traceControl.newDataAvailable.connect( self.lockControl.onTraceData )
        self.setupAsDockWidget(self.lockControl, "Control", QtCore.Qt.RightDockWidgetArea)
        
        self.actionSave.triggered.connect(self.onSave)
        self.actionSettings.triggered.connect(self.onSettings)
        self.actionExit.triggered.connect(self.onClose)
        self.actionProject.triggered.connect( self.onProjectSelection)

        self.addPlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)
        
        self.removePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        self.setWindowTitle( "Digital Lock ({0})".format(self.project) )
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        self.initMenu()
        try:
            if 'pyqtgraph-dockareastate' in self.config:
                self.area.restoreState(self.config['pyqtgraph-dockareastate'])
        except Exception as e:
            logger.error("Cannot restore dock state in experiment {0}. Exception occurred: ".format(self.experimentName) + str(e))
        QtCore.QTimer.singleShot(300000, self.onCommitConfig )      
       
    def onCommitConfig(self):
        self.saveConfig()
        self.config.saveConfig() 
        QtCore.QTimer.singleShot(300000, self.onCommitConfig )      
            
        
    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = dict()
        # initialize all the plot windows we want
        plotNames = self.config.get( 'PlotNames', ['History', 'Scope'] )
        if len(plotNames)<1:
            plotNames.append('History')
        for name in plotNames:
            dock = Dock(name)
            widget = CoordinatePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
        
    def setupAsDockWidget(self, widget, name, area=QtCore.Qt.RightDockWidgetArea, stackAbove=None, stackBelow=None ):
        dock = QtWidgets.QDockWidget(name)
        dock.setObjectName(name)
        dock.setWidget( widget )
        self.addDockWidget(area, dock )
        self.dockWidgetList.append( dock )
        if stackAbove is not None:
            self.tabifyDockWidget( stackAbove, dock )
        elif stackBelow is not None:
            self.tabifyDockWidget( dock, stackBelow )
        return dock           

    def onAddPlot(self):
        name, ok = QtWidgets.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ')
        if ok:
            name = str(name)
            dock = Dock(name)
            widget = CoordinatePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
            self.plotConfigurationChanged.emit( self.plotDict )
            
    def onRemovePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", list(self.plotDict.keys()), editable=False)
            if ok:
                name = str(name)
                self.plotDict[name]["dock"].close()
                del self.plotDict[name]
                self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be removed")
                
    def onRenamePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", list(self.plotDict.keys()), editable=False)
            if ok:
                newName, newOk = QtWidgets.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk:
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(str(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    del self.plotDict[name]
                    self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be renamed")

    def onProjectSelection(self):
        ui = ProjectInfoUi(self.project)
        ui.show()
        ui.exec_()

    def onSettings(self):
        self.settingsDialog.show()
        
    def onSave(self):
        logger = logging.getLogger(__name__)
        logger.info( "Saving config" )
        filename, _ = DataDirectory.DataDirectory().sequencefile("digitalLock-configuration.db")
        self.saveConfig()
        self.config.saveConfig(filename)
    
    def onMessageWrite(self,message,level=logging.DEBUG):
        if level>= self.loggingLevel:
            cursor = self.textEditConsole.textCursor()
            cursor.movePosition(QtGui.QTextCursor.End)
            if level < logging.ERROR:
                self.textEditConsole.setTextColor(QtCore.Qt.black)
            else:
                self.textEditConsole.setTextColor(QtCore.Qt.red)
            cursor.insertText(message)
            self.textEditConsole.setTextCursor(cursor)
            self.textEditConsole.ensureCursorVisible()

    def onClose(self):
        self.parent.close()
        
    def closeEvent(self, e):
        logger = logging.getLogger("")
        logger.debug( "Saving Configuration" )
        self.saveConfig()
        self.settingsDialog.done(0)
        self.lockControl.closeEvent(e)

    def initMenu(self):
        self.menuView.clear()
        for dock in self.dockWidgetList:
            self.menuView.addAction(dock.toggleViewAction())

    def saveConfig(self):
        self.config['MainWindow.State'] = self.parent.saveState()
        for tab in self.tabList:
            tab.saveConfig()
        self.config['Settings.deviceSerial'] = self.settings.deviceSerial
        self.config['Settings.deviceDescription'] = self.settings.deviceDescription
        self.config['MainWindow.pos'] = self.pos()
        self.config['MainWindow.size'] = self.size()
        self.config['Settings.loggingLevel'] = self.loggingLevel
        self.config['Settings.consoleMaximumLines'] = self.consoleMaximumLines
        self.config['PlotNames'] = list(self.plotDict.keys())
        self.config['pyqtgraph-dockareastate'] = self.area.saveState()
        self.settingsDialog.saveConfig()
        self.loggerUi.saveConfig()
        self.lockControl.saveConfig()
        self.lockStatus.saveConfig()
        self.traceControl.saveConfig()
Esempio n. 56
0
class AWGOptimizer(Form, Base):
    def __init__(self, deviceClass, config, parent=None):
        Base.__init__(self, parent)
        Form.__init__(self)
        Form.setupUi(self, self)
        self.config = config
        self.configname = "AWGOptimizer"
        self.setWindowTitle("AWG Optimizer")
        guiState = self.config.get(self.configname+".guiState")
        state = self.config.get(self.configname+'.state')
        pos = self.config.get(self.configname+'.pos')
        size = self.config.get(self.configname+'.size')
        isMaximized = self.config.get(self.configname+'.isMaximized')
        restoreGuiState(self, self.config.get(self.configname+".guiState"))
        if state: self.restoreState(state)
        if pos: self.move(pos)
        if size: self.resize(size)
        if isMaximized: self.showMaximized()

        self.show()
        self.awgUi = AWGUi(deviceClass, config, dict())
        self.awgUi.setupUi(self.awgUi)
        self.splitter.insertWidget(1, self.awgUi)

        #oscilloscope plot window
        name = "Oscilloscope Trace"
        self.scopeDock = Dock(name)
        self.scopePlot = CoordinatePlotWidget(self, name=name)
        self.scopeView = self.scopePlot._graphicsView
        self.scopeDock.addWidget(self.scopePlot)
        self.area = DockArea()
        self.area.addDock(self.scopeDock)
        self.plotDict ={name: {"dock":self.scopeDock, "widget":self.scopePlot, "view":self.scopeView}}
        self.verticalLayout.insertWidget(0, self.area)

        #trace ui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, self.configname, self.plotDict, hasMeasurementLog=False, highlightUnsaved=False)
        self.traceui.setupUi(self.traceui)
        traceDock = Dock("Traces")
        traceDock.addWidget(self.traceui)
        self.area.addDock(traceDock, 'left')
        self.device = self.awgUi.device

        self.measureWaveformButton.clicked.connect(self.onMeasureWaveform)
        self.optimizeButton.clicked.connect(self.onOptimize)

        dockAreaState = self.config.get(self.configname+'.dockAreaState')
        try:
            if dockAreaState: self.area.restoreState(dockAreaState)
        except Exception as e:
            print(e)

    def saveConfig(self):
        self.config[self.configname+".guiState"] = saveGuiState(self)
        self.config[self.configname+'.state'] = self.saveState()
        self.config[self.configname+'.pos'] = self.pos()
        self.config[self.configname+'.size'] = self.size()
        self.config[self.configname+'.isMaximized'] = self.isMaximized()
        self.config[self.configname+'.dockAreaState'] = self.area.saveState()
        self.awgUi.saveConfig()

    def closeEvent(self, e):
        self.saveConfig()

    def onMeasureWaveform(self):
        pass

    def onOptimize(self):
        pass
Esempio n. 57
0
    def __init__(self, stedlaser, slm, scanZ, scanXY, webcamFocusLock, aotf,
                 leicastand, *args, **kwargs):

        super().__init__(*args, **kwargs)

        # os.chdir('C:\\Users\\STEDred\Documents\TempestaSnapshots')

        self.slm = slm
        self.scanZ = scanZ
        self.aotf = aotf
        self.scanXY = scanXY
        self.dmi8 = leicastand
        self.imspector = sp.Imspector()

        self.filewarning = FileWarning()

        self.s = Q_(1, 's')
        self.lastTime = time.clock()
        self.fps = None

        # Actions in menubar
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')

        self.savePresetAction = QtGui.QAction('Save configuration...', self)
        self.savePresetAction.setShortcut('Ctrl+S')
        self.savePresetAction.setStatusTip('Save camera & recording settings')
        savePresetFunction = lambda: guitools.savePreset(self)
        self.savePresetAction.triggered.connect(savePresetFunction)
        fileMenu.addAction(self.savePresetAction)
        fileMenu.addSeparator()

        self.exportTiffAction = QtGui.QAction('Export HDF5 to Tiff...', self)
        self.exportTiffAction.setShortcut('Ctrl+E')
        self.exportTiffAction.setStatusTip('Export HDF5 file to Tiff format')
        self.exportTiffAction.triggered.connect(guitools.TiffConverterThread)
        fileMenu.addAction(self.exportTiffAction)

        self.exportlastAction = QtGui.QAction('Export last recording to Tiff',
                                              self)
        self.exportlastAction.setEnabled(False)
        self.exportlastAction.setShortcut('Ctrl+L')
        self.exportlastAction.setStatusTip('Export last recording to Tiff ' +
                                           'format')
        fileMenu.addAction(self.exportlastAction)
        fileMenu.addSeparator()

        exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(QtGui.QApplication.closeAllWindows)
        fileMenu.addAction(exitAction)

        # Potentially remove all this?
        self.presetsMenu = QtGui.QComboBox()
        self.presetDir = datapath
        if not (os.path.isdir(self.presetDir)):
            self.presetDir = os.path.join(os.getcwd(), 'control\\Presets')
        for preset in os.listdir(self.presetDir):
            self.presetsMenu.addItem(preset)
        self.loadPresetButton = QtGui.QPushButton('Load preset')
        loadPresetFunction = lambda: guitools.loadPreset(self)
        self.loadPresetButton.pressed.connect(loadPresetFunction)

        # Dock widget
        dockArea = DockArea()

        # Laser Widget
        laserDock = Dock("Laser Control", size=(400, 500))
        self.lasers = stedlaser
        self.laserWidgets = LaserWidget.LaserWidget(self.lasers, self.aotf)
        laserDock.addWidget(self.laserWidgets)
        dockArea.addDock(laserDock, 'right')

        # SLM widget
        slmDock = Dock("SLM", size=(400, 300))
        self.slmWidget = slmWidget.slmWidget(self.slm)
        slmDock.addWidget(self.slmWidget)
        dockArea.addDock(slmDock, "bottom", laserDock)

        # Widefield camera widget
        #widefieldDock = Dock("Widefield", size=(500, 500))
        #self.widefieldWidget = widefield.WidefieldWidget(webcamWidefield)
        #widefieldDock.addWidget(self.widefieldWidget)
        #dockArea.addDock(widefieldDock, "left")

        # Focus lock widget
        focusDock = Dock("Focus lock", size=(500, 500))
        self.focusWidget = focus.FocusWidget(self.scanZ, webcamFocusLock,
                                             self.imspector)
        focusDock.addWidget(self.focusWidget)
        #dockArea.addDock(focusDock, "below", widefieldDock)
        dockArea.addDock(focusDock, "left")

        # Timelapse widget
        timelapseDock = Dock("Timelapse", size=(500, 200))
        self.timelapseWidget = timelapse.TimelapseWidget(self.imspector)
        timelapseDock.addWidget(self.timelapseWidget)
        #dockArea.addDock(timelapseDock, "top", widefieldDock)
        dockArea.addDock(timelapseDock, "top", focusDock)

        # Objective mot_corr widget
        motcorrDock = Dock("Glycerol motCORR", size=(500, 200))
        self.MotcorrWidget = motcorr.MotcorrWidget(self.dmi8)
        motcorrDock.addWidget(self.MotcorrWidget)
        dockArea.addDock(motcorrDock, "below", timelapseDock)

        # XY-scanner tiling widget
        tilingDock = Dock("Tiling", size=(500, 200))
        self.tilingWidget = tiling.TilingWidget(self.scanXY, self.focusWidget,
                                                self.imspector)
        tilingDock.addWidget(self.tilingWidget)
        dockArea.addDock(tilingDock, "below", timelapseDock)

        self.setWindowTitle('Tempesta - RedSTED edition')
        self.cwidget = QtGui.QWidget()
        self.setCentralWidget(self.cwidget)

        # Widgets' layout
        layout = QtGui.QGridLayout()
        self.cwidget.setLayout(layout)
        #        layout.setColumnMinimumWidth(0, 100)
        #        layout.setColumnMinimumWidth(1, 350)
        #        layout.setColumnMinimumWidth(2, 150)
        #        layout.setColumnMinimumWidth(3, 200)
        #        layout.setRowMinimumHeight(0, 350)
        #        layout.setRowMinimumHeight(1, 350)
        #        layout.setRowMinimumHeight(2, 350)
        #        layout.setRowMinimumHeight(3, 30)
        layout.addWidget(dockArea, 0, 3, 5, 1)
class InstrumentLoggingUi(WidgetContainerBase, WidgetContainerForm):
    levelNameList = ["debug", "info", "warning", "error", "critical"]
    levelValueList = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL]
    plotConfigurationChanged = QtCore.pyqtSignal( object )
    def __init__(self, project, config):
        super(InstrumentLoggingUi, self).__init__()
        self.config = config
        self.project = project
        self.dockWidgetList = list()
        self.plotDict = dict()
        self.instrument = ""
        self.loggingLevel = config.get('Settings.loggingLevel', logging.INFO)
        self.consoleMaximumLines = config.get('Settings.consoleMaximumLinesNew', 100)
        self.consoleEnable = config.get('Settings.consoleEnable', False)
        self.printMenu = None
        if self.loggingLevel not in self.levelValueList: self.loggingLevel = logging.INFO
        
    def __enter__(self):
        return self
    
    def __exit__(self, excepttype, value, traceback):
        return False
    
    def setupUi(self, parent):
        super(InstrumentLoggingUi, self).setupUi(parent)
                
        self.dockWidgetConsole.hide()
        self.loggerUi = LoggerLevelsUi(self.config)
        self.loggerUi.setupUi(self.loggerUi)
        self.loggerDock = QtWidgets.QDockWidget("Logging")
        self.loggerDock.setWidget(self.loggerUi)
        self.loggerDock.setObjectName("_LoggerDock")
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.loggerDock)
        self.loggerDock.hide()

        logger = logging.getLogger()        
        self.toolBar.addWidget(ExceptionLogButton())
            
        # Setup Console Dockwidget
        self.levelComboBox.addItems(self.levelNameList)
        self.levelComboBox.currentIndexChanged[int].connect( self.setLoggingLevel )            
        self.levelComboBox.setCurrentIndex( self.levelValueList.index(self.loggingLevel) )
        self.consoleClearButton.clicked.connect( self.onClearConsole )
        self.linesSpinBox.valueChanged.connect( self.onConsoleMaximumLinesChanged )
        self.linesSpinBox.setValue( self.consoleMaximumLines )
        self.checkBoxEnableConsole.stateChanged.connect( self.onEnableConsole )
        self.checkBoxEnableConsole.setChecked( self.consoleEnable )

        self.parent = parent
        self.tabDict = SequenceDict()
               
        self.setupPlots()     
        
        self.preferencesUi = PreferencesUi(config, self)
        self.preferencesUi.setupUi(self.preferencesUi)
        self.preferencesUiDock = QtWidgets.QDockWidget("Print Preferences")
        self.preferencesUiDock.setWidget(self.preferencesUi)
        self.preferencesUiDock.setObjectName("_preferencesUi")
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.preferencesUiDock)

          
        # Traceui
        self.penicons = pens.penicons().penicons()
        self.traceui = Traceui.Traceui(self.penicons, self.config, "Main", self.plotDict)
        self.traceui.setupUi(self.traceui)
        setattr(self.traceui, 'autoSaveTraces', self.config.get('autoSaveTraces', False))
        self.traceui.autoSaveAction = QtWidgets.QAction('Autosave traces', self.traceui)
        self.traceui.autoSaveAction.setCheckable(True)
        self.traceui.autoSaveAction.setChecked(self.traceui.autoSaveTraces)
        self.traceui.autoSaveAction.triggered.connect(lambda checked: setattr(self.traceui, 'autoSaveTraces', checked))
        self.traceui.addAction(self.traceui.autoSaveAction)
        traceuiDock = self.setupAsDockWidget(self.traceui, "Traces", QtCore.Qt.LeftDockWidgetArea)

        # new fit widget
        self.fitWidget = FitUi(self.traceui, self.config, "Main")
        self.fitWidget.setupUi(self.fitWidget)
        self.fitWidgetDock = self.setupAsDockWidget(self.fitWidget, "Fit", QtCore.Qt.LeftDockWidgetArea, stackBelow=traceuiDock)

        self.instrumentLoggingHandler = InstrumentLoggingHandler(self.traceui, self.plotDict, self.config, 'externalInput')

        self.ExternalParametersSelectionUi = InstrumentLoggingSelection(self.config, classdict=LoggingInstruments, plotNames=list(self.plotDict.keys()),
                                                                        instrumentLoggingHandler=self.instrumentLoggingHandler )
        self.ExternalParametersSelectionUi.setupUi( self.ExternalParametersSelectionUi )
        self.ExternalParameterSelectionDock = QtWidgets.QDockWidget("Params Selection")
        self.ExternalParameterSelectionDock.setObjectName("_ExternalParameterSelectionDock")
        self.ExternalParameterSelectionDock.setWidget(self.ExternalParametersSelectionUi)
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.ExternalParameterSelectionDock)
        self.instrumentLoggingHandler.paramTreeChanged.connect( self.ExternalParametersSelectionUi.refreshParamTree)
        self.instrumentLoggingHandler.setInputChannels( self.ExternalParametersSelectionUi.inputChannels() )
        self.ExternalParametersSelectionUi.inputChannelsChanged.connect( self.instrumentLoggingHandler.setInputChannels )
    
        self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config)
        self.instrumentLoggingDisplay.setupUi( self.ExternalParametersSelectionUi.inputChannels(), self.instrumentLoggingDisplay )
        self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget("Params Reading")
        self.instrumentLoggingDisplayDock.setObjectName("_ExternalParameterDisplayDock")
        self.instrumentLoggingDisplayDock.setWidget(self.instrumentLoggingDisplay)
        self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.instrumentLoggingDisplayDock)
        self.ExternalParametersSelectionUi.inputChannelsChanged.connect( self.instrumentLoggingDisplay.setupParameters )
        self.instrumentLoggingHandler.newData.connect( self.instrumentLoggingDisplay.update )

        self.instrumentLoggingQueryUi = InstrumentLoggerQueryUi(self.config, self.traceui, self.plotDict )
        self.instrumentLoggingQueryUi.setupUi( self.instrumentLoggingQueryUi )
        self.instrumentLoggingQueryUiDock = self.setupAsDockWidget(self.instrumentLoggingQueryUi, "Query", QtCore.Qt.LeftDockWidgetArea)
    
        self.addPlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self)
        self.addPlot.setToolTip("Add new plot")
        self.addPlot.triggered.connect(self.onAddPlot)
        self.toolBar.addAction(self.addPlot)
        
        self.removePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self)
        self.removePlot.setToolTip("Remove a plot")
        self.removePlot.triggered.connect(self.onRemovePlot)
        self.toolBar.addAction(self.removePlot)

        self.renamePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self)
        self.renamePlot.setToolTip("Rename a plot")
        self.renamePlot.triggered.connect(self.onRenamePlot)
        self.toolBar.addAction(self.renamePlot)

        self.setWindowTitle( "Instrument Logger ({0})".format(self.project) )
        if 'MainWindow.State' in self.config:
            self.parent.restoreState(self.config['MainWindow.State'])
        try:
            if 'pyqtgraph-dockareastate' in self.config:
                self.area.restoreState(self.config['pyqtgraph-dockareastate'])
        except Exception as e:
            logger.error("Cannot restore dock state in experiment {0}. Exception occurred: ".format(self.experimentName) + str(e))
        self.initMenu()
        self.actionProject.triggered.connect( self.onProjectSelection)
        self.actionExit.triggered.connect(self.onClose)

    def onProjectSelection(self):
        ui = ProjectInfoUi(self.project)
        ui.show()
        ui.exec_()

    def onEnableConsole(self, state):
        self.consoleEnable = state==QtCore.Qt.Checked
                
    def onClearConsole(self):
        self.textEditConsole.clear()
        
    def onConsoleMaximumLinesChanged(self, maxlines):
        self.consoleMaximumLines = maxlines
        self.textEditConsole.document().setMaximumBlockCount(maxlines)

    def setLoggingLevel(self, index):
        self.loggingLevel = self.levelValueList[index]
                   
    def setupPlots(self):
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.plotDict = dict()
        # initialize all the plot windows we want
        plotNames = self.config.get( 'PlotNames', ['Scan'] )
        if len(plotNames)<1:
            plotNames.append('Scan')
        for name in plotNames:
            dock = Dock(name)
            widget = DateTimePlotWidget(self, name=name)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
        
    def setupAsDockWidget(self, widget, name, area=QtCore.Qt.RightDockWidgetArea, stackAbove=None, stackBelow=None ):
        dock = QtWidgets.QDockWidget(name)
        dock.setObjectName(name)
        dock.setWidget( widget )
        self.addDockWidget(area, dock )
        self.dockWidgetList.append( dock )
        if stackAbove is not None:
            self.tabifyDockWidget( stackAbove, dock )
        elif stackBelow is not None:
            self.tabifyDockWidget( dock, stackBelow )
        return dock           

    def onAddPlot(self):
        name, ok = QtWidgets.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ')
        if ok:
            name = str(name)
            dock = Dock(name)
            widget = DateTimePlotWidget(self)
            view = widget._graphicsView
            self.area.addDock(dock, "bottom")
            dock.addWidget(widget)
            self.plotDict[name] = {"dock":dock, "widget":widget, "view":view}
            self.plotConfigurationChanged.emit( self.plotDict )
            
    def onRemovePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", list(self.plotDict.keys()), editable=False)
            if ok:
                name = str(name)
                self.plotDict[name]["dock"].close()
                del self.plotDict[name]
                self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be removed")
                
    def onRenamePlot(self):
        logger = logging.getLogger(__name__)
        if len(self.plotDict) > 0:
            name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", list(self.plotDict.keys()), editable=False)
            if ok:
                newName, newOk = QtWidgets.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ')
                if newOk:
                    name = str(name)
                    newName = str(newName)
                    self.plotDict[name]["dock"].label.setText(str(newName))
                    self.plotDict[newName] = self.plotDict[name]
                    del self.plotDict[name]
                    self.plotConfigurationChanged.emit( self.plotDict )
        else:
            logger.info("There are no plots which can be renamed")

    def onSave(self):
        logger = logging.getLogger(__name__)
        logger.info( "Saving config" )
        filename, _ = DataDirectory.DataDirectory().sequencefile("InstrumentLogger-configuration.db")
        self.saveConfig()
        self.config.saveConfig(filename)
    
    def onClose(self):
        self.parent.close()
        
    def onMessageWrite(self,message,level=logging.DEBUG):
        if self.consoleEnable and level>= self.loggingLevel:
            cursor = self.textEditConsole.textCursor()
            cursor.movePosition(QtGui.QTextCursor.End)
            if level < logging.ERROR:
                self.textEditConsole.setTextColor(QtCore.Qt.black)
            else:
                self.textEditConsole.setTextColor(QtCore.Qt.red)
            cursor.insertText(message)
            self.textEditConsole.setTextCursor(cursor)
            self.textEditConsole.ensureCursorVisible()

    def closeEvent(self, e):
        logger = logging.getLogger(__name__)
        logger.info( "Close Event" )
        logger = logging.getLogger("")
        logger.debug( "Saving Configuration" )
        self.saveConfig()

    def saveConfig(self):
        self.config['MainWindow.State'] = self.parent.saveState()
        for tab in list(self.tabDict.values()):
            tab.saveConfig()
        self.config['MainWindow.pos'] = self.pos()
        self.config['MainWindow.size'] = self.size()
        self.config['PlotNames'] = list(self.plotDict.keys())
        self.config['pyqtgraph-dockareastate'] = self.area.saveState()
        self.config['Settings.loggingLevel'] = self.loggingLevel
        self.config['Settings.consoleMaximumLinesNew'] = self.consoleMaximumLines
        self.config['Settings.consoleEnable'] = self.consoleEnable
        self.config['autoSaveTraces'] = self.traceui.autoSaveTraces
        self.ExternalParametersSelectionUi.saveConfig()
        self.instrumentLoggingHandler.saveConfig()
        self.instrumentLoggingQueryUi.saveConfig()
        self.preferencesUi.saveConfig()

    def onPrint(self, target):
        printer = QtPrintSupport.QPrinter(mode=QtPrintSupport.QPrinter.ScreenResolution)
        if self.preferencesUi.preferences().printPreferences.doPrint:
            dialog = QtPrintSupport.QPrintDialog(printer, self)
            dialog.setWindowTitle("Print Document")
            if dialog.exec_() != QtWidgets.QDialog.Accepted:
                return;    
        printer.setResolution(self.preferencesUi.preferences().printPreferences.printResolution)

        pdfPrinter = QtPrintSupport.QPrinter()
        pdfPrinter.setOutputFormat(QtPrintSupport.QPrinter.PdfFormat);
        pdfPrinter.setOutputFileName(DataDirectory.DataDirectory().sequencefile(target+".pdf")[0])
        self.doPrint(target, printer, pdfPrinter, self.preferencesUi.preferences().printPreferences)

    def doPrint(self, target, printer, pdfPrinter, preferences):
        widget = self.plotDict[target]['widget']
        if preferences.savePdf:
            with SceneToPrint(widget):
                painter = QtGui.QPainter(pdfPrinter)
                widget.render( painter )
                del painter
        
        # create an exporter instance, as an argument give it
        # the item you wish to export
        with SceneToPrint(widget, preferences.gridLinewidth, preferences.curveLinewidth):
            exporter = ImageExporter(widget._graphicsView.scene()) 
      
            # set export parameters if needed
            pageWidth = printer.pageRect().width()
            pageHeight = printer.pageRect().height()
            exporter.parameters()['width'] = pageWidth*preferences.printWidth   # (note this also affects height parameter)
              
            # save to file
            png = exporter.export(toBytes=True)
            if preferences.savePng:
                png.save(DataDirectory.DataDirectory().sequencefile(target+".png")[0])
            
            if preferences.doPrint:
                painter = QtGui.QPainter( printer )
                painter.drawImage(QtCore.QPoint(pageWidth*preferences.printX, pageHeight*preferences.printY), png)

    def initMenu(self):
        """Initialize print menu and view menu"""
        #View menu
        self.menuView.clear()
        dockList = self.findChildren(QtWidgets.QDockWidget)
        for dock in dockList:
            self.menuView.addAction(dock.toggleViewAction())

        # Print menu
        if self.printMenu is not None:
            self.printMenu.clear()
        else:
            self.printMenu = self.menuFile.addMenu("Print")
        for plot in list(self.plotDict.keys()):
            action = self.printMenu.addAction( plot )
            action.triggered.connect( partial(self.onPrint, plot ))