Example #1
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()
Example #2
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()
Example #3
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])
Example #4
0
class MainWindow(QtGui.QMainWindow):
    # for dock
    def __init__(self, parent=None):

        from pyqtgraph import exporters
        exporters.Exporter.register = self.modified_register

        QtGui.QMainWindow.__init__(self, parent)

        self.setWindowIcon(QtGui.QIcon(logo))
        self.setWindowTitle('CIVET')

        self.setGeometry(200, 143, 1574, 740)
        pg.setConfigOption('background', QtGui.QColor(215, 214, 213, 255))
        pg.setConfigOption('foreground', 'k')
        palette = QtGui.QPalette()
        palette.setColor(QtGui.QPalette.Background,
                         QtGui.QColor(215, 214, 213, 255))
        self.setPalette(palette)

        self.mainframe = QtGui.QFrame()

        self.copen = 0
        self.sopen = 0
        self.ropen = 0
        self.gridstate = 0
        self.current_docks = []

        self.loadaction = QtGui.QAction("&Open", self)
        self.loadaction.setShortcut("Ctrl+O")
        self.loadaction.setStatusTip("Open File")
        self.loadaction.triggered.connect(self.loaddata)

        self.exportaction = QtGui.QAction("&Export", self)
        self.exportaction.setShortcut("Ctrl+E")
        self.exportaction.setStatusTip("Export to a folder")
        self.exportaction.triggered.connect(self.exportdata)

        self.viewaction1 = QtGui.QAction("&Grid View 1", self)
        self.viewaction1.setStatusTip("Grid View 1")
        self.viewaction1.triggered.connect(self.grid_view_1)

        self.viewaction2 = QtGui.QAction("&Grid View 2", self)
        self.viewaction2.setStatusTip("Grid View 2")
        self.viewaction2.triggered.connect(self.grid_view_2)

        self.about = QtGui.QAction("&Info", self)
        self.about.setStatusTip("Info")
        self.about.triggered.connect(self.about_info)

        self.mainMenu = self.menuBar()
        self.fileMenu = self.mainMenu.addMenu("&File")
        self.fileMenu.addAction(self.loadaction)
        self.fileMenu.addAction(self.exportaction)

        self.viewMenu = self.mainMenu.addMenu("&Display")
        self.viewMenu.addAction(self.viewaction1)
        self.viewMenu.addAction(self.viewaction2)

        self.aboutMenu = self.mainMenu.addMenu("&About")
        self.aboutMenu.addAction(self.about)

        self.maketoolbar()

        self.area = DockArea()

        self.drho = Dock("\u03c1")
        self.dlamb = Dock("\u03bb")
        self.dalpha = Dock("\u03b1")
        self.dbeta = Dock("\u03b2")
        self.dphase = Dock("Phase")
        self.dcontrols = Dock("Controls")

        self.layout = QtGui.QHBoxLayout()
        self.layout.addWidget(self.area)
        self.mainframe.setLayout(self.layout)
        self.mainframe.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Raised)
        self.mainframe.setLineWidth(8)

# all those have different relative positions so made bunch of functions, not one.

    def modified_register(self, cls):

        exporters.Exporter.Exporters.append(None)

    def dlambadd(self):
        try:
            self.area.addDock(self.dlamb, 'bottom', self.drho)
        except:
            try:
                self.area.addDock(self.dlamb, 'left', self.dphase)
            except:
                self.area.addDock(self.dlamb, 'left')

    def drhoadd(self):
        try:
            self.area.addDock(self.drho, 'top', self.dlamb)
        except:
            try:
                self.area.addDock(self.drho, 'left', self.dalpha)
            except:
                self.area.addDock(self.drho, 'left')

    def dalphaadd(self):
        try:
            self.area.addDock(self.dalpha, 'left', self.dbeta)
        except:
            try:
                self.area.addDock(self.dalpha, 'right', self.drho)
            except:
                try:
                    self.area.addDock(self.dalpha, 'top', self.dphase)
                except:
                    self.area.addDock(self.dalpha, 'left')

    def dbetaadd(self):
        try:
            self.area.addDock(self.dbeta, 'top', self.dcontrols)
        except:
            try:
                self.area.addDock(self.dbeta, 'right', self.dalpha)
            except:
                self.area.addDock(self.dbeta, 'right')

    def dphaseadd(self):
        try:
            self.area.addDock(self.dphase, 'left', self.dcontrols)
        except:
            try:
                self.area.addDock(self.dphase, 'bottom', self.dalpha)
            except:
                try:
                    self.area.addDock(self.dphase, 'right', self.dlamb)
                except:
                    self.area.addDock(self.drho, 'bottom')

    def dcontrolsadd(self):
        try:
            self.area.addDock(self.dcontrols, 'right', self.dphase)
        except:
            try:
                self.area.addDock(self.dcontrols, 'bottom', self.dbeta)
            except:
                self.area.addDock(self.dcontrols, 'right')

    def checkbox_init(self):
        self.dock_on = []

        self.cwindow = QtGui.QMainWindow()
        self.cwindow.setWindowIcon(QtGui.QIcon(logo))
        self.cwindow.setWindowTitle('Plots')

        self.boxeswidget = QtGui.QWidget(self.cwindow)
        checkbox_layout = QtGui.QGridLayout(self.boxeswidget)
        self.ch_lamb = QtGui.QCheckBox(self.boxeswidget)
        self.ch_lamb.setText('\u03bb')
        self.ch_lamb.setChecked(True)
        self.ch_lamb.stateChanged.connect(lambda: self.dlamb.close(
        ) if not self.ch_lamb.isChecked() else self.dlambadd())

        self.ch_rho = QtGui.QCheckBox(self.boxeswidget)
        self.ch_rho.setText('\u03c1')
        self.ch_rho.setChecked(True)
        self.ch_rho.stateChanged.connect(lambda: self.drho.close(
        ) if not self.ch_rho.isChecked() else self.drhoadd())

        self.ch_alpha = QtGui.QCheckBox(self.boxeswidget)
        self.ch_alpha.setText('\u03b1')
        self.ch_alpha.setChecked(True)
        self.ch_alpha.stateChanged.connect(lambda: self.dalpha.close(
        ) if not self.ch_alpha.isChecked() else self.dalphaadd())

        self.ch_beta = QtGui.QCheckBox(self.boxeswidget)
        self.ch_beta.setText('\u03b2')
        self.ch_beta.setChecked(True)
        self.ch_beta.stateChanged.connect(lambda: self.dbeta.close(
        ) if not self.ch_beta.isChecked() else self.dbetaadd())

        self.ch_phase = QtGui.QCheckBox(self.boxeswidget)
        self.ch_phase.setText('Phase')
        self.ch_phase.setChecked(True)
        self.ch_phase.stateChanged.connect(lambda: self.dphase.close(
        ) if not self.ch_phase.isChecked() else self.dphaseadd())

        self.ch_controls = QtGui.QCheckBox(self.boxeswidget)
        self.ch_controls.setText('Controls')
        self.ch_controls.setChecked(True)
        self.ch_controls.stateChanged.connect(lambda: self.dcontrols.close(
        ) if not self.ch_controls.isChecked() else self.dcontrolsadd())

        checkbox_layout.addWidget(self.ch_rho, 0, 0, 1, 1)
        checkbox_layout.addWidget(self.ch_lamb, 1, 0, 1, 1)
        checkbox_layout.addWidget(self.ch_alpha, 0, 1, 1, 1)
        checkbox_layout.addWidget(self.ch_phase, 1, 1, 1, 1)
        checkbox_layout.addWidget(self.ch_beta, 0, 2, 1, 1)
        checkbox_layout.addWidget(self.ch_controls, 1, 2, 1, 1)
        self.cwindow.setCentralWidget(self.boxeswidget)

    def checkbox(self):
        if self.copen == 0:
            self.check_current_docks()
            self.closed_docks = []

            for i in self.docklist:
                if i not in self.current_docks:
                    self.closed_docks += [i]
            for i in self.closed_docks:
                eval(i[:5] + "ch_" + i[6:]).setChecked(False)

            self.cwindow.show()
            self.copen = 1
        else:
            self.cwindow.hide()
            self.copen = 0

    def about_info(self):

        self.awindow = QtGui.QMainWindow()
        self.awindow.setWindowIcon(QtGui.QIcon(logo))
        self.awindow.setWindowTitle('About')
        labels = QtGui.QWidget(self.awindow)
        labels_layout = QtGui.QVBoxLayout(labels)
        self.line0 = QtGui.QLabel()
        self.line1 = QtGui.QLabel(
            "CIVET: Current Inspired Visualization and Evaluation of the")
        self.line2 = QtGui.QLabel()
        self.line3 = QtGui.QLabel(
            "Totally asymmetric simple exclusion process (TASEP)")
        self.line4 = QtGui.QLabel()
        self.line5 = QtGui.QLabel("Copyright (c) 2018,")
        self.line6 = QtGui.QLabel()
        self.line7 = QtGui.QLabel(
            "Wonjun Son, Dan D. Erdmann-Pham,  Khanh Dao Duc, Yun S. Song")
        self.line8 = QtGui.QLabel()
        self.line9 = QtGui.QLabel("All rights reserved.")
        self.line10 = QtGui.QLabel()

        for i in range(11):
            eval("self.line" + str(i)).setAlignment(QtCore.Qt.AlignCenter)
            labels_layout.addWidget(eval("self.line" + str(i)))
        self.awindow.setCentralWidget(labels)
        self.awindow.show()

    def exportdata(self):

        self.dialog = QtGui.QFileDialog()
        self.dialog.setOption(QtGui.QFileDialog.ShowDirsOnly)
        self.dialog.setFileMode(QtGui.QFileDialog.DirectoryOnly)

        folder_name = self.dialog.getSaveFileName(self, "Save Directory")
        filepath = os.path.join(os.path.abspath(os.sep), folder_name)
        if not os.path.exists(filepath):
            makedirs(filepath)

        # arr = QtCore.QByteArray()
        # buf = QtCore.QBuffer(arr)
        # svg = QtSvg.QSvgGenerator()
        # svg.setOutputDevice(buf)
        # dpi = QtGui.QDesktopWidget().physicalDpiX()
        # svg.setResolution(dpi)

        svg = QtSvg.QSvgGenerator()
        svg.setFileName("hh")
        svg.setSize(QtCore.QSize(2000, 2000))
        svg.setViewBox(self.rect())
        svg.setTitle("SVG svg Example Drawing")
        svg.setDescription("An SVG drawing created by the SVG Generator ")

        p = QtGui.QPainter()
        p.begin(svg)
        try:
            self.render(p)
        finally:
            p.end()
        # gen.setViewBox(QtGui.QRect(0, 0, 200, 200));
        # gen.setTitle(tr("SVG Gen Example Drawing"));
        # gen.setDescription(tr("An SVG drawing created by the SVG Generator ""Example provided with Qt."));

        lambda_data = os.path.join(filepath, "Lambda_data.csv")
        with open(lambda_data, "w") as output:
            try:
                writer = csv.writer(output, lineterminator='\n')
                for val in np.array(glo_var.lambdas)[:, 1]:
                    writer.writerow([val])
            except:
                pass

        summary = os.path.join(filepath, "Summary.csv")
        with open(summary, "w") as output:
            try:
                writer = csv.writer(output,
                                    delimiter='\t',
                                    lineterminator='\n')
                writer.writerow(["alpha", glo_var.alpha])
                writer.writerow(["beta", glo_var.beta])
                writer.writerow(["l", glo_var.l])
                writer.writerow(["Phase", self.phas.pointer.region_aft])
            except:
                pass

        # for name, pitem in self.pltlist:
        # 	self.exportimg(pitem,os.path.join(filepath,name + ".svg"))
        # 	# self.exportimg(pitem,os.path.join(filepath,name + ".png"))

        currentanddensity = os.path.join(filepath, "Current & Density.csv")
        with open(currentanddensity, "w") as output:
            writer = csv.writer(output, delimiter='\t', lineterminator='\n')
            # combine alpha, beta    pre and post. Do it here to lessen the computation
            alpha_x_data = np.concatenate([
                np.array(self.jalph.alphas_pre),
                np.linspace(self.jalph.trans_point, 1, 2)
            ])
            alpha_j_data = np.concatenate(
                [self.jalph.j_l_values,
                 np.array([self.jalph.jpost] * 2)])
            alpha_rho_data = np.array(self.jalph.rho_avg_pre +
                                      self.jalph.rho_avg_post)

            beta_x_data = np.concatenate([
                np.array(self.jbet.betas_pre),
                np.linspace(self.jbet.trans_point, 1, 2)
            ])
            beta_j_data = np.concatenate(
                [self.jbet.j_r_values,
                 np.array([self.jbet.jpost] * 2)])
            beta_rho_data = np.array(self.jbet.rho_avg_pre +
                                     self.jbet.rho_avg_post)

            alpha_data = np.vstack(
                [alpha_x_data, alpha_j_data, alpha_rho_data])
            beta_data = np.vstack([beta_x_data, beta_j_data, beta_rho_data])

            writer.writerow([
                "alpha", "Current", "Average Density", '\t', '\t', "beta",
                "Current", "Average Density"
            ])
            for i in range(len(alpha_x_data)):
                writer.writerow(
                    list(alpha_data[:, i]) + [''] * 2 + list(beta_data[:, i]))
            writer.writerow('\n')
            writer.writerow(
                ['beta', glo_var.beta, '', '', '', 'alpha', glo_var.alpha, ''])
            writer.writerow([
                'transition point', self.jalph.trans_point, '', '', '',
                'transition point', self.jbet.trans_point, ''
            ])

        self.pdfgroup1 = ['Lambda_fig', 'Density_fig']
        self.pdfgroup2 = ['Current_alpha_fig', 'Current_beta_fig']

        for name, pitem in self.pltlist:
            # self.exportimg(pitem,os.path.join(filepath,name + ".png"))
            path = os.path.join(filepath, name + ".svg")
            #			if name == 'Current_alpha_fig':
            #				self.jalph.p3.setLabel('right',"\u2329\u03c1 \u232a",**glo_var.labelstyle)
            #				self.jalph.p3main.plotItem.legend.items=[]
            #				self.jalph.p3.plot(pen=self.jalph.jpen, name='J')
            #				self.jalph.p3.plot(pen=self.jalph.rho_dash, name='\u2329\u03c1 \u232a')

            #			elif name == 'Current_beta_fig':
            #				self.jbet.p4.setLabel('right',"\u2329\u03c1 \u232a",**glo_var.labelstyle)
            #				self.jbet.p4main.plotItem.legend.items=[]
            #				self.jbet.p4.plot(pen=self.jbet.jpen, name='J')
            #				self.jbet.p4.plot(pen=self.jbet.rho_dash, name='\u2329\u03c1 \u232a')
            self.exportimg(pitem, path)

            if name in self.pdfgroup1:
                self.makepdf(path, os.path.join(filepath, name + ".pdf"), 500,
                             260, 20, 240)
            elif name == 'Current_alpha_fig':
                self.makepdf(path, os.path.join(filepath, name + ".pdf"), 350,
                             280, 30, 230)
#				self.jalph.p3.setLabel('right',"\u2329 \u03c1 \u232a",**glo_var.labelstyle)
#				self.jalph.p3main.plotItem.legend.items=[]
#				self.jalph.p3.plot(pen=self.jalph.jpen, name='J')
#				self.jalph.p3.plot(pen=self.jalph.rho_dash, name='\u2329 \u03c1 \u232a')
            elif name == 'Current_beta_fig':
                self.makepdf(path, os.path.join(filepath, name + ".pdf"), 350,
                             280, 30, 230)


#				self.jbet.p4.setLabel('right',"\u2329 \u03c1 \u232a",**glo_var.labelstyle)
#				self.jbet.p4main.plotItem.legend.items=[]
#				self.jbet.p4.plot(pen=self.jbet.jpen, name='J')
#				self.jbet.p4.plot(pen=self.jbet.rho_dash, name='\u2329 \u03c1 \u232a')

            else:
                self.makepdf(path, os.path.join(filepath, name + ".pdf"), 410,
                             330, 10, 300)

            os.remove(path)

    def makepdf(self, path, name, x, y, z, q):

        from svglib.svglib import svg2rlg
        from reportlab.pdfgen import canvas
        from reportlab.graphics import renderPDF
        rlg = svg2rlg(path)
        rlg.scale(0.8, 0.8)
        c = canvas.Canvas(name)
        c.setPageSize((x, y))
        renderPDF.draw(rlg, c, z, q)
        c.showPage()
        c.save()

    def exportimg(self, img, path):
        # self.img = pg.exporters.ImageExporter(img)
        # self.img.export(path)
        self.svg = pg.exporters.SVGExporter(img)
        self.svg.export(fileName=path)

    def maketoolbar(self):
        self.state = None
        self.titlebarstate = 1
        self.toolbar = self.addToolBar("Toolbar")

        home = QtGui.QAction(
            QtGui.QIcon(QtGui.QApplication.style().standardIcon(
                QtGui.QStyle.SP_ComputerIcon)), 'Toggle Grid View', self)
        home.triggered.connect(self.toggle_grid_view)
        self.toolbar.addAction(home)

        fix = QtGui.QAction(
            QtGui.QIcon(QtGui.QApplication.style().standardIcon(
                QtGui.QStyle.SP_ArrowDown)), 'Fix current layout', self)
        fix.triggered.connect(self.fixdock)
        self.toolbar.addAction(fix)

        self.savedockandvaluesinit()
        save = QtGui.QAction(
            QtGui.QIcon(QtGui.QApplication.style().standardIcon(
                QtGui.QStyle.SP_FileDialogListView)), 'Save current layout',
            self)
        save.triggered.connect(self.popsavedockandvalues)
        self.toolbar.addAction(save)

        self.restoredockandvaluesinit()
        restore = QtGui.QAction(
            QtGui.QIcon(QtGui.QApplication.style().standardIcon(
                QtGui.QStyle.SP_BrowserReload)), 'Restore saved layout', self)
        restore.triggered.connect(self.poprestoredockandvalues)
        self.toolbar.addAction(restore)

        self.checkbox_init()
        checkbox = QtGui.QAction(
            QtGui.QIcon(QtGui.QApplication.style().standardIcon(
                QtGui.QStyle.SP_FileDialogDetailedView)),
            'Open & close specific windows', self)
        checkbox.triggered.connect(self.checkbox)
        self.toolbar.addAction(checkbox)

    def fixdock(self):
        if self.titlebarstate == 1:
            self.dlamb.hideTitleBar()
            self.drho.hideTitleBar()
            self.dalpha.hideTitleBar()
            self.dbeta.hideTitleBar()
            self.dcontrols.hideTitleBar()
            self.dphase.hideTitleBar()
            self.titlebarstate = 0

        else:
            self.dlamb.showTitleBar()
            self.drho.showTitleBar()
            self.dalpha.showTitleBar()
            self.dbeta.showTitleBar()
            self.dcontrols.showTitleBar()
            self.dphase.showTitleBar()
            self.titlebarstate = 1

    def savedockandvaluesinit(self):

        self.swindow = QtGui.QMainWindow()
        self.swindow.setWindowIcon(QtGui.QIcon(logo))
        self.swindow.setWindowTitle('Save')

        boxeswidget = QtGui.QWidget(self.swindow)
        checkbox_layout = QtGui.QGridLayout(boxeswidget)

        self.sa_dock = QtGui.QCheckBox(boxeswidget)
        self.sa_dock.setText('Grid View')
        self.sa_dock.setChecked(True)

        self.sa_values = QtGui.QCheckBox(boxeswidget)
        self.sa_values.setText('Values')
        self.sa_values.setChecked(True)

        self.save_button = QtGui.QPushButton('Save', self)
        self.save_button.clicked.connect(self.savedockandvalues)

        checkbox_layout.addWidget(self.sa_dock, 0, 0, 1, 1)
        checkbox_layout.addWidget(self.sa_values, 0, 1, 1, 1)
        checkbox_layout.addWidget(self.save_button, 1, 0, 1, 2)

        self.swindow.setCentralWidget(boxeswidget)

    def restoredockandvaluesinit(self):

        self.rwindow = QtGui.QMainWindow()
        self.rwindow.setWindowIcon(QtGui.QIcon(logo))
        self.rwindow.setWindowTitle('Restore')

        boxeswidget = QtGui.QWidget(self.rwindow)
        checkbox_layout = QtGui.QGridLayout(boxeswidget)

        self.re_dock = QtGui.QCheckBox(boxeswidget)
        self.re_dock.setText('Grid View')
        self.re_dock.setChecked(True)

        self.re_values = QtGui.QCheckBox(boxeswidget)
        self.re_values.setText('Values')
        self.re_values.setChecked(True)

        self.restore_button = QtGui.QPushButton('Restore', self)
        self.restore_button.clicked.connect(self.restoredockandvalues)

        checkbox_layout.addWidget(self.re_dock, 0, 0, 1, 1)
        checkbox_layout.addWidget(self.re_values, 0, 1, 1, 1)
        checkbox_layout.addWidget(self.restore_button, 1, 0, 1, 2)

        self.rwindow.setCentralWidget(boxeswidget)

    def savedockandvalues(self):
        if self.sa_values.checkState:
            self.savedlambdas = deepcopy(glo_var.lambdas)
            self.savedalpha = glo_var.alpha
            self.savedbeta = glo_var.beta
            self.savedl = glo_var.l
        if self.sa_dock.checkState:
            self.saved_state = []
            self.state = self.area.saveState()
            self.saved_state = self.check_current_docks()[:]

        self.sopen = 0
        self.swindow.hide()

    def popsavedockandvalues(self):
        if self.sopen == 0:
            self.swindow.show()
            self.sopen = 1

        else:
            self.swindow.hide()
            self.sopen = 0

    def poprestoredockandvalues(self):
        if self.ropen == 0:
            self.rwindow.show()
            self.ropen = 1

        else:
            self.rwindow.hide()
            self.ropen = 0

    def restoredockandvalues(self):
        if self.re_values.checkState:
            glo_var.lambdas = deepcopy(self.savedlambdas)
            glo_var.alpha = self.savedalpha
            glo_var.beta = self.savedbeta
            glo_var.l = self.savedl

            self.lamb_po.update()
            self.rh.update()
            self.phas.update()
            self.jalph.update()
            self.jbet.update()
            self.slid.update_alpha_slid(self.slid.ws[0])
            self.slid.update_beta_slid(self.slid.ws[1])
            self.slid.update_l_slid(self.slid.ws[2])

        if self.re_dock.checkState:

            if self.state != None:
                closed_docks = []
                self.check_current_docks()
                # Notice after below, current dock != real current dock. But it doesn't matter since we call check current dock every time.
                for i in self.current_docks:
                    if i not in self.saved_state:
                        eval(i).close()
                for i in self.saved_state:
                    if i not in self.current_docks:
                        eval(i + "add")()
                self.area.restoreState(self.state)
        self.ropen = 0
        self.rwindow.hide()

    def realinit(self):
        self.clear_buttons = [
            "self.lamb_po.p1main.coordinate_label.setText(\"\")",
            "self.rh.p2main.coordinate_label.setText(\"\")",
            "self.jalph.p3main.coordinate_label.setText(\"\")",
            "self.jbet.p4main.coordinate_label.setText(\"\")",
            "self.phas.p5main.coordinate_label.setText(\"\")"
        ]

        glo_var.pass_main(self)

        self.docklist = [
            'self.drho', 'self.dlamb', 'self.dalpha', 'self.dbeta',
            'self.dphase', 'self.dcontrols'
        ]
        self.area = DockArea()
        self.drho = Dock("Particle Density \u2374", closable=True)
        self.dlamb = Dock("Hopping Rate \u03bb", closable=True)
        self.dphase = Dock("Phase Diagram", closable=True)
        self.dcontrols = Dock("Controls", closable=True)
        self.dalpha = Dock(
            "Current J and average density \u27e8\u2374\u27e9 as a function of \u03b1",
            closable=True)
        self.dbeta = Dock(
            "Current J and average density \u27e8\u2374\u27e9 as a function of \u03b2",
            closable=True)

        self.layout = QtGui.QHBoxLayout()
        self.layout.addWidget(self.area)
        self.mainframe.setLayout(self.layout)
        self.mainframe.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Raised)
        self.mainframe.setLineWidth(8)

        pg.setConfigOptions(antialias=True)

        self.rh = rho.rho(self.drho)
        self.jalph = jalpha.jalpha(self.dalpha, self.rh)
        self.jbet = jbeta.jbeta(self.dbeta, self.rh)
        self.phas = phase.phase(self.dphase)
        self.lamb_po = lamb_pol.lamb_pol(self.dlamb)
        self.slid = slider.Widget(self.dcontrols, self.lamb_po, self.phas,
                                  self.rh, self.jbet, self.jalph)
        self.lamb_po.receive(self.slid)

        # default values to restore is input
        self.savedlambdas = glo_var.lambdas[:]
        self.savedalpha = glo_var.alpha
        self.savedbeta = glo_var.beta
        self.savedl = glo_var.l

        self.pltlist = [['Lambda_fig', self.lamb_po.p1],
                        ['Density_fig', self.rh.p2],
                        ['Current_alpha_fig', self.jalph.plotitemtoexport],
                        ['Current_beta_fig', self.jbet.plotitemtoexport],
                        ['Phase_fig', self.phas.p5]]

        self.grid_view_1()

        self.setCentralWidget(self.area)

        print(dir(self.area))
        print(self.area.childrenRect(), "childrenRect")
        print(self.area.contentsRect(), "contentesRect")
        print(self.area.rect())

    def check_current_docks(self):
        self.current_docks = []
        for i in self.docklist:
            if self.area.getContainer(eval(i)):
                self.current_docks += [i]
            else:
                pass
        return self.current_docks

    def toggle_grid_view(self):
        if self.gridstate == 0:
            self.grid_view_2()
            self.gridstate = 1
        else:
            self.grid_view_1()
            self.gridstate = 0

    def grid_view_1(self):
        for i in self.docklist:
            try:
                eval(i).close()
            except:
                pass

        self.drho.setMinimumSize(652, 370)
        self.dlamb.setMinimumSize(652, 370)
        self.dphase.setMinimumSize(487, 465)
        self.dcontrols.setMinimumSize(487, 275)
        self.dalpha.setMinimumSize(435, 370)
        self.dbeta.setMinimumSize(435, 370)

        self.area.addDock(self.drho, 'left')
        self.area.addDock(self.dlamb, 'bottom', self.drho)
        self.area.addDock(self.dphase, 'right')
        self.area.addDock(self.dcontrols, 'bottom', self.dphase)
        self.area.addDock(self.dalpha, 'right')
        self.area.addDock(self.dbeta, 'bottom', self.dalpha)

        self.drho.setMinimumSize(0, 0)
        self.dlamb.setMinimumSize(0, 0)
        self.dphase.setMinimumSize(0, 0)
        self.dcontrols.setMinimumSize(0, 0)
        self.dalpha.setMinimumSize(0, 0)
        self.dbeta.setMinimumSize(0, 0)

    def grid_view_2(self):
        for i in self.docklist:
            try:
                eval(i).close()
            except:
                pass
        self.area.addDock(self.drho, 'top')
        self.area.addDock(self.dlamb, 'bottom', self.drho)
        self.area.addDock(self.dphase, 'bottom')
        self.area.addDock(self.dcontrols, 'left', self.dphase)
        self.area.addDock(self.dalpha, 'right')
        self.area.addDock(self.dbeta, 'bottom', self.dalpha)

    def opengraphs(self):
        self.mn = main.main_class(app)
        self.window.hide()

    def loaddata(self):
        name = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.',
                                                 'text (*.txt *.csv)')
        if name == "":
            pass
        else:
            self.read_file(name)
            self.realinit()

    def read_file(self, input):
        global ison
        temp = []
        if ison == 0:
            ison = 1
        else:
            self.setCentralWidget(None)
            glo_var.initialize()

        if input[-3:] == 'csv':
            with open(input, newline='') as csvfile:
                spamreader = csv.reader(csvfile, delimiter=',', quotechar='|')
                lis = []
                for j in spamreader:
                    lis += j
                num_of_inputs = len(lis)
                glo_var.lambdas_degree = num_of_inputs
                for i in range(num_of_inputs):
                    glo_var.lambdas += [[
                        i / (num_of_inputs - 1),
                        round(eval(lis[i]), 2)
                    ]]
            glo_var.alpha = 0.04
            glo_var.beta = 0.04
            glo_var.l = 1

        elif input[-3:] == 'txt':
            f = open(input, 'r')
            # Breaks the loop i
            try:
                temp = []
                while (True):
                    T = f.readline().strip()
                    temp += [[glo_var.lambdas_degree, round(eval(T), 2)]]
            except:
                for x, y in temp:
                    glo_var.lambdas += [[x / (glo_var.lambdas_degree - 1), y]]
            glo_var.l = 1

        else:
            err = QtGui.QMessageBox(self.win)
            err.setIcon(QMessageBox().Warning)
            err.setText("Please select txt or csv file Format")
            err.setWindowTitle("File Format Error")
            err.setStandardButtons(QMessageBox.Ok)
            err.buttonClicked.connect()

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseMove:
            if event.buttons() == QtCore.Qt.NoButton:
                pos = event.pos()
                if self.toolbar.rect().contains(
                        pos) or not self.area.rect().contains(pos):
                    self.clear_points()
            else:
                pass
        return QtGui.QMainWindow.eventFilter(self, source, event)

    def clear_points(self, exclude=None):
        if not exclude:
            for x in self.clear_buttons:
                eval(x)
        else:
            for x in self.clear_buttons[:exclude -
                                        1] + self.clear_buttons[exclude:]:
                eval(x)
Example #5
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()
Example #6
0
class MainWindow(QMainWindow):
    """
    Main control window for showing the live captured images and initiating special tasks
    """
    def __init__(self, experiment):
        """
        Inits the camera window

        :param experiment: Experiment that is controlled by the GUI
        """
        super().__init__()
        self.setWindowTitle('PyNTA: Python Nanoparticle Tracking Analysis')
        self.setMouseTracking(True)
        self.experiment = experiment
        self.area = DockArea()
        self.setCentralWidget(self.area)
        self.resize(1064, 840)
        self.area.setMouseTracking(True)

        # Main widget
        self.camWidget = MonitorMainWidget()
        self.camWidget.setup_cross_cut(self.experiment.max_height)
        self.camWidget.setup_cross_hair(
            [self.experiment.max_width, self.experiment.max_height])
        self.camWidget.setup_roi_lines(
            [self.experiment.max_width, self.experiment.max_height])
        self.camWidget.setup_mouse_tracking()

        self.messageWidget = messageWidget()

        self.cheatSheet = popOutWindow()

        self.dmainImage = Dock("Camera",
                               size=(80, 35))  # sizes are in percentage
        self.dmainImage.addWidget(self.camWidget)
        self.area.addDock(self.dmainImage, 'right')
        self.dmessage = Dock("Messages", size=(40, 30))
        self.dmessage.addWidget(self.messageWidget)
        self.area.addDock(self.dmessage, 'right')

        # # Widget for displaying information to the user

        # # Small window to display the results of the special task
        # self.trajectoryWidget = trajectoryWidget()
        # # Window for the camera viewer
        # # self.camViewer = cameraViewer(self._session, self.camera, parent=self)
        # # Configuration widget with a parameter tree
        # # self.config = ConfigWidget(self._session)
        # # Line cut widget
        # self.crossCut = crossCutWindow(parent=self)
        # self.popOut = popOutWindow(parent=self) #_future: for making long message pop-ups
        # # Select settings Window
        # # self.selectSettings = HDFLoader()
        #
        self.refreshTimer = QtCore.QTimer()
        self.refreshTimer.timeout.connect(self.updateGUI)
        # self.refreshTimer.timeout.connect(self.crossCut.update)
        #
        self.refreshTimer.start(self.experiment.config['GUI']['refresh_time'])
        #
        # self.acquiring = False
        # self.logmessage = []
        #
        # ''' Initialize the camera and the camera related things '''
        # self.max_sizex = self.camera.GetCCDWidth()
        # self.max_sizey = self.camera.GetCCDHeight()
        # self.current_width = self.max_sizex
        # self.current_height = self.max_sizey
        #
        # # if self._session.Camera['roi_x1'] == 0:
        # #     self._session.Camera = {'roi_x1': 1}
        # # if self._session.Camera['roi_x2'] == 0 or self._session.Camera['roi_x2'] > self.max_sizex:
        # #     self._session.Camera = {'roi_x2': self.max_sizex}
        # # if self._session.Camera['roi_y1'] == 0:
        # #     self._session.Camera = {'roi_y1': 1}
        # # if self._session.Camera['roi_y2'] == 0 or self._session.Camera['roi_y2'] > self.max_sizey:
        # #     self._session.Camera = {'roi_y2': self.max_sizey}
        #
        # # self.config.populateTree(self.experiment.config)
        # self.lastBuffer = time.time()
        # self.lastRefresh = time.time()
        #
        # # Program variables
        # self.tempimage = []
        # self.bgimage = []
        # self.trackinfo = np.zeros((1,5)) # real particle trajectory filled by "LocateParticle" analysis
        # # self.noiselvl = self._session.Tracking['noise_level']
        # self.fps = 0
        # self.buffertime = 0
        # self.buffertimes = []
        # self.refreshtimes = []
        # self.totalframes = 0
        # self.droppedframes = 0
        # self.buffer_memory = 0
        # self.waterfall_data = []
        # self.watindex = 0 # Waterfall index
        # self.corner_roi = [] # Real coordinates of the corner of the ROI region. (Min_x and Min_y).
        # self.docks = []
        # # self.corner_roi.append(self._session.Camera['roi_x1'])
        # # self.corner_roi.append(self._session.Camera['roi_y1'])
        #
        # # Program status controllers
        # self.continuous_saving = False
        # self.show_waterfall = False
        # self.subtract_background = False
        # self.save_running = False
        # self.accumulate_buffer = False
        # self.specialtask_running = False
        # self.dock_state = None
        #
        self.setupActions()
        self.setupToolbar()
        self.setupMenubar()
        # self.setupDocks()
        # self.setupSignals()

        ### This block should erased in due time and one must rely exclusively on Session variables.
        # self.filedir = self._session.Saving['directory']
        # self.snap_filename = self._session.Saving['filename_photo']
        # self.movie_filename = self._session.Saving['filename_video']
        ###
        self.messageWidget.appendLog(
            'i',
            'Program started by %s' % self.experiment.config['User']['name'])

    def start_tracking(self):
        self.experiment.start_tracking()

    def showHelp(self):
        """To show the cheatsheet for shortcuts in a pop-up meassage box
        OBSOLETE, will be deleted after transferring info into a better message viewer!
        """
        self.experiment.plot_histogram()
        # msgBox = QtGui.QMessageBox()
        # msgBox.setIcon(QtGui.QMessageBox.Information)
        # msgBox.setText("Keyboard shortcuts and Hotkeys")
        # msgBox.setInformativeText("Press details for a full list")
        # msgBox.setWindowTitle("pynta CheatSheet")
        # msgBox.setDetailedText("""
        #     F1, Show cheatsheet\n
        #     F5, Snap image\n
        #     F6, Continuous run\n
        #     Alt+mouse: Select line \n
        #     Ctrl+mouse: Crosshair \n
        #     Ctrl+B: Toggle buffering\n
        #     Ctrl+G: Toggle background subtraction\n
        #     Ctrl+F: Empty buffer\n
        #     Ctrl+C: Start tracking\n
        #     Ctrl+V: Stop tracking\n
        #     Ctrl+M: Autosave on\n
        #     Ctrl+N: Autosave off\n
        #     Ctrl+S: Save image\n
        #     Ctrl+W: Start waterfall\n
        #     Ctrl+Q: Exit application\n
        #     Ctrl+Shift+W: Save waterfall data\n
        #     Ctrl+Shift+T: Save trajectory\n
        #     """)

    def setupActions(self):
        """Setups the actions that the program will have. It is placed into a function
        to make it easier to reuse in other windows.

        :rtype: None
        """
        self.exitAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/power-icon.png'), '&Exit', self)
        self.exitAction.setShortcut('Ctrl+Q')
        self.exitAction.setStatusTip('Exit application')
        self.exitAction.triggered.connect(self.exitSafe)

        self.saveAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/floppy-icon.png'), '&Save image',
            self)
        self.saveAction.setShortcut('Ctrl+S')
        self.saveAction.setStatusTip('Save Image')
        self.saveAction.triggered.connect(self.saveImage)

        self.showHelpAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/info-icon.png'),
            'Show cheatsheet', self)
        self.showHelpAction.setShortcut(QtCore.Qt.Key_F1)
        self.showHelpAction.setStatusTip('Show Cheatsheet')
        self.showHelpAction.triggered.connect(self.showHelp)

        self.saveWaterfallAction = QtGui.QAction("Save Waterfall", self)
        self.saveWaterfallAction.setShortcut('Ctrl+Shift+W')
        self.saveWaterfallAction.setStatusTip(
            'Save waterfall data to new file')
        self.saveWaterfallAction.triggered.connect(self.saveWaterfall)

        self.saveTrajectoryAction = QtGui.QAction("Save Trajectory", self)
        self.saveTrajectoryAction.setShortcut('Ctrl+Shift+T')
        self.saveTrajectoryAction.setStatusTip(
            'Save trajectory data to new file')
        self.saveTrajectoryAction.triggered.connect(self.saveTrajectory)

        self.snapAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/snap.png'), 'S&nap photo', self)
        self.snapAction.setShortcut(QtCore.Qt.Key_F5)
        self.snapAction.setStatusTip('Snap Image')
        self.snapAction.triggered.connect(self.snap)

        self.movieAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/video-icon.png'), 'Start &movie',
            self)
        self.movieAction.setShortcut(QtCore.Qt.Key_F6)
        self.movieAction.setStatusTip('Start Movie')
        self.movieAction.triggered.connect(self.startMovie)

        self.movieSaveStartAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/Download-Database-icon.png'),
            'Continuous saves', self)
        self.movieSaveStartAction.setShortcut('Ctrl+M')
        self.movieSaveStartAction.setStatusTip('Continuous save to disk')
        self.movieSaveStartAction.triggered.connect(self.movieSave)

        self.movieSaveStopAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/Delete-Database-icon.png'),
            'Stop continuous saves', self)
        self.movieSaveStopAction.setShortcut('Ctrl+N')
        self.movieSaveStopAction.setStatusTip('Stop continuous save to disk')
        self.movieSaveStopAction.triggered.connect(self.movieSaveStop)

        self.startWaterfallAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/Blue-Waterfall-icon.png'),
            'Start &Waterfall', self)
        self.startWaterfallAction.setShortcut('Ctrl+W')
        self.startWaterfallAction.setStatusTip('Start Waterfall')
        self.startWaterfallAction.triggered.connect(self.startWaterfall)

        self.toggleBGAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/noBg.png'),
            'Toggle B&G-reduction', self)
        self.toggleBGAction.setShortcut('Ctrl+G')
        self.toggleBGAction.setStatusTip('Toggle Background Reduction')
        self.toggleBGAction.triggered.connect(self.start_tracking)

        self.setROIAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/Zoom-In-icon.png'), 'Set &ROI',
            self)
        self.setROIAction.setShortcut('Ctrl+T')
        self.setROIAction.setStatusTip('Set ROI')
        self.setROIAction.triggered.connect(self.getROI)

        self.clearROIAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/Zoom-Out-icon.png'), 'Set R&OI',
            self)
        self.clearROIAction.setShortcut('Ctrl+T')
        self.clearROIAction.setStatusTip('Clear ROI')
        self.clearROIAction.triggered.connect(self.clearROI)

        self.accumulateBufferAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/disk-save.png'),
            'Accumulate buffer', self)
        self.accumulateBufferAction.setShortcut('Ctrl+B')
        self.accumulateBufferAction.setStatusTip(
            'Start or stop buffer accumulation')
        self.accumulateBufferAction.triggered.connect(self.bufferStatus)

        self.clearBufferAction = QtGui.QAction('Clear Buffer', self)
        self.clearBufferAction.setShortcut('Ctrl+F')
        self.clearBufferAction.setStatusTip('Clears the buffer')
        self.clearBufferAction.triggered.connect(self.emptyQueue)

        self.viewerAction = QtGui.QAction('Start Viewer', self)
        # self.viewerAction.triggered.connect(self.camViewer.show)

        self.configAction = QtGui.QAction('Config Window', self)
        # self.configAction.triggered.connect(self.config.show)

        self.dockAction = QtGui.QAction('Restore Docks', self)
        self.dockAction.triggered.connect(self.setupDocks)

        self.crossCutAction = QtGui.QAction(
            QtGui.QIcon('pynta/View/GUI/Icons/Ruler-icon.png'),
            'Show cross cut', self)
        # self.crossCutAction.triggered.connect(self.crossCut.show)

        self.settingsAction = QtGui.QAction('Load config', self)
        # self.settingsAction.triggered.connect(self.selectSettings.show)

    def setupToolbar(self):
        """Setups the toolbar with the desired icons. It's placed into a function
        to make it easier to reuse in other windows.
        """
        self.toolbar = self.addToolBar('Exit')
        self.toolbar.addAction(self.exitAction)
        self.toolbar2 = self.addToolBar('Image')
        self.toolbar2.addAction(self.saveAction)
        self.toolbar2.addAction(self.snapAction)
        self.toolbar2.addAction(self.crossCutAction)
        self.toolbar3 = self.addToolBar('Movie')
        self.toolbar3.addAction(self.movieAction)
        self.toolbar3.addAction(self.movieSaveStartAction)
        self.toolbar3.addAction(self.movieSaveStopAction)
        self.toolbar4 = self.addToolBar('Extra')
        self.toolbar4.addAction(self.startWaterfallAction)
        self.toolbar4.addAction(self.setROIAction)
        self.toolbar4.addAction(self.clearROIAction)
        self.toolbar4.addAction(self.clearROIAction)
        self.toolbar4.addAction(self.toggleBGAction)
        self.toolbar5 = self.addToolBar('Help')
        self.toolbar5.addAction(self.showHelpAction)

    def setupMenubar(self):
        """Setups the menubar.
        """
        menubar = self.menuBar()
        self.fileMenu = menubar.addMenu('&File')
        self.fileMenu.addAction(self.settingsAction)
        self.fileMenu.addAction(self.saveAction)
        self.fileMenu.addAction(self.exitAction)
        self.snapMenu = menubar.addMenu('&Snap')
        self.snapMenu.addAction(self.snapAction)
        self.snapMenu.addAction(self.saveAction)
        self.movieMenu = menubar.addMenu('&Movie')
        self.movieMenu.addAction(self.movieAction)
        self.movieMenu.addAction(self.movieSaveStartAction)
        self.movieMenu.addAction(self.movieSaveStopAction)
        self.movieMenu.addAction(self.startWaterfallAction)
        self.configMenu = menubar.addMenu('&Configure')
        self.configMenu.addAction(self.toggleBGAction)
        self.configMenu.addAction(self.setROIAction)
        self.configMenu.addAction(self.clearROIAction)
        self.configMenu.addAction(self.accumulateBufferAction)
        self.configMenu.addAction(self.clearBufferAction)
        self.configMenu.addAction(self.viewerAction)
        self.configMenu.addAction(self.configAction)
        self.configMenu.addAction(self.dockAction)
        self.saveMenu = menubar.addMenu('S&ave')
        self.snapMenu.addAction(self.saveAction)
        self.saveMenu.addAction(self.saveWaterfallAction)
        self.saveMenu.addAction(self.saveTrajectoryAction)
        self.helpMenu = menubar.addMenu('&Help')
        self.helpMenu.addAction(self.showHelpAction)

    def setupDocks(self):
        """Setups the docks in order to recover the initial configuration if one gets closed."""

        for d in self.docks:
            try:
                d.close()
            except:
                pass

        self.docks = []

        self.dmainImage = Dock("Camera",
                               size=(80, 35))  #sizes are in percentage
        self.dwaterfall = Dock("Waterfall", size=(80, 35))
        self.dparams = Dock("Parameters", size=(20, 100))
        self.dtraj = Dock("Trajectory", size=(40, 30))

        # self.dstatus = Dock("Status", size=(100, 3))

        self.area.addDock(self.dmainImage, 'right')
        self.area.addDock(self.dparams, 'left', self.dmainImage)
        self.area.addDock(self.dtraj, 'bottom', self.dmainImage)
        self.area.addDock(self.dmessage, 'right', self.dtraj)

        self.docks.append(self.dmainImage)
        self.docks.append(self.dtraj)
        self.docks.append(self.dmessage)
        self.docks.append(self.dparams)
        self.docks.append(self.dwaterfall)
        # self.area.addDock(self.dstatus, 'bottom', self.dparams)

        self.dmainImage.addWidget(self.camWidget)

        self.dparams.addWidget(self.config)
        self.dtraj.addWidget(self.trajectoryWidget)

        self.dock_state = self.area.saveState()

    def setupSignals(self):
        """Setups all the signals that are going to be handled during the excution of the program."""
        self.connect(self._session, QtCore.SIGNAL('updated'),
                     self.config.populateTree)
        self.connect(self.config, QtCore.SIGNAL('updateSession'),
                     self.updateSession)
        self.connect(self.camWidget, QtCore.SIGNAL('specialTask'),
                     self.startSpecialTask)
        self.connect(self.camWidget, QtCore.SIGNAL('stopSpecialTask'),
                     self.stopSpecialTask)
        self.connect(self.camViewer, QtCore.SIGNAL('stopMainAcquisition'),
                     self.stopMovie)
        self.connect(self, QtCore.SIGNAL('stopChildMovie'),
                     self.camViewer.stopCamera)
        self.connect(self, QtCore.SIGNAL('closeAll'),
                     self.camViewer.closeViewer)
        self.connect(self.selectSettings, QtCore.SIGNAL("settings"),
                     self.update_settings)
        self.connect(self, QtCore.SIGNAL('closeAll'),
                     self.selectSettings.close)

    def snap(self):
        """Function for acquiring a single frame from the camera. It is triggered by the user.
        It gets the data the GUI will be updated at a fixed framerate.
        """
        if self.experiment.acquiring:  #If it is itself acquiring a message is displayed to the user warning him
            msgBox = QtGui.QMessageBox()
            msgBox.setIcon(QtGui.QMessageBox.Critical)
            msgBox.setText("You cant snap a photo while in free run")
            msgBox.setInformativeText("The program is already acquiring data")
            msgBox.setWindowTitle("Already acquiring")
            msgBox.setDetailedText(
                """When in free run, you can\'t trigger another acquisition. \n
                You should stop the free run acquisition and then snap a photo."""
            )
            msgBox.setStandardButtons(QtGui.QMessageBox.Ok)
            retval = msgBox.exec_()
            self.messageWidget.appendLog('e',
                                         'Tried to snap while in free run')
        else:
            self.experiment.snap()
            # self.messageWidget.appendLog('i', 'Snapped photo')

    def toggleBGReduction(self):
        """Toggles between background cancellation modes. Takes a background snap if necessary
        """

        if self.subtract_background:
            self.subtract_background = False
            self.messageWidget.appendLog('i',
                                         'Background reduction deactivated')
        else:
            if len(self.tempimage) == 0:
                self.snap()
                self.messageWidget.appendLog('i',
                                             'Snapped an image as background')
            else:
                self.subtract_background = True
                self.bgimage = self.tempimage.astype(float)
                self.messageWidget.appendLog('i',
                                             'Background reduction active')

    def saveImage(self):
        """Saves the image that is being displayed to the user.
        """
        if len(self.tempimage) >= 1:
            # Data will be appended to existing file
            fn = self._session.Saving['filename_photo']
            filename = '%s.hdf5' % (fn)
            fileDir = self._session.Saving['directory']
            if not os.path.exists(fileDir):
                os.makedirs(fileDir)

            f = h5py.File(os.path.join(fileDir, filename), "a")
            now = str(datetime.now())
            g = f.create_group(now)
            dset = g.create_dataset('image', data=self.tempimage)
            meta = g.create_dataset('metadata', data=self._session.serialize())
            f.flush()
            f.close()
            self.messageWidget.appendLog('i', 'Saved photo')

    def startMovie(self):
        self.experiment.start_free_run()

    def stopMovie(self):
        if self.acquiring:
            self.workerThread.keep_acquiring = False
            while self.workerThread.isRunning():
                pass
            self.acquiring = False
            self.camera.stopAcq()
            self.messageWidget.appendLog('i', 'Continuous run stopped')
            if self.continuous_saving:
                self.movieSaveStop()

    def movieData(self):
        """Function just to trigger and read the camera in the separate thread.
        """
        self.workerThread.start()

    def movieSave(self):
        """Saves the data accumulated in the queue continuously.
        """
        if not self.continuous_saving:
            # Child process to save the data. It runs continuously until and exit flag
            # is passed through the Queue. (self.q.put('exit'))
            self.accumulate_buffer = True
            if len(self.tempimage) > 1:
                im_size = self.tempimage.nbytes
                max_element = int(self._session.Saving['max_memory'] / im_size)
                #self.q = Queue(0)
            fn = self._session.Saving['filename_video']
            filename = '%s.hdf5' % (fn)
            fileDir = self._session.Saving['directory']
            if not os.path.exists(fileDir):
                os.makedirs(fileDir)
            to_save = os.path.join(fileDir, filename)
            metaData = self._session.serialize(
            )  # This prints a YAML-ready version of the session.
            self.p = Process(target=workerSaver,
                             args=(
                                 to_save,
                                 metaData,
                                 self.q,
                             ))  #
            self.p.start()
            self.continuous_saving = True
            self.messageWidget.appendLog('i', 'Continuous autosaving started')
        else:
            self.messageWidget.appendLog(
                'w', 'Continuous savings already triggered')

    def movieSaveStop(self):
        """Stops the saving to disk. It will however flush the queue.
        """
        if self.continuous_saving:
            self.q.put('Stop')
            self.accumulate_buffer = False
            #self.p.join()
            self.messageWidget.appendLog('i', 'Continuous autosaving stopped')
            self.continuous_saving = False

    def emptyQueue(self):
        """Clears the queue.
        """
        # Worker thread for clearing the queue.
        self.clearWorker = Process(target=clearQueue, args=(self.q, ))
        self.clearWorker.start()

    def startWaterfall(self):
        """Starts the waterfall. The waterfall can be accelerated if camera supports hardware binning in the appropriate
        direction. If not, has to be done via software but the acquisition time cannot be improved.
        TODO: Fast waterfall should have separate window, since the acquisition of the full CCD will be stopped.
        """
        if not self.show_waterfall:
            self.watWidget = waterfallWidget()
            self.area.addDock(self.dwaterfall, 'bottom', self.dmainImage)
            self.dwaterfall.addWidget(self.watWidget)
            self.show_waterfall = True
            Sx, Sy = self.camera.getSize()
            self.waterfall_data = np.zeros(
                (self._session.GUI['length_waterfall'], Sx))
            self.watWidget.img.setImage(np.transpose(self.waterfall_data),
                                        autoLevels=False,
                                        autoRange=False,
                                        autoHistogramRange=False)
            self.messageWidget.appendLog('i', 'Waterfall opened')
        else:
            self.closeWaterfall()

    def stopWaterfall(self):
        """Stops the acquisition of the waterfall.
        """
        pass

    def closeWaterfall(self):
        """Closes the waterfall widget.
        """
        if self.show_waterfall:
            self.watWidget.close()
            self.dwaterfall.close()
            self.show_waterfall = False
            del self.waterfall_data
            self.messageWidget.appendLog('i', 'Waterfall closed')

    def setROI(self, X, Y):
        """
        Gets the ROI from the lines on the image. It also updates the GUI to accommodate the changes.
        :param X:
        :param Y:
        :return:
        """
        if not self.acquiring:
            self.corner_roi[0] = X[0]
            self.corner_roi[1] = Y[0]
            if self._session.Debug['to_screen']:
                print('Corner: %s, %s' %
                      (self.corner_roi[0], self.corner_roi[1]))
            self._session.Camera = {'roi_x1': int(X[0])}
            self._session.Camera = {'roi_x2': int(X[1])}
            self._session.Camera = {'roi_y1': int(Y[0])}
            self._session.Camera = {'roi_y2': int(Y[1])}
            self.messageWidget.appendLog('i', 'Updated roi_x1: %s' % int(X[0]))
            self.messageWidget.appendLog('i', 'Updated roi_x2: %s' % int(X[1]))
            self.messageWidget.appendLog('i', 'Updated roi_y1: %s' % int(Y[0]))
            self.messageWidget.appendLog('i', 'Updated roi_y2: %s' % int(Y[1]))

            Nx, Ny = self.camera.setROI(X, Y)
            Sx, Sy = self.camera.getSize()
            self.current_width = Sx
            self.current_height = Sy

            self.tempimage = np.zeros((Nx, Ny))
            self.camWidget.hline1.setValue(1)
            self.camWidget.hline2.setValue(Ny)
            self.camWidget.vline1.setValue(1)
            self.camWidget.vline2.setValue(Nx)
            self.trackinfo = np.zeros((1, 5))
            #self.camWidget.img2.clear()
            if self.show_waterfall:
                self.waterfall_data = np.zeros(
                    (self._session.GUI['length_waterfall'],
                     self.current_width))
                self.watWidget.img.setImage(np.transpose(self.waterfall_data))

            self.config.populateTree(self._session)
            self.messageWidget.appendLog('i', 'Updated the ROI')
        else:
            self.messageWidget.appendLog('e',
                                         'Cannot change ROI while acquiring.')

    def getROI(self):
        """Gets the ROI coordinates from the GUI and updates the values."""
        y1 = np.int(self.camWidget.hline1.value())
        y2 = np.int(self.camWidget.hline2.value())
        x1 = np.int(self.camWidget.vline1.value())
        x2 = np.int(self.camWidget.vline2.value())
        X = np.sort((x1, x2))
        Y = np.sort((y1, y2))
        # Updates to the real values
        X += self.corner_roi[0] - 1
        Y += self.corner_roi[1] - 1
        self.setROI(X, Y)

    def clearROI(self):
        """Resets the roi to the full image.
        """
        if not self.acquiring:
            self.camWidget.hline1.setValue(1)
            self.camWidget.vline1.setValue(1)
            self.camWidget.vline2.setValue(self.max_sizex)
            self.camWidget.hline2.setValue(self.max_sizey)
            self.corner_roi = [1, 1]
            self.getROI()
        else:
            self.messageWidget.appendLog('e',
                                         'Cannot change ROI while acquiring.')

    def bufferStatus(self):
        """Starts or stops the buffer accumulation.
        """
        if self.accumulate_buffer:
            self.accumulate_buffer = False
            self.messageWidget.appendLog('i', 'Buffer accumulation stopped')
        else:
            self.accumulate_buffer = True
            self.messageWidget.appendLog('i', 'Buffer accumulation started')

    def getData(self, data, origin):
        """Gets the data that is being gathered by the working thread.

        .. _getData:
        .. data: single image or a list of images (saved in buffer)
        .. origin: indicates which command has trigerred execution of this method (e.g. 'snap' of 'movie')
        both input variables are handed it through QThread signal that is "emit"ted
        """
        s = 0
        if origin == 'snap':  # Single snap.
            self.acquiring = False
            self.workerThread.origin = None
            self.workerThread.keep_acquiring = False  # This already happens in the worker thread itself.
            self.camera.stopAcq()

        if isinstance(data, list):
            for d in data:
                if self.accumulate_buffer:
                    s = float(self.q.qsize()) * int(d.nbytes) / 1024 / 1024
                    if s < self._session.Saving['max_memory']:
                        self.q.put(d)
                    else:
                        self.droppedframes += 1

                if self.show_waterfall:
                    if self.watindex == self._session.GUI['length_waterfall']:
                        if self._session.Saving['autosave_trajectory']:
                            self.saveWaterfall()

                        self.waterfall_data = np.zeros(
                            (self._session.GUI['length_waterfall'],
                             self.current_width))
                        self.watindex = 0

                    centerline = np.int(self.current_height / 2)
                    vbinhalf = np.int(self._session.GUI['vbin_waterfall'])
                    if vbinhalf >= self.current_height / 2 - 1:
                        wf = np.array([np.sum(d, 1)])
                    else:
                        wf = np.array([
                            np.sum(
                                d[:,
                                  centerline - vbinhalf:centerline + vbinhalf],
                                1)
                        ])
                    self.waterfall_data[self.watindex, :] = wf
                    self.watindex += 1
                self.totalframes += 1
            self.tempimage = d
        else:
            self.tempimage = data
            if self.accumulate_buffer:
                s = float(self.q.qsize()) * int(data.nbytes) / 1024 / 1024

                if s < self._session.Saving['max_memory']:
                    self.q.put(data)
                else:
                    self.droppedframes += 1

            if self.show_waterfall:
                if self.watindex == self._session.GUI['length_waterfall']:
                    # checks if the buffer variable for waterfall image is full, saves it if requested, and sets it to zero.
                    if self._session.Saving['autosave_trajectory']:
                        self.saveWaterfall()

                    self.waterfall_data = np.zeros(
                        (self._session.GUI['length_waterfall'],
                         self.current_width))
                    self.watindex = 0

                centerline = np.int(self.current_height / 2)
                vbinhalf = np.int(self._session.GUI['vbin_waterfall'] / 2)

                if vbinhalf >= self.current_height - 1:
                    wf = np.array([np.sum(data, 1)])
                else:
                    wf = np.array([
                        np.sum(
                            data[:,
                                 centerline - vbinhalf:centerline + vbinhalf],
                            1)
                    ])
                self.waterfall_data[self.watindex, :] = wf
                self.watindex += 1

            self.totalframes += 1

        new_time = time.time()
        self.buffertime = new_time - self.lastBuffer
        self.lastBuffer = new_time
        self.buffer_memory = s
        if self._session.Debug['queue_memory']:
            print('Queue Memory: %3.2f MB' % self.buffer_memory)

    def updateGUI(self):
        """Updates the image displayed to the user.
        """
        if self.experiment.temp_image is not None:
            img = self.experiment.temp_image
            self.camWidget.img.setImage(img.astype(int),
                                        autoLevels=False,
                                        autoRange=False,
                                        autoHistogramRange=False)
        if self.experiment.link_particles_running:
            self.camWidget.draw_target_pointer(
                self.experiment.localize_particles_image(img))

    def saveWaterfall(self):
        """Saves the waterfall data, if any.
        """
        if len(self.waterfall_data) > 1:
            fn = self._session.Saving['filename_waterfall']
            filename = '%s.hdf5' % (fn)
            fileDir = self._session.Saving['directory']
            if not os.path.exists(fileDir):
                os.makedirs(fileDir)

            f = h5py.File(os.path.join(fileDir, filename), "a")
            now = str(datetime.now())
            g = f.create_group(now)
            dset = g.create_dataset('waterfall', data=self.waterfall_data)
            meta = g.create_dataset('metadata',
                                    data=self._session.serialize().encode(
                                        "ascii", "ignore"))
            f.flush()
            f.close()
            self.messageWidget.appendLog('i', 'Saved Waterfall')

    def saveTrajectory(self):
        """Saves the trajectory data, if any.
        """
        if len(self.trackinfo) > 1:
            fn = self._session.Saving['filename_trajectory']
            filename = '%s.hdf5' % (fn)
            fileDir = self._session.Saving['directory']
            if not os.path.exists(fileDir):
                os.makedirs(fileDir)

            f = h5py.File(os.path.join(fileDir, filename), "a")
            now = str(datetime.now())
            g = f.create_group(now)
            dset = g.create_dataset('trajectory', data=[self.trackinfo])
            meta = g.create_dataset('metadata',
                                    data=self._session.serialize().encode(
                                        "ascii", "ignore"))
            f.flush()
            f.close()
            self.messageWidget.appendLog('i', 'Saved Trajectory')

    def update_settings(self, settings):
        new_session = _session(settings)
        self.updateSession(new_session)
        self.config.populateTree(self._session)

    def updateSession(self, session):
        """Updates the session variables passed by the config window.
        """
        update_cam = False
        update_roi = False
        update_exposure = False
        update_binning = True
        for k in session.params['Camera']:
            new_prop = session.params['Camera'][k]
            old_prop = self._session.params['Camera'][k]
            if new_prop != old_prop:
                update_cam = True
                if k in ['roi_x1', 'roi_x2', 'roi_y1', 'roi_y2']:
                    update_roi = True
                    if self._session.Debug['to_screen']:
                        print('Update ROI')
                elif k == 'exposure_time':
                    update_exposure = True
                elif k in ['binning_x', 'binning_y']:
                    update_binning = True

        if session.GUI['length_waterfall'] != self._session.GUI[
                'length_waterfall']:
            if self.show_waterfall:
                self.closeWaterfall()
                self.restart_waterfall = True

        self.messageWidget.appendLog('i', 'Parameters updated')
        self.messageWidget.appendLog(
            'i', 'Measurement: %s' % session.User['measurement'])
        self._session = session.copy()

        if update_cam:
            if self.acquiring:
                self.stopMovie()

            if update_roi:
                X = np.sort(
                    [session.Camera['roi_x1'], session.Camera['roi_x2']])
                Y = np.sort(
                    [session.Camera['roi_y1'], session.Camera['roi_y2']])
                self.setROI(X, Y)

            if update_exposure:
                new_exp = self.camera.setExposure(
                    session.Camera['exposure_time'])
                self._session.Camera = {'exposure_time': new_exp}
                self.messageWidget.appendLog('i',
                                             'Updated exposure: %s' % new_exp)
                if self._session.Debug['to_screen']:
                    print("New Exposure: %s" % new_exp)
                    print(self._session)

            if update_binning:
                self.camera.setBinning(session.Camera['binning_x'],
                                       session.Camera['binning_y'])

        self.refreshTimer.stop()
        self.refreshTimer.start(session.GUI['refresh_time'])

    def startSpecialTask(self):
        """Starts a special task. This is triggered by the user with a special combination of actions, for example clicking
        with the mouse on a plot, draggin a crosshair, etc."""
        if not self.specialtask_running:
            if self.acquiring:
                self.stopMovie()
                self.acquiring = False

            locy = self.camWidget.crosshair[0].getPos()[1]
            locx = self.camWidget.crosshair[1].getPos()[0]
            self.trackinfo = np.zeros((1, 5))
            self.trajectoryWidget.plot.clear()
            imgsize = self.tempimage.shape
            iniloc = [locx, locy]
            self.specialTaskWorker = specialTaskTracking(
                self._session, self.camera, self.noiselvl, imgsize, iniloc)
            self.connect(self.specialTaskWorker, QtCore.SIGNAL('image'),
                         self.getData)
            self.connect(self.specialTaskWorker, QtCore.SIGNAL('coordinates'),
                         self.getParticleLocation)
            self.specialTaskWorker.start()
            self.specialtask_running = True
            self.messageWidget.appendLog('i', 'Live tracking started')
        else:
            print('Special task already running')

    def stopSpecialTask(self):
        """Stops the special task"""
        if self.specialtask_running:
            self.specialTaskWorker.keep_running = False
            self.specialtask_running = False
            if self._session.Saving['autosave_trajectory'] == True:
                self.saveTrajectory()
            self.messageWidget.appendLog('i', 'Live tracking stopped')

    def done(self):
        #self.saveRunning = False
        self.acquiring = False

    def exitSafe(self):
        self.close()

    def closeEvent(self, evnt):
        """
            Triggered at closing. Checks that the save is complete and closes the dataFile
        """
        self.experiment.finalize()

        # self.messageWidget.appendLog('i', 'Closing the program')
        # if self.acquiring:
        #     self.stopMovie()
        # if self.specialtask_running:
        #     self.stopSpecialTask()
        #     while self.specialTaskWorker.isRunning():
        #         pass
        # self.emit(QtCore.SIGNAL('closeAll'))
        # self.camera.stopCamera()
        # self.movieSaveStop()
        # try:
        #     # Checks if the process P exists and tries to close it.
        #     if self.p.is_alive():
        #         qs = self.q.qsize()
        #         with ProgressDialog("Finish saving data...", 0, qs) as dlg:
        #             while self.q.qsize() > 1:
        #                 dlg.setValue(qs - self.q.qsize())
        #                 time.sleep(0.5)
        #     self.p.join()
        # except AttributeError:
        #     pass
        # if self.q.qsize() > 0:
        #     self.messageWidget.appendLog('i', 'The queue was not empty')
        #     print('Freeing up memory...')
        #     self.emptyQueue()
        #
        # # Save LOG.
        # fn = self._session.Saving['filename_log']
        # timestamp = datetime.now().strftime('%H%M%S')
        # filename = '%s%s.log' % (fn, timestamp)
        # fileDir = self._session.Saving['directory']
        # if not os.path.exists(fileDir):
        #     os.makedirs(fileDir)
        #
        # f = open(os.path.join(fileDir,filename), "a")
        # for line in self.messageWidget.logText:
        #     f.write(line+'\n')
        # f.flush()
        # f.close()
        # print('Saved LOG')
        super(MainWindow, self).closeEvent(evnt)
Example #7
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])
Example #8
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
Example #9
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)
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 )      
Example #11
0
class WidgetBase(BaseClassTemplate):
    def __init__(self, parent=None, hideHistograms=False) -> None:
        BaseClassTemplate.__init__(self, parent=parent)

        self.uiBase = BaseWidgetTemplate()
        self.uiBase.setupUi(self)

        #############################################################
        #                   ATTRIBUTES                              #
        #############################################################

        self.gui_timer = QTimer()  # type: QTimer
        self.gui_timer.timeout.connect(self.updateDisplay)
        if self.uiBase.wao_Display.isChecked():
            self.gui_timer.start(1000. / self.uiBase.wao_frameRate.value())
        self.loopLock = threading.Lock(
        )  # type: Threading.Lock # Asynchronous loop / display safe-threading
        self.hideHistograms = hideHistograms
        #############################################################
        #               PYQTGRAPH DockArea INIT                     #
        #############################################################

        self.area = DockArea()
        self.uiBase.wao_DisplayDock.setWidget(self.area)
        self.gridSH = []

        #############################################################
        #                 CONNECTED BUTTONS                         #
        #############################################################
        # Default path for config files
        self.defaultParPath = "."
        self.defaultAreaPath = "."
        self.uiBase.wao_loadConfig.clicked.connect(self.loadConfig)
        self.uiBase.wao_loadArea.clicked.connect(self.loadArea)
        self.uiBase.wao_saveArea.clicked.connect(self.saveArea)
        self.uiBase.wao_init.clicked.connect(self.initConfig)
        self.uiBase.wao_configFromFile.clicked.connect(self.addConfigFromFile)

        self.uiBase.wao_Display.stateChanged.connect(self.gui_timer_config)
        self.uiBase.wao_frameRate.setValue(2)

        self.uiBase.wao_loadConfig.setDisabled(False)
        self.uiBase.wao_init.setDisabled(True)

        self.disp_checkboxes = []
        self.docks = {}  # type: Dict[str, pg.dockarea.Dock]
        self.viewboxes = {}  # type: Dict[str, pg.ViewBox]
        self.imgs = {}  # type: Dict[str, pg.ImageItem]
        self.hists = {}  # type: Dict[str, pg.HistogramLUTItem]

        self.PupilLines = None
        self.adjustSize()

    def gui_timer_config(self, state) -> None:
        self.uiBase.wao_frameRate.setDisabled(state)
        if state:
            self.gui_timer.start(1000. / self.uiBase.wao_frameRate.value())
        else:
            self.gui_timer.stop()

    def closeEvent(self, event: Any) -> None:
        self.quitGUI(event)

    def quitGUI(self, event: Any = None) -> None:
        reply = QtWidgets.QMessageBox.question(
            self, 'Message', "Are you sure to quit?",
            QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
            QtWidgets.QMessageBox.No)

        if reply == QtWidgets.QMessageBox.Yes:
            if event:
                event.accept()
            quit()
        else:
            if event:
                event.ignore()

    #############################################################
    #                       METHODS                             #
    #############################################################

    def saveArea(self, widget, filename=None):
        '''
            Callback when a area layout file is double clicked in the file browser
            Place the selected file name in the browsing drop-down menu,
            the call the self.loadConfig callback of the load button.
        '''
        if filename is None:
            filepath = QtWidgets.QFileDialog(
                directory=self.defaultAreaPath).getSaveFileName(
                    self, "Select area layout file", "",
                    "area layout file (*.area);;all files (*)")
            filename = filepath[0]

        try:
            with open(filename, "w+") as f:
                st = self.area.saveState()
                f.write(str(st))
        except FileNotFoundError as err:
            warnings.warn(filename + " not loaded: " + err)

    def showDock(self, name):
        for disp_checkbox in self.disp_checkboxes:
            if disp_checkbox.text() == name:
                disp_checkbox.setChecked(True)
                break
        if name in self.docks.keys():
            self.area.addDock(self.docks[name])

    def restoreMyState(self, state):
        typ, contents, _ = state

        if typ == 'dock':
            self.showDock(contents)
        else:
            for o in contents:
                self.restoreMyState(o)

    def loadArea(self, widget=None, filename=None):
        # close all docks
        for disp_checkbox in self.disp_checkboxes:
            disp_checkbox.setChecked(False)
        for dock in self.docks.values():
            if dock.isVisible():
                dock.close()

        if filename is None:
            filepath = QtWidgets.QFileDialog(
                directory=self.defaultAreaPath).getOpenFileName(
                    self, "Select area layout file", "",
                    "area layout file (*.area);;all files (*)")
            filename = filepath[0]

        try:
            with open(filename, "r") as f:
                st = eval(f.readline())

                # restore docks from main area
                if st['main'] is not None:
                    self.restoreMyState(st["main"])

                # restore docks from floating area
                for win in st["float"]:
                    self.restoreMyState(win[0]['main'])

                # rearange dock s as in stored state
                self.area.restoreState(st)
        except FileNotFoundError as err:
            warnings.warn(filename + "not loaded: " + err)

    def addConfigFromFile(self) -> None:
        '''
            Callback when a config file is double clicked in the file browser
            Place the selected file name in the browsing drop-down menu,
            the call the self.loadConfig callback of the load button.
        '''
        filepath = QtWidgets.QFileDialog(
            directory=self.defaultParPath).getOpenFileName(
                self, "Select parameter file", "",
                "parameters file (*.py);;hdf5 file (*.h5);;all files (*)")

        self.uiBase.wao_selectConfig.clear()
        self.uiBase.wao_selectConfig.addItem(str(filepath[0]))

        self.loadConfig(configFile=self.uiBase.wao_selectConfig.currentText())

    def update_displayDock(self):
        guilty_guy = self.sender().text()
        state = self.sender().isChecked()
        if state:
            self.area.addDock(self.docks[guilty_guy])
        elif self.docks[guilty_guy].isVisible():
            self.docks[guilty_guy].close()

    def add_dispDock(self, name: str, parent, type: str = "pg_image") -> Dock:
        checkBox = QtGui.QCheckBox(name, parent)
        checkBox.clicked.connect(self.update_displayDock)
        checkableAction = QtGui.QWidgetAction(parent)
        checkableAction.setDefaultWidget(checkBox)
        parent.addAction(checkableAction)
        self.disp_checkboxes.append(checkBox)

        d = Dock(name)  # , closable=True)
        self.docks[name] = d
        if type == "pg_image":
            img = pg.ImageItem(border='w')
            self.imgs[name] = img

            viewbox = pg.ViewBox()

            viewbox.setAspectLocked(True)
            viewbox.addItem(img)  # Put image in plot area
            self.viewboxes[name] = viewbox
            iv = pg.ImageView(view=viewbox, imageItem=img)
            viewbox.invertY(False)

            if (self.hideHistograms):
                iv.ui.histogram.hide()
            iv.ui.histogram.autoHistogramRange()  # init levels
            iv.ui.histogram.setMaximumWidth(100)
            iv.ui.menuBtn.hide()
            iv.ui.roiBtn.hide()
            d.addWidget(iv)
        elif type == "pg_plot":
            img = pg.PlotItem(border='w')
            self.imgs[name] = img
            d.addWidget(img)
        elif type == "MPL":
            img = MatplotlibWidget()
            self.imgs[name] = img
            d.addWidget(img)
        # elif type == "SR":
        #     d.addWidget(self.uiBase.wao_Strehl)
        return d

    def loadConfig(self, *args, **kwargs) -> None:
        '''
            Callback when 'LOAD' button is hit
        '''
        for groupbox in [
                self.uiBase.wao_phasesgroup_tb, self.uiBase.wao_imagesgroup_tb,
                self.uiBase.wao_graphgroup_tb
        ]:
            layout = groupbox.menu()
            while layout and not layout.isEmpty():
                w = layout.children()[0]
                layout.removeAction(w)
                w.setParent(None)
        self.disp_checkboxes.clear()

        # TODO: remove self.imgs, self.viewboxes and self.docks children
        for _, dock in self.docks.items():
            if dock.isVisible():
                dock.close()

        self.docks.clear()
        self.imgs.clear()
        self.viewboxes.clear()

        self.wao_phasesgroup_cb = QtGui.QMenu(self)
        self.uiBase.wao_phasesgroup_tb.setMenu(self.wao_phasesgroup_cb)
        self.uiBase.wao_phasesgroup_tb.setText('Select')
        self.uiBase.wao_phasesgroup_tb.setPopupMode(
            QtWidgets.QToolButton.InstantPopup)

        self.wao_graphgroup_cb = QtGui.QMenu(self)
        self.uiBase.wao_graphgroup_tb.setMenu(self.wao_graphgroup_cb)
        self.uiBase.wao_graphgroup_tb.setText('Select')
        self.uiBase.wao_graphgroup_tb.setPopupMode(
            QtWidgets.QToolButton.InstantPopup)

        self.uiBase.wao_imagesgroup_tb.setText('Select')
        self.wao_imagesgroup_cb = QtGui.QMenu(self)
        self.uiBase.wao_imagesgroup_tb.setMenu(self.wao_imagesgroup_cb)
        self.uiBase.wao_imagesgroup_tb.setPopupMode(
            QtWidgets.QToolButton.InstantPopup)

        # self.uiBase.wao_init.setDisabled(False)
        #
        # if (hasattr(self.sim.config, "layout")):
        #     area_filename = self.defaultAreaPath + "/" + self.sim.config.layout + ".area"
        #     self.loadArea(filename=area_filename)
        #
        # self.adjustSize()

    def loadDefaultConfig(self) -> None:
        import glob
        parlist = sorted(glob.glob(self.defaultParPath + "/*.py"))
        self.uiBase.wao_selectConfig.clear()
        self.uiBase.wao_selectConfig.addItems(
            [parlist[i].split('/')[-1] for i in range(len(parlist))])

    def initConfig(self) -> None:
        self.loopLock.acquire(True)
        self.uiBase.wao_loadConfig.setDisabled(True)
        self.uiBase.wao_init.setDisabled(True)
        self.thread = WorkerThread(self.initConfigThread)
        self.thread.finished.connect(self.initConfigFinished)
        self.thread.start()

    def initConfigThread(self) -> None:
        pass

    def initConfigFinished(self) -> None:
        self.uiBase.wao_loadConfig.setDisabled(False)
        self.uiBase.wao_init.setDisabled(False)
        self.loopLock.release()

    def updateDisplay(self) -> None:
        if not self.loopLock.acquire(False):
            return
        else:
            try:
                pass
            finally:
                self.loopLock.release()

    def addSHGrid(self, pg_image, valid_sub, sspsize, pitch):
        # First remove the old grid, if any
        if self.PupilLines is not None:
            pg_image.removeItem(self.PupilLines)

        nssp_tot = valid_sub[0].size
        connect = np.ones((nssp_tot, 5), dtype=bool)
        connect[:, -1] = 0  # don't draw the segment between each trace
        roi_x = np.ones((nssp_tot, 5), dtype=int)
        roi_y = np.ones((nssp_tot, 5), dtype=int)
        for idx_ssp in range(nssp_tot):
            (x, y) = (valid_sub[0][idx_ssp], valid_sub[1][idx_ssp])
            roi_x[idx_ssp, :] = [x, x, x + sspsize, x + sspsize, x]
            roi_y[idx_ssp, :] = [y, y + sspsize, y + sspsize, y, y]
        self.PupilLines = PupilBoxes(roi_x, roi_y)
        pg_image.addItem(self.PupilLines)

    def printInPlace(self, text: str) -> None:
        # This seems to trigger the GUI and keep it responsive
        print(text, end='\r', flush=True)

    def run(self):
        self.loopOnce()
        if not self.stop:
            QTimer.singleShot(0, self.run)  # Update loop
Example #12
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()
Example #13
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
Example #14
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()
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 ))
Example #16
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))
Example #17
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()
Example #18
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)
Example #19
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()