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()
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()
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
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])
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)
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 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
class AWGUi(AWGForm, AWGBase): varDictChanged = QtCore.pyqtSignal(object) def __init__(self, deviceClass, config, globalDict, parent=None): AWGBase.__init__(self, parent) AWGForm.__init__(self) self.config = config self.configname = 'AWGUi.' + deviceClass.displayName self.globalDict = globalDict self.autoSave = self.config.get(self.configname + '.autoSave', True) self.waveformCache = OrderedDict() self.settingsDict = self.config.get(self.configname + '.settingsDict', dict()) self.settingsName = self.config.get(self.configname + '.settingsName', '') # self.settingsDict=dict() # self.settingsName='' self.recentFiles = self.config.get( self.configname + '.recentFiles', dict() ) #dict of form {basename: filename}, where filename has path and basename doesn't self.lastDir = self.config.get(self.configname + '.lastDir', getProject().configDir) Settings.deviceProperties = deviceClass.deviceProperties Settings.saveIfNecessary = self.saveIfNecessary Settings.replot = self.replot for settings in list( self.settingsDict.values() ): #make sure all pickled settings are consistent with device, in case it changed for channel in range(deviceClass.deviceProperties['numChannels']): if channel >= len(settings.channelSettingsList ): #create new channels if it's necessary settings.channelSettingsList.append({ 'segmentDataRoot': AWGSegmentNode(None), 'segmentTreeState': None, 'plotEnabled': True, 'plotStyle': Settings.plotStyles.lines }) else: settings.channelSettingsList[channel].setdefault( 'segmentDataRoot', AWGSegmentNode(None)) settings.channelSettingsList[channel].setdefault( 'segmentTreeState', None) settings.channelSettingsList[channel].setdefault( 'plotEnabled', True) settings.channelSettingsList[channel].setdefault( 'plotStyle', Settings.plotStyles.lines) self.settings = Settings( ) #we always run settings through the constructor if self.settingsName in self.settingsDict: self.settings.update(self.settingsDict[self.settingsName]) self.device = deviceClass(self.settings) def setupUi(self, parent): logger = logging.getLogger(__name__) AWGForm.setupUi(self, parent) self.setWindowTitle(self.device.displayName) self._varAsOutputChannelDict = dict() self.area = DockArea() self.splitter.insertWidget(0, self.area) self.awgChannelUiList = [] for channel in range(self.device.deviceProperties['numChannels']): awgChannelUi = AWGChannelUi(channel, self.settings, self.globalDict, self.waveformCache, parent=self) awgChannelUi.setupUi(awgChannelUi) awgChannelUi.dependenciesChanged.connect( self.onDependenciesChanged) self.awgChannelUiList.append(awgChannelUi) dock = Dock("AWG Channel {0}".format(channel)) dock.addWidget(awgChannelUi) self.area.addDock(dock, 'right') self.device.waveforms[channel] = awgChannelUi.waveform self.refreshVarDict() # Settings control self.saveButton.clicked.connect(self.onSave) self.removeButton.clicked.connect(self.onRemove) self.reloadButton.clicked.connect(self.onReload) self.settingsModel = QtCore.QStringListModel() self.settingsComboBox.setModel(self.settingsModel) self.settingsModel.setStringList(sorted(self.settingsDict.keys())) self.settingsComboBox.setCurrentIndex( self.settingsComboBox.findText(self.settingsName)) self.settingsComboBox.currentIndexChanged[str].connect(self.onLoad) self.settingsComboBox.lineEdit().editingFinished.connect( self.onComboBoxEditingFinished) self.autoSaveCheckBox.setChecked(self.autoSave) self.saveButton.setEnabled(not self.autoSave) self.saveButton.setVisible(not self.autoSave) self.reloadButton.setEnabled(not self.autoSave) self.reloadButton.setVisible(not self.autoSave) self.autoSaveCheckBox.stateChanged.connect(self.onAutoSave) #programming options table self.programmingOptionsTable.setupUi( globalDict=self.globalDict, parameterDict=self.device.parameters()) self.programmingOptionsTable.valueChanged.connect(self.device.update) # Table self.tableModel = AWGTableModel(self.settings, self.globalDict) self.tableView.setModel(self.tableModel) self.tableModel.valueChanged.connect(self.onValue) self.delegate = MagnitudeSpinBoxDelegate(self.globalDict) self.tableView.setItemDelegateForColumn(self.tableModel.column.value, self.delegate) #File self.filenameModel = QtCore.QStringListModel() self.filenameComboBox.setModel(self.filenameModel) self.filenameModel.setStringList([ basename for basename, filename in list(self.recentFiles.items()) if os.path.exists(filename) ]) self.filenameComboBox.setCurrentIndex( self.filenameComboBox.findText( os.path.basename(self.settings.filename))) self.filenameComboBox.currentIndexChanged[str].connect(self.onFilename) self.removeFileButton.clicked.connect(self.onRemoveFile) self.newFileButton.clicked.connect(self.onNewFile) self.openFileButton.clicked.connect(self.onOpenFile) self.saveFileButton.clicked.connect(self.onSaveFile) self.reloadFileButton.clicked.connect(self.onReloadFile) #cache self.cacheDepthSpinBox.setValue(self.settings.cacheDepth) self.cacheDepthSpinBox.valueChanged.connect(self.onCacheDepth) self.clearCacheButton.clicked.connect(self.onClearCache) #status bar self.label = QtGui.QLabel('Sample Rate: {0}'.format( self.settings.deviceProperties['sampleRate'])) self.statusbar.addWidget(self.label) #Restore GUI state state = self.config.get(self.configname + '.state') pos = self.config.get(self.configname + '.pos') size = self.config.get(self.configname + '.size') isMaximized = self.config.get(self.configname + '.isMaximized') dockAreaState = self.config.get(self.configname + '.dockAreaState') guiState = self.config.get(self.configname + ".guiState") restoreGuiState(self, guiState) try: if pos: self.move(pos) if size: self.resize(size) if isMaximized: self.showMaximized() if state: self.restoreState(state) for awgChannelUi in self.awgChannelUiList: channelGuiState = self.config[ self.configname + "channel{0}.guiState".format(awgChannelUi.channel)] restoreGuiState(awgChannelUi, channelGuiState) except Exception as e: logger.warning( "Error on restoring state in AWGUi {0}. Exception occurred: {1}" .format(self.device.displayName, e)) try: if dockAreaState: self.area.restoreState(dockAreaState) except Exception as e: logger.warning( "Cannot restore dock state in AWGUi {0}. Exception occurred: {1}" .format(self.device.displayName, e)) self.area.deleteLater() self.area = DockArea() self.splitter.insertWidget(0, self.area) for channelUi in self.awgChannelUiList: dock = Dock("AWG Channel {0}".format(channel)) dock.addWidget(channelUi) self.area.addDock(dock, 'right') self.saveIfNecessary() def onCacheDepth(self, newVal): self.settings.cacheDepth = newVal self.saveIfNecessary() def onClearCache(self): self.waveformCache.clear() def onComboBoxEditingFinished(self): """a settings name is typed into the combo box""" currentText = str(self.settingsComboBox.currentText()) if self.settingsName != currentText: self.settingsName = currentText if self.settingsName not in self.settingsDict: self.settingsDict[self.settingsName] = copy.deepcopy( self.settings) self.onLoad(self.settingsName) def saveIfNecessary(self): """save the current settings if autosave is on and something has changed""" currentText = str(self.settingsComboBox.currentText()) if self.settingsDict.get( self.settingsName ) != self.settings or currentText != self.settingsName: if self.autoSave: self.onSave() else: self.saveButton.setEnabled(True) def replot(self): """plot all channels""" for channelUi in self.awgChannelUiList: channelUi.replot() def onSave(self): """save current settings""" self.settingsName = str(self.settingsComboBox.currentText()) self.settingsDict[self.settingsName] = copy.deepcopy(self.settings) with BlockSignals(self.settingsComboBox) as w: self.settingsModel.setStringList(sorted(self.settingsDict.keys())) w.setCurrentIndex(w.findText(self.settingsName)) self.saveButton.setEnabled(False) def saveConfig(self): """save GUI configuration to config""" self.config[self.configname + ".guiState"] = saveGuiState(self) for awgChannelUi in self.awgChannelUiList: self.config[self.configname + "channel{0}.guiState".format( awgChannelUi.channel)] = saveGuiState(awgChannelUi) self.settings.channelSettingsList[awgChannelUi.channel][ 'segmentTreeState'] = awgChannelUi.segmentView.saveTreeState() self.config[self.configname + '.state'] = self.saveState() self.config[self.configname + '.pos'] = self.pos() self.config[self.configname + '.size'] = self.size() self.config[self.configname + '.isMaximized'] = self.isMaximized() self.config[self.configname + '.isVisible'] = self.isVisible() self.config[self.configname + '.dockAreaState'] = self.area.saveState() self.config[self.configname + '.settingsDict'] = self.settingsDict self.config[self.configname + '.settingsName'] = self.settingsName self.config[self.configname + '.autoSave'] = self.autoSave self.config[self.configname + '.recentFiles'] = self.recentFiles self.config[self.configname + '.lastDir'] = self.lastDir def onRemove(self): """Remove current settings from combo box""" name = str(self.settingsComboBox.currentText()) if name in self.settingsDict: self.settingsDict.pop(name) self.settingsName = list( self.settingsDict.keys())[0] if self.settingsDict else '' with BlockSignals(self.settingsComboBox) as w: self.settingsModel.setStringList( sorted(self.settingsDict.keys())) w.setCurrentIndex(w.findText(self.settingsName)) self.onLoad(self.settingsName) def onReload(self): """Reload settings""" name = str(self.settingsComboBox.currentText()) self.onLoad(name) def onLoad(self, name): """load settings""" for channelUi in self.awgChannelUiList: self.settings.channelSettingsList[channelUi.channel][ 'segmentTreeState'] = channelUi.segmentView.saveTreeState() name = str(name) if name in self.settingsDict: self.settingsName = name self.tableModel.beginResetModel() [ channelUi.segmentModel.beginResetModel() for channelUi in self.awgChannelUiList ] self.settings.update(self.settingsDict[self.settingsName]) self.programmingOptionsTable.setParameters( self.device.parameters()) self.saveButton.setEnabled(False) with BlockSignals(self.filenameComboBox) as w: w.setCurrentIndex( w.findText(os.path.basename(self.settings.filename))) with BlockSignals(self.cacheDepthSpinBox) as w: w.setValue(self.settings.cacheDepth) for channelUi in self.awgChannelUiList: channelUi.waveform.updateDependencies() channelUi.plotCheckbox.setChecked( self.settings.channelSettingsList[ channelUi.channel]['plotEnabled']) with BlockSignals(channelUi.styleComboBox) as w: w.setCurrentIndex(self.settings.channelSettingsList[ channelUi.channel]['plotStyle']) channelUi.segmentModel.root = self.settings.channelSettingsList[ channelUi.channel]['segmentDataRoot'] channelUi.replot() self.onDependenciesChanged() self.saveButton.setEnabled(False) self.tableModel.endResetModel() [ channelUi.segmentModel.endResetModel() for channelUi in self.awgChannelUiList ] for channelUi in self.awgChannelUiList: channelUi.segmentView.restoreTreeState( self.settings.channelSettingsList[ channelUi.channel]['segmentTreeState']) def onAutoSave(self, checked): """autosave is changed""" self.autoSave = checked self.saveButton.setEnabled(not checked) self.saveButton.setVisible(not checked) self.reloadButton.setEnabled(not checked) self.reloadButton.setVisible(not checked) if checked: self.onSave() def onValue(self, var=None, value=None): """variable value is changed in the table""" self.saveIfNecessary() self.replot() def evaluate(self, name): """re-evaluate the text in the tableModel (happens when a global changes)""" self.tableModel.evaluate(name) self.programmingOptionsTable.evaluate(name) def refreshVarDict(self): """refresh the variable dictionary by checking all waveform dependencies""" allDependencies = set() [ channelUi.waveform.updateDependencies() for channelUi in self.awgChannelUiList ] [ allDependencies.update(channelUi.waveform.dependencies) for channelUi in self.awgChannelUiList ] default = lambda varname: { 'value': Q(1, 'us'), 'text': None } if varname.startswith('Duration') else { 'value': Q(0), 'text': None } deletions = [ varname for varname in self.settings.varDict if varname not in allDependencies ] [self.settings.varDict.pop(varname) for varname in deletions ] #remove all values that aren't dependencies anymore [ self.settings.varDict.setdefault(varname, default(varname)) for varname in allDependencies ] #add missing values self.settings.varDict.sort(key=lambda val: -1 if val[0].startswith( 'Duration') else ord(str(val[0])[0])) self.varDictChanged.emit(self.varAsOutputChannelDict) for channelUi in self.awgChannelUiList: channelUi.replot() def onDependenciesChanged(self, channel=None): """When dependencies change, refresh all variables""" self.tableModel.beginResetModel() self.refreshVarDict() self.tableModel.endResetModel() self.saveIfNecessary() def onFilename(self, basename): """filename combo box is changed. Open selected file""" basename = str(basename) filename = self.recentFiles[basename] if os.path.isfile(filename) and filename != self.settings.filename: self.openFile(filename) def onRemoveFile(self): """Remove file button is clicked. Remove filename from combo box.""" text = str(self.filenameComboBox.currentText()) index = self.filenameComboBox.findText(text) if text in self.recentFiles: self.recentFiles.pop(text) with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(-1) self.onFilename(w.currentText()) def onNewFile(self): """New button is clicked. Pop up dialog asking for new name, and create file.""" filename, _ = QtWidgets.QFileDialog.getSaveFileName( self, 'New File', self.lastDir, 'YAML (*.yml)') if filename: self.lastDir, basename = os.path.split(filename) self.recentFiles[basename] = filename self.settings.filename = filename with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(w.findText(basename)) self.onSaveFile() def onOpenFile(self): """Open file button is clicked. Pop up dialog asking for filename.""" filename, _ = QtWidgets.QFileDialog.getOpenFileName( self, 'Select File', self.lastDir, 'YAML (*.yml)') if filename: self.openFile(filename) def openFile(self, filename): """Open the file 'filename'""" if os.path.exists(filename): self.lastDir, basename = os.path.split(filename) self.recentFiles[basename] = filename self.settings.filename = filename with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(w.findText(basename)) with open(filename, 'r') as f: yamldata = yaml.load(f) variables = yamldata.get('variables') channelData = yamldata.get('channelData') self.tableModel.beginResetModel() [ channelUi.segmentModel.beginResetModel() for channelUi in self.awgChannelUiList ] if channelData: for channelUi in self.awgChannelUiList: if channelUi.channel < len(channelData): self.settings.channelSettingsList[channelUi.channel][ 'segmentDataRoot'] = self.convertListToNodes( channelData[channelUi.channel], isRoot=True) channelUi.segmentModel.root = self.settings.channelSettingsList[ channelUi.channel]['segmentDataRoot'] if variables: for varname, vardata in list(variables.items()): self.settings.varDict.setdefault(varname, dict()) self.settings.varDict[varname]['value'] = Q( vardata['value'], vardata['unit']) self.settings.varDict[varname]['text'] = vardata['text'] for channelUi in self.awgChannelUiList: channelUi.waveform.updateDependencies() channelUi.replot() self.onDependenciesChanged() self.tableModel.endResetModel() [ channelUi.segmentModel.endResetModel() for channelUi in self.awgChannelUiList ] [ channelUi.segmentView.expandAll() for channelUi in self.awgChannelUiList ] else: logging.getLogger(__name__).warning( "file '{0}' does not exist".format(filename)) if filename in self.recentFiles: del self.recentFiles[filename] with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList( list(self.recentFiles.keys())) w.setCurrentIndex(-1) def convertNodeToList(self, node): nodeList = [] for childNode in node.children: if childNode.nodeType == nodeTypes.segment: nodeList.append({ 'equation': childNode.equation, 'duration': childNode.duration, 'enabled': childNode.enabled }) elif childNode.nodeType == nodeTypes.segmentSet: nodeList.append({ 'repetitions': childNode.repetitions, 'enabled': childNode.enabled, 'segments': self.convertNodeToList(childNode) }) return nodeList def convertListToNodes(self, data, parent=None, enabled=True, repetitions=None, isRoot=False): node = AWGSegmentNode(parent=None) if isRoot else AWGSegmentSet( parent=parent, enabled=enabled, repetitions=repetitions) for segment in data: if 'duration' in segment: childNode = AWGSegment(parent=node, equation=segment['equation'], duration=segment['duration'], enabled=segment['enabled']) node.children.append(childNode) elif 'repetitions' in segment: segmentSet = self.convertListToNodes( segment['segments'], parent=node, enabled=segment['enabled'], repetitions=segment['repetitions']) node.children.append(segmentSet) else: logging.getLogger(__name__).error( "Unable to convert list to nodes") return node def onSaveFile(self): """Save button is clicked. Save data to segment file""" channelData = [] for channelSettings in self.settings.channelSettingsList: segmentData = self.convertNodeToList( channelSettings['segmentDataRoot']) channelData.append(segmentData) yamldata = {'channelData': channelData} variables = { varname: { 'value': float(varValueTextDict['value'].toStringTuple()[0]), 'unit': varValueTextDict['value'].toStringTuple()[1], 'text': varValueTextDict['text'] } for varname, varValueTextDict in list( self.settings.varDict.items()) } yamldata.update({'variables': variables}) with open(self.settings.filename, 'w') as f: yaml.dump(yamldata, f, default_flow_style=False) def onReloadFile(self): self.openFile(self.settings.filename) @QtCore.pyqtProperty(dict) def varAsOutputChannelDict(self): """dict of output channels, for use in scans""" for varname in self.settings.varDict: if varname not in self._varAsOutputChannelDict: self._varAsOutputChannelDict[varname] = VarAsOutputChannel( self, varname, self.globalDict) deletions = [ varname for varname in self._varAsOutputChannelDict if varname not in self.settings.varDict ] [self._varAsOutputChannelDict.pop(varname) for varname in deletions ] #remove all values that aren't dependencies anymore return self._varAsOutputChannelDict def close(self): self.saveConfig() numTempAreas = len(self.area.tempAreas) for i in range(numTempAreas): if len(self.area.tempAreas) > 0: self.area.tempAreas[0].win.close() super(AWGUi, self).close()
class 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
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])
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()