def layout(self): area = DockArea() self.win.setCentralWidget(area) self.win.resize(2000,1900) self.win.setWindowTitle(self.title) docks=[] docks.append(Dock("Parameters", size=(500,1000))) docks.append(Dock("Voltage", size=(1000,250))) docks.append(Dock("Recovery current", size=(1000,250))) docks.append(Dock("Phase plane", size=(1000,500))) docks.append(Dock("Test set", size=(500,1000))) docks.append(Dock("Analysis", size=(500,350))) area.addDock(docks[4], 'left') ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet) area.addDock(docks[0], 'right',docks[4]) area.addDock(docks[1], 'right') area.addDock(docks[2], 'bottom',docks[1]) area.addDock(docks[3], 'bottom',docks[2]) area.addDock(docks[5], 'bottom',docks[0]) for d,w in zip(docks, self.obj.widgets): d.addWidget(w)
def __init__(self, fit: chisurf.fitting.fit.FitGroup, parent: QtWidgets.QWidget, **kwargs): super().__init__(fit=fit, parent=parent) self.layout = QtWidgets.QVBoxLayout(self) self.data_x, self.data_y = None, None self.pltControl = DistributionPlotControl(self, parent=self, **kwargs) area = DockArea() self.layout.addWidget(area) hide_title = plot_settings['hideTitle'] d2 = Dock("Fit", size=(500, 400), hideTitle=hide_title) self.p1 = QtWidgets.QPlainTextEdit() p2 = pg.PlotWidget(useOpenGL=pyqtgraph_settings['useOpenGL']) d2.addWidget(p2) area.addDock(d2, 'top') distribution_plot = p2.getPlotItem() self.distribution_plot = distribution_plot self.distribution_curve = distribution_plot.plot(x=[0.0], y=[0.0], pen=pg.mkPen( colors['data'], width=lw), name='Data')
def layout(self): area = DockArea() self.win.setCentralWidget(area) self.win.resize(2000, 1900) self.win.setWindowTitle(self.title) docks = [] docks.append(Dock("Parameters", size=(500, 1000))) docks.append(Dock("Voltage", size=(1000, 250))) docks.append(Dock("Recovery current", size=(1000, 250))) docks.append(Dock("Phase plane", size=(1000, 500))) docks.append(Dock("Test set", size=(500, 1000))) docks.append(Dock("Analysis", size=(500, 350))) area.addDock( docks[4], 'left' ) ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet) area.addDock(docks[0], 'right', docks[4]) area.addDock(docks[1], 'right') area.addDock(docks[2], 'bottom', docks[1]) area.addDock(docks[3], 'bottom', docks[2]) area.addDock(docks[5], 'bottom', docks[0]) for d, w in zip(docks, self.obj.widgets): d.addWidget(w)
def setup_widgets(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) dock_position = Dock("Position") dock_area.addDock(dock_position) # Position 2d plot position_graphics = pg.GraphicsLayoutWidget() position_graphics.show() view = position_graphics.addViewBox() self.position_img = pg.ImageItem(border='w') view.addItem(self.position_img) dock_position.addWidget(position_graphics) # Status widget dock_status = Dock("Status", size=(800, 1)) dock_area.addDock(dock_status, 'top') cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.spin_box = Qt.QSpinBox(value=1) self.spin_box.setMaximum(10) self.spin_box.setSuffix(" Threshold") layout.addWidget(self.spin_box, 0, 6, 0, 1) dock_status.addWidget(cw) self.spin_box.valueChanged.connect(lambda value: self.send_command(str(value)))
def setup_widgets(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) dock_position = Dock("Position") dock_area.addDock(dock_position) # Position 2d plot position_graphics = pg.GraphicsLayoutWidget() position_graphics.show() view = position_graphics.addViewBox() self.position_img = pg.ImageItem(border='w') view.addItem(self.position_img) dock_position.addWidget(position_graphics) # Status widget dock_status = Dock("Status", size=(800, 1)) dock_area.addDock(dock_status, 'top') cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.spin_box = Qt.QSpinBox(value=1) self.spin_box.setMaximum(10) self.spin_box.setSuffix(" Threshold") layout.addWidget(self.spin_box, 0, 6, 0, 1) dock_status.addWidget(cw) self.spin_box.valueChanged.connect( lambda value: self.send_command(str(value)))
def __init__(self, scan_z, webcam_focus_lock, *args, **kwargs): super().__init__(*args, **kwargs) self.scan_z = scan_z self.filewarning = FileWarning() # Dock widget dockArea = DockArea() # Focus lock widget focusDock = Dock("Focus lock", size=(500, 500)) self.focusWidget = focus.FocusWidget(self.scan_z, webcam_focus_lock) focusDock.addWidget(self.focusWidget) dockArea.addDock(focusDock, "left") self.setWindowTitle('Tempesta - Focus lock edition') self.cwidget = QtGui.QWidget() self.setCentralWidget(self.cwidget) # Widgets' layout layout = QtGui.QGridLayout() self.cwidget.setLayout(layout) layout.addWidget(dockArea, 0, 0, 1, 1)
def __init__(self, fit: chisurf.fitting.fit.FitGroup, *args, **kwargs): super(ParameterScanPlot, self).__init__(fit) self.layout = QtWidgets.QVBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setSpacing(0) self.data_x, self.data_y = None, None self.pltControl = ParameterScanWidget(model=fit.model, parent=self) area = DockArea() self.layout.addWidget(area) hide_title = plot_settings['hideTitle'] d2 = Dock("Chi2-Surface", hideTitle=hide_title) self.p1 = QtWidgets.QPlainTextEdit() p2 = pg.PlotWidget() d2.addWidget(p2) area.addDock(d2, 'top') distribution_plot = p2.getPlotItem() self.distribution_plot = distribution_plot self.distribution_curve = distribution_plot.plot(x=[0.0], y=[0.0], pen=pg.mkPen( colors['data'], width=lw), name='Data')
def create_dock(self): area = DockArea() self.obj_graph['param']['dock'] = Dock("setting parameters") self.obj_graph['plot']['dock'] = Dock("graphic 1") self.obj_graph['plot2']['dock'] = Dock("graphic 2") area.addDock(self.obj_graph['param']['dock'], 'left') area.addDock(self.obj_graph['plot']['dock'], 'right') area.addDock(self.obj_graph['plot2']['dock'], 'bottom', self.obj_graph['plot']['dock']) self.setCentralWidget(area)
class MainWindow(QtWidgets.QMainWindow): """The only window of the application.""" def __init__(self, settings): super(MainWindow, self).__init__() self.settings = settings self.setupUi() self.dock_area = DockArea() self.setCentralWidget(self.dock_area) self.createDocks() self.loadSettings() self.setWindowTitle('Rb Lock') def setupUi(self): pass def createDocks(self): self.rb_lock_widget = RbLockWidget(self.settings, self) self.rb_lock_widget_dock = Dock('Rb Lock', widget=self.rb_lock_widget) self.dock_area.addDock(self.rb_lock_widget_dock) def loadSettings(self): """Load window state from self.settings""" self.settings.beginGroup('mainwindow') geometry = self.settings.value('geometry') state = self.settings.value('windowstate') dock_string = str(self.settings.value('dockstate')) if dock_string is not "": dock_state = eval(dock_string) self.dock_area.restoreState(dock_state) self.settings.endGroup() self.restoreGeometry(geometry) self.restoreState(state) def saveSettings(self): """Save window state to self.settings.""" self.settings.beginGroup('mainwindow') self.settings.setValue('geometry', self.saveGeometry()) self.settings.setValue('windowstate', self.saveState()) dock_state = self.dock_area.saveState() # dock_state returned here is a python dictionary. Coundn't find a good # way to save dicts in QSettings, hence just using representation # of it. self.settings.setValue('dockstate', repr(dock_state)) self.settings.endGroup() def closeEvent(self, event): self.rb_lock_widget.saveSettings() self.saveSettings()
def _add_btn_layout(self): # add a DockArea for buttons area = DockArea() dock = Dock("Functions") area.addDock(dock) area.show() self.vlayout.addWidget(area, 1, 1) btn_layout = pg.LayoutWidget() dock.addWidget(btn_layout) self.btn_layout = btn_layout
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()
def setup_widgets(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) dock_position = Dock("Position") dock_area.addDock(dock_position) # Position 2d plot position_graphics = pg.GraphicsLayoutWidget() position_graphics.show() view = position_graphics.addViewBox() self.position_img = pg.ImageItem(border='w') view.addItem(self.position_img) dock_position.addWidget(position_graphics)
def create_graph_views(self): """ Creates the window containing the graph views. :return: None """ dock_area = DockArea() self.setCentralWidget(dock_area) dock_3d = Dock('3D') dock_area.addDock(dock_3d) dock_1d = Dock('1D') dock_area.addDock(dock_1d, 'above', dock_3d) dock_2d = Dock('2D') dock_area.addDock(dock_2d, 'above', dock_3d) self.plot_3d = Plot3DWidget(self.model_wrapper, dock_3d) dock_3d.addWidget(self.plot_3d) self.plot_2d = Plot2DWidget(self.model_wrapper, self.statusBar(), dock_2d) dock_2d.addWidget(self.plot_2d) self.plot_1d = Plot1DWidget(self.model_wrapper, self.statusBar(), dock_1d) dock_1d.addWidget(self.plot_1d) # TODO: move away from this function dock_list = Dock('integration') dock_area.addDock(dock_list) dock_list.addWidget(IntegrationList(self.model_wrapper, dock_list))
def main(): app = QtWidgets.QApplication(sys.argv) win = QtWidgets.QMainWindow() area = DockArea() win.setCentralWidget(area) win.show() dock = Dock(name='Test Dock', area=area) area.addDock(dock) QtCore.QThread.sleep(2) dock.close() QtWidgets.QApplication.processEvents() sys.exit(app.exec_())
def setup_plots(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) dock_position = Dock("Position Correlation") dock_area.addDock(dock_position) # Position 2d plot position_graphics = pg.GraphicsLayoutWidget() position_graphics.show() view = position_graphics.addViewBox() self.position_img = pg.ImageItem(border='w') view.addItem(self.position_img) dock_position.addWidget(position_graphics)
def __init__(self, fit): super().__init__(fit=fit) self.trajectory = fit.model self.source = fit.model self.layout = QtWidgets.QVBoxLayout(self) area = DockArea() self.layout.addWidget(area) hide_title = chisurf.settings.gui['plot']['hideTitle'] d1 = Dock("RMSD") d2 = Dock("dRMSD") d3 = Dock("Energy") d4 = Dock("FRET") p1 = pg.PlotWidget() p2 = pg.PlotWidget() p3 = pg.PlotWidget() p4 = pg.PlotWidget() d1.addWidget(p1) d2.addWidget(p2) d3.addWidget(p3) d4.addWidget(p4) area.addDock(d1, 'top') area.addDock(d2, 'right', d1) area.addDock(d3, 'bottom') area.addDock(d4, 'right', d3) # RMSD - Curves self.rmsd_plot = p1.getPlotItem() self.drmsd_plot = p2.getPlotItem() self.energy_plot = p3.getPlotItem() self.fret_plot = p4.getPlotItem() lw = chisurf.settings.gui['plot']['line_width'] self.rmsd_curve = self.rmsd_plot.plot(x=[0.0], y=[0.0], pen=pg.mkPen(colors['irf'], width=lw), name='rmsd') self.drmsd_curve = self.drmsd_plot.plot(x=[0.0], y=[0.0], pen=pg.mkPen(colors['data'], width=lw), name='drmsd') self.energy_curve = self.energy_plot.plot(x=[0.0], y=[0.0], pen=pg.mkPen( colors['models'], width=lw), name='energy') self.fret_curve = self.fret_plot.plot(x=[0.0], y=[0.0], pen=pg.mkPen(colors['models'], width=lw), name='fret')
class Tab(QWidget): def __init__(self, num_tabs=3): super().__init__() self.num_tabs = num_tabs self.initUI() def initUI(self): self.layout = QGridLayout(self) self.dock_area = DockArea() self.layout.addWidget(self.dock_area) self.add_docks() def add_docks(self): self.d1 = QDockWidget('d1') self.d2 = QDockWidget('d2') self.dock_area.addDock(self.d1.dock)
def initDialog(self,results=None,KData=None,bDrawText=False): # 1) creates layouts dialog = QtGui.QDialog() mainLayout = QtGui.QHBoxLayout() rightLayout = QtGui.QVBoxLayout() mainLayout.addLayout(rightLayout) dialog.setLayout(mainLayout) dialog.setWindowTitle(('Strategy Results')) # 2) creates widgets from Widgets.pgCandleWidgetCross import pgCandleWidgetCross from Widgets.pgCrossAddition import pgCrossAddition from pyqtgraph.dockarea import DockArea,Dock area = DockArea() ## Create docks, place them into the window one at a time. ## Note that size arguments are only a suggestion; docks will still have to ## fill the entire dock area and obey the limits of their internal widgets. d1 = Dock("price", size=(200,100)) d2 = Dock("position", size=(200,100)) area.addDock(d1, 'bottom') area.addDock(d2, 'bottom') rightLayout.addWidget(area) pgCandleView = pgCandleWidgetCross(dataForCandle=KData) PyqtGraphindicators = pgCrossAddition() toShow = pgCandleView self.pricePlot(toShow) d1.addWidget(toShow) PyqtGraphPosition = pgCrossAddition() self.positionPlot(PyqtGraphPosition) d2.addWidget(PyqtGraphPosition) PyqtGraphPosition.showGrid(x=True, y=True) PyqtGraphPosition.setXLink(toShow) return dialog
def make_sequential_flowchart_with_gui(clsList, inputData=None, log=True): nodes, fc = make_sequential_flowchart(clsList, inputData=inputData) win = QtGui.QMainWindow() area = DockArea() win.setCentralWidget(area) for node in nodes: if node.useUi and node.uiClass is not None: nodeDock = Dock(node.name()) nodeDock.addWidget(node.ui) area.addDock(nodeDock) if log: logDock = Dock('Log') logDock.addWidget(plottrlog.setupLogging(makeDialog=False)) area.addDock(logDock, 'bottom') win.show() return nodes, fc, win
class UIWindow(object): def __init__(self): super().__init__() pg.setConfigOptions(imageAxisOrder='row-major') self.MainWindow = QtGui.QMainWindow() self.tabwidg = QtGui.QTabWidget() self.area = DockArea() self.plotDock = Dock("Plots", size=(400, 400)) self.surfaceDock = Dock("Contour", size=(250, 400)) self.controlDock = ControlDock() self.controlDock.setStretch(*(10, 100)) self.graph = Graph() self.contour = Contour() self.MainWindow.setGeometry(20, 50, 1200, 600) self.MainWindow.setObjectName("Monitor") self.MainWindow.setWindowTitle("AXUV tool") self.MainWindow.statusBar().showMessage('') self.MainWindow.setAcceptDrops(True) self.__setLayout() def __setLayout(self): self.MainWindow.setCentralWidget(self.tabwidg) self.tabwidg.addTab(self.area, "Data") self.area.addDock(self.plotDock, "right") self.area.addDock(self.controlDock, "left") self.area.addDock(self.surfaceDock, "bottom", self.controlDock) self.plotDock.addWidget(self.graph) self.surfaceDock.addWidget(self.contour) def showMain(self): self.MainWindow.show()
def run(self): # 2. Implement run() window = QMainWindow() version = self.build_settings['version'] window.setWindowTitle("real_time_vocoder.py v" + version) area = DockArea() d1 = Dock("Plot Widget", size=(800, 200), closable=False) d2 = Dock("Parameter Widget", size=(200, 200), closable=False) # parameter_widget2 = parameterWidget() # parameter_widget.setObjectName("F0Slider") # parameter_widget.setStyleSheet(""" # QSlider{ # background:red; # size:100px; # } # """) self.spectogram_widget = SpectrogramWidget() self.wave_widget = WaveWidget() self.mic = MicrophoneRecorder(True, self.spectogram_widget.read_collected, self.wave_widget.read_collected) # コントロールのレイアウト設定 self.createParamterWidget() d1.addWidget(self.spectogram_widget) d1.addWidget(self.wave_widget) d2.addWidget(self.mainControl) area.addDock(d1) area.addDock(d2, "right") interval = CHUNKS / FS t = QtCore.QTimer() t.timeout.connect(self.mic.read) t.start(interval / 1000) #QTimer takes ms window.resize(800, 400) window.setCentralWidget(area) window.show() self.app.aboutToQuit.connect(self.mic.close) return self.app.exec_() # 3. End run() with this line
def setup_status_widget(self, parent): # Visualizes the nodes + their connections + CPU usage # Status dock area showing setup dock_area = DockArea() parent.addTab(dock_area, 'Status') self.status_dock = Dock("Status") dock_area.addDock(self.status_dock) # GraphicsLayout to align graphics status_graphics_widget = pg.GraphicsLayoutWidget() status_graphics_widget.show() self.status_dock.addWidget(status_graphics_widget) try: self.configuration['receiver'] except KeyError: return # Create nodes with links from configuration file for converter/receiver for receiver_index, (receiver_name, receiver_settings) in enumerate(self.configuration['receiver'].items()): # Add receiver info view = status_graphics_widget.addViewBox(row=receiver_index, col=5, lockAspect=True, enableMouse=False) text = pg.TextItem('Receiver\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200)) text.setPos(0.5, 0.5) view.addItem(text) # Add corresponding producer info try: if self.configuration['converter']: try: actual_converter = self.configuration['converter'][receiver_name] view = status_graphics_widget.addViewBox(row=receiver_index, col=1, lockAspect=True, enableMouse=False) text = pg.TextItem('Producer\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200)) text.setPos(0.5, 0.5) view.addItem(text) view = status_graphics_widget.addViewBox(row=receiver_index, col=3, lockAspect=True, enableMouse=False) text = pg.TextItem('Converter\n%s' % receiver_settings, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200)) text.setPos(0.5, 0.5) view.addItem(text) except KeyError: # no converter for receiver pass except KeyError: # No converter defined in configruation pass
def setup_status_widget(self, parent): # Visualizes the nodes + their connections + CPU usage # Status dock area showing setup dock_area = DockArea() parent.addTab(dock_area, 'Status') self.status_dock = Dock("Status") dock_area.addDock(self.status_dock) # GraphicsLayout to align graphics status_graphics_widget = pg.GraphicsLayoutWidget() status_graphics_widget.show() self.status_dock.addWidget(status_graphics_widget) try: self.configuration['receiver'] except KeyError: return # Create nodes with links from configuration file for converter/receiver for receiver_index, (receiver_name, receiver_settings) in enumerate(self.configuration['receiver'].items()): # Add receiver info view = status_graphics_widget.addViewBox(row=receiver_index, col=5, lockAspect=True, enableMouse=False) text = pg.TextItem('Receiver\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200)) text.setPos(0.5, 0.5) view.addItem(text) # Add corresponding producer info try: if self.configuration['converter']: try: actual_converter = self.configuration['converter'][receiver_name] view = status_graphics_widget.addViewBox(row=receiver_index, col=1, lockAspect=True, enableMouse=False) text = pg.TextItem('Producer\n%s' % receiver_name, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200)) text.setPos(0.5, 0.5) view.addItem(text) view = status_graphics_widget.addViewBox(row=receiver_index, col=3, lockAspect=True, enableMouse=False) text = pg.TextItem('Converter\n%s' % receiver_settings, border='b', fill=(0, 0, 255, 100), anchor=(0.5, 0.5), color=(0, 0, 0, 200)) text.setPos(0.5, 0.5) view.addItem(text) except KeyError: # no converter for receiver pass except KeyError: # No converter defined in configruation pass
def create_dock(self): area = DockArea() self.obj_graph['param']['dock'] = Dock("setting parameters") self.obj_graph['plot']['dock'] = Dock("R (V) function of current (mA)") self.obj_graph['plot2']['dock'] = Dock("Phi (deg) function of current (mA)") area.addDock(self.obj_graph['param']['dock'], 'left') area.addDock(self.obj_graph['plot']['dock'],'right') area.addDock(self.obj_graph['plot2']['dock'],'bottom',self.obj_graph['plot']['dock']) self.setCentralWidget(area)
class PV_Setup(QWidget): """ This Widget sets up and shows all the PV necessary for SAXS/WAXS/GI-SAXS/GI-WAXS/ASAXS data collection """ def __init__(self,parent=None): QWidget.__init__(self, parent) self.motors={} self.scalars={} self.detectors={} self.devices={} self.vbLayout=QVBoxLayout(self) self.setupDockArea=DockArea(self) self.vbLayout.addWidget(self.setupDockArea) #Creating the docks self.motorDock=Dock("Motors",size=(300,300)) self.scalarDock=Dock("Scalars",size=(300,300)) self.detectorDock=Dock("Area Detectors",size=(300,300)) self.deviceDock=Dock("Devices",size=(300,300)) #Adding the Docks to the DockArea self.setupDockArea.addDock(self.detectorDock) self.setupDockArea.addDock(self.scalarDock) self.setupDockArea.addDock(self.motorDock) self.setupDockArea.addDock(self.deviceDock) #Moving the Docks w.r.t each other to position them as tabs self.setupDockArea.moveDock(self.detectorDock,'above',self.deviceDock) self.setupDockArea.moveDock(self.scalarDock,'above',self.detectorDock) self.setupDockArea.moveDock(self.motorDock,'above',self.scalarDock) #Populating the docks with other widgets self.motorPV=PVInfo_Widget(parent=self,pvType='Motor') self.motorDock.addWidget(self.motorPV.layout) self.scalarPV=PVInfo_Widget(parent=self,pvType='Scalar') self.scalarDock.addWidget(self.scalarPV.layout) self.detectorPV=PVInfo_Widget(parent=self,pvType='Detector') self.detectorDock.addWidget(self.detectorPV.layout) self.devicePV=PVInfo_Widget(parent=self,pvType='Device') self.deviceDock.addWidget(self.devicePV.layout)
def initDialogSummary(self, result, KData=None): # 1) creates layouts dialog = QtGui.QDialog() mainLayout = QtGui.QHBoxLayout() rightLayout = QtGui.QVBoxLayout() mainLayout.addLayout(rightLayout) dialog.setLayout(mainLayout) dialog.setWindowTitle(('Strategy Results')) import os, sys xpower = os.path.abspath( os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir, 'midProjects', 'histdataUI')) sys.path.append(xpower) from Widgets.pgCandleWidgetCross import pgCandleWidgetCross from Widgets.pgCrossAddition import pgCrossAddition from pyqtgraph.dockarea import DockArea, Dock area = DockArea() rightLayout.addWidget(area) # 2) creates widgets # 2.1)candle pgCandleView = pgCandleWidgetCross(dataForCandle=KData) dCandle = Dock("candles", closable=True, size=(200, 300)) ## give this dock the minimum possible size area.addDock(dCandle, 'bottom') dCandle.addWidget(pgCandleView) # 2) creates widgets # 2.3)position_cost if (True): PyqtGraphPositionCost = pgCrossAddition() self.availableCashPlot(PyqtGraphPositionCost) dAvailableCash = Dock("available_cash", closable=True, size=(200, 100)) area.addDock(dAvailableCash, 'bottom') dAvailableCash.addWidget(PyqtGraphPositionCost) PyqtGraphPositionCost.setXLink(pgCandleView) # 2.3)position_cost if (True): PyqtGraphPositionCost = pgCrossAddition() self.portfolioPlot(PyqtGraphPositionCost) dPortfolioValue = Dock("portfolio_value", closable=True, size=(200, 100)) area.addDock(dPortfolioValue, 'bottom') dPortfolioValue.addWidget(PyqtGraphPositionCost) PyqtGraphPositionCost.setXLink(pgCandleView) return dialog
def initDialogSummary(self,result,KData=None): # 1) creates layouts dialog = QtGui.QDialog() mainLayout = QtGui.QHBoxLayout() rightLayout = QtGui.QVBoxLayout() mainLayout.addLayout(rightLayout) dialog.setLayout(mainLayout) dialog.setWindowTitle(('Strategy Results')) import os,sys xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdataUI')) sys.path.append(xpower) from Widgets.pgCandleWidgetCross import pgCandleWidgetCross from Widgets.pgCrossAddition import pgCrossAddition from pyqtgraph.dockarea import DockArea,Dock area = DockArea() rightLayout.addWidget(area) # 2) creates widgets # 2.1)candle pgCandleView = pgCandleWidgetCross(dataForCandle=KData) dCandle = Dock("candles",closable=True, size=(200,300)) ## give this dock the minimum possible size area.addDock(dCandle, 'bottom') dCandle.addWidget(pgCandleView) # 2) creates widgets # 2.3)position_cost if(True): PyqtGraphPositionCost = pgCrossAddition() self.availableCashPlot(PyqtGraphPositionCost) dAvailableCash = Dock("available_cash",closable=True, size=(200,100)) area.addDock(dAvailableCash, 'bottom') dAvailableCash.addWidget(PyqtGraphPositionCost) PyqtGraphPositionCost.setXLink(pgCandleView) # 2.3)position_cost if(True): PyqtGraphPositionCost = pgCrossAddition() self.portfolioPlot(PyqtGraphPositionCost) dPortfolioValue = Dock("portfolio_value",closable=True, size=(200,100)) area.addDock(dPortfolioValue, 'bottom') dPortfolioValue.addWidget(PyqtGraphPositionCost) PyqtGraphPositionCost.setXLink(pgCandleView) return dialog
def __init__(self, fit: chisurf.fitting.fit.FitGroup, *args, **kwargs): super().__init__(fit=fit, *args, **kwargs) # plot control dialog self.pltControl = AvPlotControl(self, **kwargs) self.layout = QtWidgets.QVBoxLayout(self) area = DockArea() self.layout.addWidget(area) hide_title = chisurf.settings.gui['plot']['hideTitle'] d1 = Dock("quenching", size=(300, 300), hideTitle=hide_title) d2 = Dock("diffusion", size=(300, 300), hideTitle=hide_title) d3 = Dock("equilibrium", size=(300, 300), hideTitle=hide_title) area.addDock(d1, 'top') area.addDock(d2, 'right', d1) area.addDock(d3, 'bottom') self.quenching_widget = gl.GLViewWidget() self.quenching_widget.opts['distance'] = 100 d1.addWidget(self.quenching_widget)
class AnalysisDockWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'designer', 'analysis_dock.ui'), self) self.histogram_widget = HistogramWidget(self) self.tracks_widget = TracksWidget(self) self.intensities_widget = GraphMonitorWidget(self) self.dockarea = DockArea() self.layout().insertWidget(0, self.dockarea) self.histogram_dock = Dock(name='Histogram', closable=False) self.histogram_dock.addWidget(self.histogram_widget) self.dockarea.addDock(self.histogram_dock) self.tracks_dock = Dock(name='Trajectories', closable=False) self.tracks_dock.addWidget(self.tracks_widget) self.dockarea.addDock(self.tracks_dock) self.intensities_dock = Dock(name='Intensities', closable=False) self.intensities_dock.addWidget(self.intensities_widget) self.dockarea.addDock(self.intensities_dock)
def setup_widgets(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) # Occupancy Docks self.occupancy_images = [] for plane in range(3): # Loop over 3 * 2 plot widgets # Dock left dock_occcupancy = Dock("Occupancy plane %d" % 2 * plane, size=(100, 200)) dock_area.addDock(dock_occcupancy) occupancy_graphics = pg.GraphicsLayoutWidget() # Plot docks occupancy_graphics.show() view = occupancy_graphics.addViewBox() self.occupancy_images.append(pg.ImageItem(border='w')) view.addItem(self.occupancy_images[2 * plane]) view.setRange(QtCore.QRectF(0, 0, 80, 336)) dock_occcupancy.addWidget(occupancy_graphics) # Dock right dock_occcupancy_2 = Dock("Occupancy plane %d" % (2 * plane + 1), size=(100, 200)) dock_area.addDock(dock_occcupancy_2, 'right', dock_occcupancy) occupancy_graphics = pg.GraphicsLayoutWidget() # Plot docks occupancy_graphics.show() view = occupancy_graphics.addViewBox() self.occupancy_images.append(pg.ImageItem(border='w')) view.addItem(self.occupancy_images[2 * plane + 1]) view.setRange(QtCore.QRectF(0, 0, 80, 336)) dock_occcupancy_2.addWidget(occupancy_graphics) # dock_event_status = Dock("Event status", size=(400, 400)) # dock_trigger_status = Dock("Trigger status", size=(400, 400)) # dock_area.addDock(dock_trigger_status, 'above', dock_service_records) # dock_area.addDock(dock_event_status, 'above', dock_trigger_status) dock_status = Dock("Status", size=(800, 40)) dock_area.addDock(dock_status, 'top') # Status dock on top cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz") self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz") self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz") self.timestamp_label = QtGui.QLabel("Data Timestamp\n") self.plot_delay_label = QtGui.QLabel("Plot Delay\n") self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n") self.spin_box = Qt.QSpinBox(value=0) self.spin_box.setMaximum(1000000) self.spin_box.setSuffix(" Readouts") self.reset_button = QtGui.QPushButton('Reset') self.noisy_checkbox = QtGui.QCheckBox('Mask noisy pixels') layout.addWidget(self.timestamp_label, 0, 0, 0, 1) layout.addWidget(self.plot_delay_label, 0, 1, 0, 1) layout.addWidget(self.rate_label, 0, 2, 0, 1) layout.addWidget(self.hit_rate_label, 0, 3, 0, 1) layout.addWidget(self.event_rate_label, 0, 4, 0, 1) layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1) layout.addWidget(self.spin_box, 0, 6, 0, 1) layout.addWidget(self.noisy_checkbox, 0, 7, 0, 1) layout.addWidget(self.reset_button, 0, 8, 0, 1) dock_status.addWidget(cw) # Connect widgets self.reset_button.clicked.connect(lambda: self.send_command('RESET')) self.spin_box.valueChanged.connect(lambda value: self.send_command(str(value))) self.noisy_checkbox.stateChanged.connect(lambda value: self.send_command('MASK %d' % value)) # event_status_widget = pg.PlotWidget() # self.event_status_plot = event_status_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) # event_status_widget.showGrid(y=True) # dock_event_status.addWidget(event_status_widget) # trigger_status_widget = pg.PlotWidget() # self.trigger_status_plot = trigger_status_widget.plot(np.linspace(-0.5, 7.5, 9), np.zeros((8)), stepMode=True) # trigger_status_widget.showGrid(y=True) # dock_trigger_status.addWidget(trigger_status_widget) self.plot_delay = 0
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(QMainWindow, Ui_MainWindow): """Where all the action happens.""" def __init__(self, settings): super(MainWindow, self).__init__() self.settings = settings self.setupUi(self) # MainWindow is a collection of widgets in their respective docks. # We make DockArea our central widget self.dock_area = DockArea() self.setCentralWidget(self.dock_area) self.createDocks() self.initAfterCreatingDockWidgets() self.loadSettings() self.connectSignalsToSlots() # all signals in place, send out the first image # self.image_browser.populateAndEmitImageInfo() self.image_browser.initialEmit() self.roi_editor_h.initialEmit() self.roi_editor_v.initialEmit() self.roi_editor_int.initialEmit() self.roi_editor_err.initialEmit() self.loadPlugins() def loadPlugins(self): """Looks for all plugins and creates menu entries, signals and slots for them.""" self.pluginSignalMapper = QSignalMapper(self) for p in plugin_list: click_action = QAction(p.name, self) self.menuPlugins.addAction(click_action) self.connect(click_action, SIGNAL("triggered()"), self.pluginSignalMapper, SLOT("map()")) self.pluginSignalMapper.setMapping(click_action, QString(p.name)) self.connect(self.pluginSignalMapper, SIGNAL("mapped(const QString &)"), self.image_browser.handlePluginClicked) def createDocks(self): """Create all dock widgets and add them to DockArea.""" self.image_view = ImageView(self.settings, self) self.image_browser = ImageBrowser(self.settings, self) self.fitter = Fitter(self.settings, self) self.roi_editor_h = RoiEditor(self.settings, self.image_view, self, name='ROIH', pen=(1, 9), axis=1) self.roi_editor_v = RoiEditor(self.settings, self.image_view, self, name='ROIV', pen=(1, 1), axis=0) self.roi_editor_int = RoiEditor(self.settings, self.image_view, self, name='ROI Int', pen=(1, 2), axis=1) self.roi_editor_err = RoiEditor(self.settings, self.image_view, self, name='ROI Err', pen=(1, 3), axis=1) self.roi_plot_h = Plot1d(parent=self, title='ROI H') self.roi_plot_v = Plot1d(parent=self, title='ROI V') self.analyzer = Analyzer(self.settings, parent=self) # Create docks for all widgets self.dock_image_view = Dock('Image View', widget=self.image_view) self.dock_image_browser = Dock('Image Browser', widget=self.image_browser) self.dock_fitter = Dock('Fitter', widget=self.fitter) self.dock_roi_h = Dock('ROIH', widget=self.roi_editor_h) self.dock_roi_v = Dock('ROIV', widget=self.roi_editor_v) self.dock_roi_int = Dock('ROI Int', widget=self.roi_editor_int) self.dock_roi_err = Dock('ROI Err', widget=self.roi_editor_err) self.dock_roi_plot_h = Dock('ROIH Plot', widget=self.roi_plot_h) self.dock_roi_plot_v = Dock('ROIV Plot', widget=self.roi_plot_v) self.dock_analyzer = Dock('Analyze', widget=self.analyzer) self.dock_area.addDock(self.dock_image_view, position='top') self.dock_area.addDock(self.dock_image_browser, position='right', relativeTo=self.dock_image_view) self.dock_area.addDock(self.dock_fitter, position='left', relativeTo=self.dock_image_view) self.dock_area.addDock(self.dock_roi_h, position='bottom', relativeTo=self.dock_fitter) self.dock_area.addDock(self.dock_roi_v, position='below', relativeTo=self.dock_roi_h) self.dock_area.addDock(self.dock_roi_int, position='below', relativeTo=self.dock_roi_v) self.dock_area.addDock(self.dock_roi_err, position='below', relativeTo=self.dock_roi_int) self.dock_area.addDock(self.dock_roi_plot_h, position='below', relativeTo=self.dock_image_view) self.dock_area.addDock(self.dock_roi_plot_v, position='right', relativeTo=self.dock_roi_plot_h) self.dock_area.addDock(self.dock_analyzer, position='top', relativeTo=self.dock_image_browser) def initAfterCreatingDockWidgets(self): self.setWindowTitle(self.image_browser.current_directory) def connectSignalsToSlots(self): self.actionOpen_Directory.triggered.connect(self.image_browser.handleOpenDirectoryAction) self.actionDark_File.triggered.connect(self.image_browser.handleDarkFileAction) self.actionRefresh.triggered.connect(self.image_browser.handleRefreshAction) self.actionSave.triggered.connect(self.image_browser.handleSaveAnalysis) self.image_browser.windowTitleChanged.connect(self.setWindowTitle) # self.image_browser.imageChanged.connect(self.image_view.handleImageChanged) self.image_browser.imageChanged.connect(self.fitter.handleImageChanged) self.image_browser.imageChanged.connect(self.analyzer.handleImageChanged) self.roi_editor_int.roiChanged.connect(self.image_browser.handleRoiChanged) self.roi_editor_err.roiChanged.connect(self.image_browser.handleROIErrChanged) self.roi_editor_h.roiChanged.connect(self.image_browser.handleROIHChanged) self.roi_editor_v.roiChanged.connect(self.image_browser.handleROIVChanged) self.roi_editor_h.roiChanged.connect(self.fitter.handleROIHChanged) self.roi_editor_h.roiChanged.connect(self.analyzer.handleROIHChanged) self.roi_editor_v.roiChanged.connect(self.fitter.handleROIVChanged) self.roi_editor_v.roiChanged.connect(self.analyzer.handleROIVChanged) self.roi_editor_int.roiChanged.connect(self.fitter.handleROIIntChanged) self.roi_editor_int.roiChanged.connect(self.analyzer.handleROIIntChanged) self.roi_editor_err.roiChanged.connect(self.fitter.handleROIErrChanged) self.roi_editor_err.roiChanged.connect(self.analyzer.handleROIErrChanged) self.image_view.doubleClicked.connect(self.roi_editor_h.centerROI) self.image_view.doubleClicked.connect(self.roi_editor_v.centerROI) self.fitter.imageChanged.connect(self.image_view.handleImageChanged) self.fitter.horDataChanged.connect(self.roi_plot_h.handleDataChanged) self.fitter.verDataChanged.connect(self.roi_plot_v.handleDataChanged) self.fitter.doneFitting.connect(self.analyzer.handleDoneFitting) def loadSettings(self): """Load window state from self.settings""" self.settings.beginGroup('mainwindow') geometry = self.settings.value('geometry').toByteArray() state = self.settings.value('windowstate').toByteArray() dock_string = str(self.settings.value('dockstate').toString()) if dock_string is not "": dock_state = eval(dock_string) self.dock_area.restoreState(dock_state) self.settings.endGroup() self.restoreGeometry(geometry) self.restoreState(state) def saveSettings(self): """Save window state to self.settings.""" self.settings.beginGroup('mainwindow') self.settings.setValue('geometry', self.saveGeometry()) self.settings.setValue('windowstate', self.saveState()) dock_state = self.dock_area.saveState() # dock_state returned here is a python dictionary. Coundn't find a good # way to save dicts in QSettings, hence just using representation # of it. self.settings.setValue('dockstate', repr(dock_state)) self.settings.endGroup() def closeEvent(self, event): self.saveSettings() self.image_browser.saveSettings() self.roi_editor_int.saveSettings() self.roi_editor_err.saveSettings() self.roi_editor_v.saveSettings() self.roi_editor_h.saveSettings() self.analyzer.saveSettings() super(MainWindow, self).closeEvent(event) def setWindowTitle(self, newTitle=''): """Prepend IP-BEC to all window titles.""" title = 'IP-BEC: ' + newTitle super(MainWindow, self).setWindowTitle(title)
from pyqtgraph.dockarea import DockArea, Dock pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') app = QtGui.QApplication([]) win = QtGui.QMainWindow() area = DockArea() win.setCentralWidget(area) win.resize(1000,500) win.setWindowTitle('pyqtgraph example: dockarea') d1 = Dock("Dock 1", size=(500,300)) d2 = Dock("Dock 2", size=(500,300)) area.addDock(d1, 'left') ## place d1 at left edge of dock area (it will fill the whole space since there are no other docks yet) area.addDock(d2, 'right') for e in sorted(dir(pg.PlotWidget().plotItem)): print e # p=pg.plot() # for e in sorted(dir(p)): # print e w=pg.PlotWidget() w.setWindowTitle('pyqtgraph example: PlotSpeedTest') w.setRange(QtCore.QRectF(0, -20, 5000, 30)) w.setLabel('bottom', 'Index', units='B') curve = w.plot()
class GraphArea(pg.QtGui.QWidget): def __init__(self, parent=None, src=None): super(GraphArea, self).__init__(parent) self.src = src # TODO: Save defaults self.cur_patient = self.src.patient_folders[0] self.auto_default_range = settings.auto_default_range # Depth control if settings.annotation_on: self.dc = GUI.DepthControl(vpf=1./40) else: self.dc = GUI.DepthControl() self.dc.s.selected_updated.connect(self.depths_updated) self.src.s.repaint_dc.connect(self.dc.repaint) self.dc.display_hashes = settings.preprocess_hashes # Dict of depths with their plot widgets self.selected_depths = {} # Current link group self.cur_link = None # Try out other horizontal policies # self.setSizePolicy( # pg.QtGui.QSizePolicy.MinimumExpanding, # pg.QtGui.QSizePolicy.Ignored) # self.setMinimumWidth(1) # Signals for interacting with all children self.s = UpdateSignal() # Progress bar self.pbar = None self.init_UI() def init_UI(self): # Patient selection hbox = pg.QtGui.QHBoxLayout() self.patient_txt = pg.QtGui.QLabel('Patient: ') self.pcombo = pg.ComboBox( items=self.src.patient_folders, default=self.cur_patient) # Connect patient update signal self.pcombo.currentIndexChanged.connect(self.patient_update) hbox.addWidget(self.patient_txt, stretch=0) hbox.addWidget(self.pcombo, stretch=1) # Channel selection self.channel_txt = pg.QtGui.QLabel('Channel: ') ''' Assuming all channels found in first depth - change later! ''' channels = self.src.get_channels(self.cur_patient, 0) self.ccombo = pg.ComboBox(items=channels) # Add context menu channel combobox to manage channels self.init_channel_menu() self.ccombo.setContextMenuPolicy(pg.QtCore.Qt.CustomContextMenu) self.ccombo.customContextMenuRequested.connect(self.channel_menu) # Connect channel update signal self.ccombo.currentIndexChanged.connect(self.update_plots) hbox.addWidget(self.channel_txt, stretch=0) hbox.addWidget(self.ccombo, stretch=1) # Button to toggle annotations if settings.annotation_on: self.toggle_annotation = QtGui.QPushButton('Annotate') self.toggle_annotation.setCheckable(True) self.toggle_annotation.setChecked(not settings.hide_annotation) hbox.addWidget(self.toggle_annotation, stretch=0) ## View controls for all plots ## view_hbox = QtGui.QHBoxLayout() # view_hbox.addWidget(QtGui.QLabel('Range Controls:'), stretch=0) view_hbox.addStretch(1) self.update_x_range_button = QtGui.QPushButton('X') view_hbox.addWidget(self.update_x_range_button, stretch=0) self.x_range_min = QtGui.QLineEdit(str(settings.default_x_range[0])) self.x_range_max = QtGui.QLineEdit(str(settings.default_x_range[1])) view_hbox.addWidget(QtGui.QLabel('Min (ms):'), stretch=0) view_hbox.addWidget(self.x_range_min, stretch=0) view_hbox.addWidget(QtGui.QLabel('Max (ms):'), stretch=0) view_hbox.addWidget(self.x_range_max, stretch=0) self.update_y_range_button = QtGui.QPushButton('Y') view_hbox.addWidget(self.update_y_range_button, stretch=0) self.y_range_min = QtGui.QLineEdit(str(settings.default_y_range[0])) self.y_range_max = QtGui.QLineEdit(str(settings.default_y_range[1])) view_hbox.addWidget(QtGui.QLabel('Min (mV):'), stretch=0) view_hbox.addWidget(self.y_range_min, stretch=0) view_hbox.addWidget(QtGui.QLabel('Max (mV):'), stretch=0) view_hbox.addWidget(self.y_range_max, stretch=0) # Connect signal # self.update_x_range_button.clicked.connect( # lambda: self.s.x_range_updated.emit( # (float(self.x_range_min.text()), float(self.x_range_max.text())) # ) # ) # self.update_y_range_button.clicked.connect( # lambda: self.s.y_range_updated.emit( # (float(self.y_range_min.text()), float(self.y_range_max.text())) # ) # ) self.update_x_range_button.clicked.connect(self.emit_x_range_updated) self.update_y_range_button.clicked.connect(self.emit_y_range_updated) # Scroll area self.scroll = ScrollArea() # Main display self.dock_area = DockArea() self.min_plot_height = settings.plot_height # Scroll widget self.scroll.setWidgetResizable(True) self.scroll.setWidget(self.dock_area) # Refresh self.update_plots() self.update_depths() # Construct layout vbox = pg.QtGui.QVBoxLayout() vbox.addLayout(hbox) # Hide individual control (Give dynamic option to enable later?) # vbox.addLayout(view_hbox) # Position depth control and main displays hbox2 = pg.QtGui.QHBoxLayout() vbox2 = pg.QtGui.QVBoxLayout() vbox2.setMargin(0) hbox2.setMargin(0) # Add horizontal slider # self.horizontal_axis = XAxisControl() vbox2.addWidget(self.scroll, stretch=9) # vbox2.addWidget(self.horizontal_axis, stretch=1) # 90% to 10% graph to depth control split; add customizability? hbox2.addLayout(vbox2, stretch=9) # Set the depth control inside an optional vbox for annotation possibility if settings.annotation_on: vbox3 = pg.QtGui.QVBoxLayout() vbox3.setMargin(0) vbox3.setSpacing(2) vbox3.setContentsMargins(0,0,0,0) # Depth control depth_annotate = GUI.AnnotateDepths(self.src, self.dc) depth_annotate.s.annotations_updated.connect(self.update_annotations) # depth_annotate.hide() # depth_annotate.setSizePolicy(pg.QtGui.QSizePolicy.Minimum, pg.QtGui.QSizePolicy.Minimum) vbox3.addWidget(self.dc, stretch=10) vbox3.addWidget(depth_annotate, stretch=0) hbox2.addLayout(vbox3, stretch=1) else: hbox2.addWidget(self.dc, stretch=1) vbox.addLayout(hbox2) self.setLayout(vbox) ''' Default settings for channel combo box ''' # Set default checked state based on settings only_data = self.src.only_data_channels only_spike = self.src.only_spike_channels if only_data and not only_spike: self.only_data_action.setChecked(True) self.only_data() if only_spike and not only_data: self.only_spike_action.setChecked(True) self.only_spike() self.show() # Initialize channel context menu def init_channel_menu(self): self.cmenu = pg.QtGui.QMenu(self) self.only_data_action = pg.QtGui.QAction('Only Data', self.cmenu, checkable=True) # self.only_data_action.setStatusTip('Only display channels with data') self.only_data_action.triggered.connect(self.only_data) self.only_spike_action = pg.QtGui.QAction('Only Spikes', self.cmenu, checkable=True) # self.only_spike_action.setStatusTip('Only display RAW data') self.only_spike_action.triggered.connect(self.only_spike) # Add to menu self.cmenu.addAction(self.only_spike_action) self.cmenu.addAction(self.only_data_action) # Display channel context menu at right location def channel_menu(self, point): self.cmenu.exec_(self.ccombo.mapToGlobal(point)) def only_data(self): channels = self.src.get_channels(self.cur_patient, 0) only_data = self.only_data_action.isChecked() only_spike = self.only_spike_action.isChecked() if only_data: channels = self.src.parse_data_channels(channels) if only_spike: # Also toggle off the other filter, since not compatible self.only_spike_action.toggle() self.ccombo.setItems(channels) def only_spike(self): channels = self.src.get_channels(self.cur_patient, 0) only_data = self.only_data_action.isChecked() only_spike = self.only_spike_action.isChecked() if only_spike: channels = self.src.parse_spike_channels(channels) if only_data: self.only_data_action.toggle() self.ccombo.setItems(channels) def update_depths(self): # Update depth control patient = self.src.patients[self.cur_patient] self.dc.updateDepths(patient.depths) # Update patient and hashrates if necessary if settings.preprocess_hashes: self.dc.updatePatient(patient) self.dc.updateSelected(None) self.dc.repaint() def patient_update(self): # Update current patient and channel list self.cur_patient = self.pcombo.value() ''' Assuming all channels found in first depth ''' channels = self.src.get_channels(self.cur_patient, 0) if self.only_data_action.isChecked(): channels = self.src.parse_data_channels(channels) elif self.only_spike_action.isChecked(): channels = self.src.parse_spike_channels(channels) self.ccombo.setItems(channels) # Clear and reset various parts of GUI when patient changes self.update_depths() # Just run an update to notify everything about channel as well self.update_plots() # Remove all selected depths # self.selected_depths.clear() for depth in self.selected_depths.keys(): # Clear docks self.selected_depths[depth].close() self.selected_depths.pop(depth) self.update_layout() self.update_plots() # @timeit def update_plots(self): # Update individual plots patient = self.src.patients[self.cur_patient] channel = self.ccombo.value() auto_range = False # Notify depth control if necessary if settings.preprocess_hashes: if channel in settings.spike_channels: self.dc.updateChannel(channel) self.emit_x_range_updated() self.emit_y_range_updated() else: self.dc.updateChannel(None) auto_range = True self.dc.repaint() # Progress bar update if self.pbar is not None: self.pbar.set_description('Plotting data') # Update all the split dock widgets for depth, dock in self.selected_depths.iteritems(): dock.widgets[0].update(self.src, patient, channel, depth) if auto_range: dock.widgets[0].auto_range_contents() if self.pbar is not None: self.pbar.update(1) # @timeit def depths_updated(self): self.dc.repaint() previous = set(self.selected_depths.iterkeys()) updated = set(self.dc.selected) # Remove depths in previous not in updated purge = previous - updated # Add plot items necessary for new depths add = updated - previous # Instantiate progress bar total_length = len(purge) + len(add) + (2 * len(updated)) if total_length > 0: print('\nVisualizing for channel: %s' % self.ccombo.value()) self.pbar = tqdm.tqdm(total=total_length) ### Delete previous docks ### # cur = time() for depth in purge: # Progress bar description if self.pbar is not None: self.pbar.set_description('Deleting docks') # Clear widget # Seems bugged - does this actually close the widget? self.selected_depths[depth].widgets[0].close() ### Disconnect signals ### self.s.x_range_updated.disconnect(self.selected_depths[depth].widgets[0].main_widget.set_x_range) self.s.y_range_updated.disconnect(self.selected_depths[depth].widgets[0].main_widget.set_y_range) if settings.annotation_on: self.toggle_annotation.toggled.disconnect(self.selected_depths[depth].widgets[0].toggle_second_widget) # Clear docks self.selected_depths[depth].close() self.selected_depths.pop(depth) if self.pbar is not None: self.pbar.update(1) ### Add new docks ### # print('Time to delete: %f' % (time() - cur)) # cur = time() for depth in add: # Progress bar update if self.pbar is not None: self.pbar.set_description('Loading data') # Wrap the widget in a dock widget = GUI.DefaultPlotWidget(self.src) self.add_plot_dock(depth, widget) if self.pbar is not None: self.pbar.update(1) # print('Time to add: %f' % (time() - cur)) # cur = time() ### Update layout ### self.update_layout() # print('Time to update layout: %f' % (time() - cur)) # cur = time() ### Update plots ### self.update_plots() # print('Time to update plots: %f' % (time() - cur)) # Update annotate toggle if settings.annotation_on: self.toggle_annotation.setChecked(not settings.hide_annotation) # Update views # print('updating') if self.auto_default_range: self.emit_x_range_updated() self.emit_y_range_updated() # print('updated') if self.pbar is not None: self.pbar.close() self.pbar = None # @timeit def update_layout(self): length = len(self.selected_depths) self.dock_area.setMinimumSize(0, length * self.min_plot_height) # Progress bar update if self.pbar is not None: self.pbar.set_description('Populating visual elements') for depth in sorted(self.selected_depths.iterkeys(), reverse=True): dock = self.selected_depths[depth] self.dock_area.addDock(dock, position='bottom') if self.pbar is not None: self.pbar.update(1) def add_plot_dock(self, depth, widget): dock = Dock(depth, size=(1,1), closable=False, autoOrientation=False) split_dock_widget = SplitDockWidget(widget) ### Connect signals ### self.s.x_range_updated.connect(widget.set_x_range) self.s.y_range_updated.connect(widget.set_y_range) widget.s.title_updated.connect(dock.setTitle) if settings.annotation_on: self.toggle_annotation.toggled.connect(split_dock_widget.toggle_second_widget) dock.addWidget(split_dock_widget) self.selected_depths[depth] = dock ## Emit the signals necessary to update all the plots ## def emit_x_range_updated(self): self.s.x_range_updated.emit( (float(self.x_range_min.text()), float(self.x_range_max.text())) ) def emit_y_range_updated(self): self.s.y_range_updated.emit( (float(self.y_range_min.text()), float(self.y_range_max.text())) ) # Update annotations across all the necessary depths for the patient def update_annotations(self, update): # Update is tuple of form (depths, labels) depths, labels = update ch_nr = self.src.get_channel_number(self.ccombo.value()) patient = self.src.patients[self.cur_patient] for depth in depths: # Update all annotation widgets if depth in self.selected_depths: dock = self.selected_depths[depth] dock.widgets[0].update_annotation(labels) # Update patient for depths not currently displayed else: # Calculate current id cur_id = (depth, ch_nr) # Check if depth_labels already has labels if cur_id not in patient.depth_labels: patient.depth_labels[cur_id] = list(labels) else: for label in labels: if label not in patient.depth_labels[cur_id]: patient.depth_labels[cur_id].append(label)
class MarkWriteMainWindow(QtGui.QMainWindow): sigProjectChanged = QtCore.Signal(object) # new_project sigResetProjectData = QtCore.Signal(object) # project sigSelectedPenDataUpdate = QtCore.Signal(object, object) # (smin,smax), segmentdata sigSegmentCreated = QtCore.Signal(object) # new segment sigSegmentRemoved = QtCore.Signal(object, object) # segment being removed, # segment index in list sigAppSettingsUpdated = QtCore.Signal(object, #dict of app settings that changed object,) #ful settings dict sigActiveObjectChanged = QtCore.Signal(object, object) #new, old active objects _mainwin_instance=None _appdirs = None def __init__(self, qtapp): global SETTINGS QtGui.QMainWindow.__init__(self) MarkWriteMainWindow._mainwin_instance = self self._current_project = None self._activeobject = None self._predefinedtags = loadPredefinedSegmentTagList(u'default.tag') # create qt actions used by menu, toolbar, or both self.createGuiActions() # init GUI related stuff self.setupGUI(qtapp) self.sigProjectChanged.connect(self.handleProjectChange) self.sigSelectedPenDataUpdate.connect(self.handleSelectedPenDataUpdate) self.sigAppSettingsUpdated.connect(self._penDataTimeLineWidget.handleUpdatedSettingsEvent) self.sigAppSettingsUpdated.connect(self._penDataSpatialViewWidget.handleUpdatedSettingsEvent) self.sigAppSettingsUpdated.connect(self._selectedPenDataViewWidget.handleUpdatedSettingsEvent) @staticmethod def instance(): return MarkWriteMainWindow._mainwin_instance @property def project(self): return self._current_project @property def activeobject(self): return self._activeobject def setActiveObject(self, timeperioddatatype=None): prevactiveobj = self._activeobject self._activeobject = timeperioddatatype if timeperioddatatype is None: self._activeobject = self.project.selectedtimeregion #print "Settings active object:",self._activeobject if isinstance(self._activeobject,PenDataSegment): #print "**Setting region:",self._activeobject self._segmenttree.doNotSetActiveObject=True self.project.selectedtimeregion.setRegion(self._activeobject.timerange) self._segmenttree.doNotSetActiveObject=False self.removeSegmentAction.setEnabled(True) else: self.removeSegmentAction.setEnabled(False) self.sigActiveObjectChanged.emit(self._activeobject,prevactiveobj) return self._activeobject @property def predefinedtags(self): if self.project: return self.project.autodetected_segment_tags + self._predefinedtags return self._predefinedtags def createGuiActions(self): # # File Menu / Toolbar Related Actions # atext = 'Open a supported digitized pen position ' \ 'file format.' aicon = 'folder&32.png' self.openFileAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), '&Open', self) self.openFileAction.setShortcut('Ctrl+O') self.openFileAction.setEnabled(True) self.openFileAction.setStatusTip(atext) self.openFileAction.triggered.connect(self.openFile) #atext = 'Save Current Project.' #aicon = 'save&32.png' #self.saveProjectAction = ContextualStateAction( # QtGui.QIcon(getIconFilePath(aicon)), # 'Save', # self) #self.saveProjectAction.setShortcut('Ctrl+S') #self.saveProjectAction.setEnabled(False) #self.saveProjectAction.setStatusTip(atext) #self.saveProjectAction.triggered.connect(self.saveProject) atext = 'Export Pen Sample Level Report to a File.' aicon = 'sample_report&32.png' self.exportSampleReportAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Sample Report', self) #self.exportSampleReportAction.setShortcut('Ctrl+S') self.exportSampleReportAction.setEnabled(False) self.exportSampleReportAction.setStatusTip(atext) self.exportSampleReportAction.triggered.connect( self.createPenSampleLevelReportFile) atext = 'Export Segment Level Report to a File.' aicon = 'segment_report&32.png' self.exportSegmentReportAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Segment Report', self) #self.exportSampleReportAction.setShortcut('Ctrl+S') self.exportSegmentReportAction.setEnabled(False) self.exportSegmentReportAction.setStatusTip(atext) self.exportSegmentReportAction.triggered.connect( self.createSegmentLevelReportFile) self.exportSampleReportAction.enableActionsList.append(self.exportSegmentReportAction) atext = 'Open the Application Settings Dialog.' aicon = 'settings&32.png' self.showProjectSettingsDialogAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), '&Settings', self) self.showProjectSettingsDialogAction.setShortcut('Alt+S') self.showProjectSettingsDialogAction.setEnabled(True) self.showProjectSettingsDialogAction.setStatusTip(atext) self.showProjectSettingsDialogAction.triggered.connect( self.handleDisplayAppSettingsDialogEvent) atext = 'Close the MarkWrite Application. Any data segmention will be lost!' aicon = 'shut_down&32.png' self.exitAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Exit', self) self.exitAction.setShortcut('Ctrl+Alt+Q') self.exitAction.setEnabled(True) self.exitAction.setStatusTip(atext) self.exitAction.triggered.connect(self.closeEvent) # # Selection Menu / Toolbar Related Actions # atext = 'Create a Segment Using Currently Selected Pen Data.' aicon = 'accept&32.png' self.createSegmentAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Create &New', self) self.createSegmentAction.setShortcut(QtCore.Qt.Key_Return) self.createSegmentAction.setEnabled(False) self.createSegmentAction.setStatusTip(atext) self.createSegmentAction.triggered.connect(self.createSegment) atext = 'Delete the Selected Segment and any of the segments children.' aicon = 'delete&32.png' self.removeSegmentAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), '&Delete', self) self.removeSegmentAction.setShortcut('Ctrl+D') self.removeSegmentAction.setEnabled(False) self.removeSegmentAction.setStatusTip(atext) self.removeSegmentAction.triggered.connect(self.removeSegment) # # Timeline Plot Zoom Related Actions # atext = 'Increase Timeplot Horizontal Magnification 2x' aicon = 'zoom_in&32.png' self.zoomInTimelineAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Zoom In 2x', self) self.zoomInTimelineAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Plus) self.zoomInTimelineAction.setEnabled(False) self.zoomInTimelineAction.setStatusTip(atext) self.zoomInTimelineAction.triggered.connect(self.zoomInTimeline) atext = 'Decrease Timeplot Horizontal Magnification 2x' aicon = 'zoom_out&32.png' self.zoomOutTimelineAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Zoom Out 2x', self) self.zoomOutTimelineAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Minus) self.zoomOutTimelineAction.setEnabled(False) self.zoomOutTimelineAction.setStatusTip(atext) self.zoomOutTimelineAction.triggered.connect(self.zoomOutTimeline) self.exportSampleReportAction.enableActionsList.append(self.zoomInTimelineAction) self.exportSampleReportAction.enableActionsList.append(self.zoomOutTimelineAction) atext = 'Reposition Views around Selected Time Period' aicon = 'target&32.png' self.gotoSelectedTimePeriodAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Go To Selected Time Period', self) self.gotoSelectedTimePeriodAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Home) self.gotoSelectedTimePeriodAction.setEnabled(False) self.gotoSelectedTimePeriodAction.setStatusTip(atext) self.gotoSelectedTimePeriodAction.triggered.connect(self.gotoSelectTimelinePeriod) atext = "Move selected time period forward, so that it's start time is one sample after the current selection's end time" aicon = 'move_selection_forward&32.png' self.forwardSelectionAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Jump Forward', self) self.forwardSelectionAction.setShortcut(QtCore.Qt.Key_Right) self.forwardSelectionAction.setEnabled(False) self.forwardSelectionAction.setStatusTip(atext) self.forwardSelectionAction.triggered.connect(self.jumpTimeSelectionForward) atext = "Move selected time period backward, so that it's end time is one sample prior to the current selection's start time." aicon = 'move_selection_backward&32.png' self.backwardSelectionAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Jump Backward', self) self.backwardSelectionAction.setShortcut(QtCore.Qt.Key_Left) self.backwardSelectionAction.setEnabled(False) self.backwardSelectionAction.setStatusTip(atext) self.backwardSelectionAction.triggered.connect(self.jumpTimeSelectionBackward) atext = 'Increase Timeline Selection End Time' aicon = 'increase_select_endtime&32.png' self.increaseSelectionEndPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Increase Selection End', self) self.increaseSelectionEndPointAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Right) self.increaseSelectionEndPointAction.setEnabled(False) self.increaseSelectionEndPointAction.setStatusTip(atext) self.increaseSelectionEndPointAction.triggered.connect(self.increaseSelectionEndPointTime) atext = 'Decrease Timeline Selection End Time' aicon = 'descrease_select_endtime&32.png' self.decreaseSelectionEndPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Decrease Selection End', self) self.decreaseSelectionEndPointAction.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_Left) self.decreaseSelectionEndPointAction.setEnabled(False) self.decreaseSelectionEndPointAction.setStatusTip(atext) self.decreaseSelectionEndPointAction.triggered.connect(self.decreaseSelectionEndPointTime) #====================================== atext = 'Increase Timeline Selection Start Time' aicon = 'increase_select_starttime&32.png' self.increaseSelectionStartPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Increase Selection Start', self) self.increaseSelectionStartPointAction.setShortcut(QtCore.Qt.ALT + QtCore.Qt.Key_Right) self.increaseSelectionStartPointAction.setEnabled(False) self.increaseSelectionStartPointAction.setStatusTip(atext) self.increaseSelectionStartPointAction.triggered.connect(self.increaseSelectionStartPointTime) atext = 'Decrease Timeline Selection Start Time' aicon = 'decrease_select_starttime&32.png' self.decreaseSelectionStartPointAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'Decrease Selection Start', self) self.decreaseSelectionStartPointAction.setShortcut(QtCore.Qt.ALT + QtCore.Qt.Key_Left) self.decreaseSelectionStartPointAction.setEnabled(False) self.decreaseSelectionStartPointAction.setStatusTip(atext) self.decreaseSelectionStartPointAction.triggered.connect(self.decreaseSelectionStartPointTime) self.exportSampleReportAction.enableActionsList.append(self.zoomInTimelineAction) self.exportSampleReportAction.enableActionsList.append(self.zoomOutTimelineAction) self.exportSampleReportAction.enableActionsList.append(self.gotoSelectedTimePeriodAction) self.exportSampleReportAction.enableActionsList.append(self.decreaseSelectionEndPointAction) self.exportSampleReportAction.enableActionsList.append(self.increaseSelectionEndPointAction) self.exportSampleReportAction.enableActionsList.append(self.decreaseSelectionStartPointAction) self.exportSampleReportAction.enableActionsList.append(self.increaseSelectionStartPointAction) self.exportSampleReportAction.enableActionsList.append(self.forwardSelectionAction) self.exportSampleReportAction.enableActionsList.append(self.backwardSelectionAction) # # Help Menu / Toolbar Related Actions # atext = 'Displays the MarkWrite About Dialog.' aicon = 'info&32.png' self.aboutAction = ContextualStateAction( QtGui.QIcon(getIconFilePath(aicon)), 'About', self) self.aboutAction.setEnabled(True) self.aboutAction.setStatusTip(atext) self.aboutAction.triggered.connect(self.showAboutDialog) def setupGUI(self, app): ''' :return: ''' # ## Create Main GUI Menu Bar # menubar = self.menuBar() fileMenu = menubar.addMenu('&File') fileMenu.addAction(self.openFileAction) #fileMenu.addAction(self.saveProjectAction) fileMenu.addAction(self.showProjectSettingsDialogAction) fileMenu.addSeparator() exportMenu = fileMenu.addMenu("&Export") exportMenu.addAction(self.exportSampleReportAction) exportMenu.addAction(self.exportSegmentReportAction) exportMenu.addSeparator() self.customReportActions=[] for custom_report in custom_report_classes: a = exportMenu.addAction(custom_report.reportlabel(), lambda: self.exportCustomReport(custom_report)) a.setEnabled(False) self.customReportActions.append(a) self.exportSampleReportAction.enableActionsList.append(a) fileMenu.addSeparator() fileMenu.addAction(self.exitAction) segmentMenu = menubar.addMenu('&Segment') segmentMenu.addAction(self.createSegmentAction) segmentMenu.addAction(self.removeSegmentAction) helpMenu = menubar.addMenu('&Help') helpMenu.addAction(self.aboutAction) self.toolbarFile = self.addToolBar('File') self.toolbarFile.addAction(self.openFileAction) #self.toolbarFile.addAction(self.saveProjectAction) self.toolbarFile.addAction(self.showProjectSettingsDialogAction) self.toolbarFile.addAction(self.exportSampleReportAction) self.toolbarFile.addAction(self.exportSegmentReportAction) self.toolbarsegment = self.addToolBar('Segment') self.toolbarsegment.addAction(self.createSegmentAction) self.toolbarsegment.addAction(self.removeSegmentAction) self.toolbartimelineview = self.addToolBar('Timeline View') self.toolbartimelineview.addAction(self.zoomInTimelineAction) self.toolbartimelineview.addAction(self.zoomOutTimelineAction) self.toolbarsegment = self.addToolBar('Timeline Selection') self.toolbarsegment.addAction(self.gotoSelectedTimePeriodAction) self.toolbarsegment.addAction(self.decreaseSelectionStartPointAction) self.toolbarsegment.addAction(self.increaseSelectionStartPointAction) self.toolbarsegment.addAction(self.backwardSelectionAction) self.toolbarsegment.addAction(self.forwardSelectionAction) self.toolbarsegment.addAction(self.decreaseSelectionEndPointAction) self.toolbarsegment.addAction(self.increaseSelectionEndPointAction) self.toolbarHelp = self.addToolBar('Help') self.toolbarHelp.addAction(self.aboutAction) # ## Create App Dock Area # self._dockarea = DockArea() self.setCentralWidget(self._dockarea) # Enable antialiasing for prettier plots pg.setConfigOptions(antialias=True) # Create Docking Layout def addDock(name, inner_widget=None): ww, wh = DEFAULT_WIN_SIZE dpos, (dw, dh) = DEFAULT_DOCK_PLACEMENT[name] if isinstance(dpos, basestring): self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]), dpos) else: self._dockarea.addDock(Dock(name, size=[ww * dw, wh * dh]), dpos[0], self._dockarea.docks[dpos[1]]) if inner_widget: self._dockarea.docks[name].addWidget(inner_widget) from markwrite.gui.selecteddataview import SelectedPointsPlotWidget from markwrite.gui.spatialview import PenDataSpatialPlotWidget from markwrite.gui.timelineplot import PenDataTemporalPlotWidget from markwrite.gui.segmenttree import SegmentInfoDockArea self._segmenttree = SegmentInfoDockArea() addDock(u"Segment Tree", self._segmenttree) self._penDataTimeLineWidget = PenDataTemporalPlotWidget() self._penDataSpatialViewWidget = PenDataSpatialPlotWidget() addDock(u"Timeline", self._penDataTimeLineWidget) addDock(u"Spatial View", self._penDataSpatialViewWidget) self._selectedPenDataViewWidget = SelectedPointsPlotWidget() addDock(u"Selected Data", self._selectedPenDataViewWidget) # ## Do Misc. GUI setup. # self.setWindowIcon(QtGui.QIcon(getIconFilePath('edit&32.png'))) self.statusBar().showMessage('Ready') self.updateAppTitle() self.resize(*DEFAULT_WIN_SIZE) @property def penDataTemporalPlotWidget(self): return self._penDataTimeLineWidget def updateAppTitle(self): if self._current_project is None: fileName = u'' else: fileName = self._current_project.name fileName = u'{0} : '.format(fileName) app_title = u'MarkWrite' full_title = u'{0}{1}'.format(fileName, app_title) self.setWindowTitle(full_title) def showAboutDialog(self): QtGui.QMessageBox.about(self, ABOUT_DIALOG_TITLE, ABOUT_DIALOG_TEXT) self.sender().enableAndDisableActions() def openFile(self): file_path = fileOpenDlg() if file_path: file_path = file_path[0] if len(file_path) > 0: try: wmproj = MarkWriteProject(file_path=file_path,mwapp=self) self.createSegmentAction.setEnabled(True) self.sigProjectChanged.emit(wmproj) self.sigResetProjectData.emit(wmproj) except: import traceback traceback.print_exc() ErrorDialog.info_text = u"An error occurred while " \ u"opening:\n%s\nMarkWrite will " \ u"now close." % ( file_path) ErrorDialog().display() self.closeEvent(u'FORCE_EXIT') def createPenSampleLevelReportFile(self): default_file_name = u"pen_samples_{0}.txt".format(self.project.name) file_path = fileSaveDlg(initFileName=default_file_name, prompt="Export Pen Sample Report") if file_path: PenSampleReportExporter().export(file_path, self.project) def createSegmentLevelReportFile(self): default_file_name = u"segments_{0}.txt".format(self.project.name) file_path = fileSaveDlg(initFileName=default_file_name, prompt="Export Segment Level Report") if file_path: SegmentLevelReportExporter().export(file_path, self.project) def exportCustomReport(self,reportcls): default_file_name = u"{}_{}.txt".format(reportcls.outputfileprefix(),self.project.name) file_path = fileSaveDlg(initFileName=default_file_name, prompt="Export %s"%(reportcls.reportlabel())) if file_path: reportcls().export(file_path, self.project) def createSegment(self): """ Displays the Create Segment dialog. If dialog is not cancelled and segment name length >0, then create a new segment and add to the projects segment list. :return: """ if self.createSegmentAction.isEnabled(): # Shrink timeline selection region to fit start and end time # of possible segment being created. selectedtimeperiod = self.project.selectedtimeperiod[:] pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*selectedtimeperiod) if len(pendata_ix_range)>0: segmenttimeperiod = self.project.pendata['time'][pendata_ix_range] self.project.selectedtimeregion.setRegion(segmenttimeperiod) tag, ok = showSegmentNameDialog(self.predefinedtags) tag = unicode(tag).strip().replace('\t', "#") if len(tag) > 0 and ok: psid = self.project.getSelectedDataSegmentIDs()[0] new_segment = self.project.createSegmentFromSelectedPenData(tag, psid) self.handleSelectedPenDataUpdate(None,None) self.sigSegmentCreated.emit(new_segment) self.setActiveObject(new_segment) else: # If segment creation was cancelled or failed, then reset # timeline selection region to original time period. self.project.selectedtimeregion.setRegion(selectedtimeperiod) else: ErrorDialog.info_text = u"Segment Creation Failed.\nNo selected " \ u"pen data." ErrorDialog().display() def removeSegment(self): ConfirmAction.text = 'Delete Segment Confirmation' ConfirmAction.info_text = "Are you sure you want to <b>permanently deleted</b> the currently selected segment?" \ "<br><br>" \ "Any children of this segment will also be deleted." yes = ConfirmAction.display() if not yes: return segment = self.activeobject if segment and segment.parent is not None: seg_ix = segment.parent.getChildIndex(segment) # Decrement the pendata array 'segment_id' field for elements within # the segment being removed so that # of segments that contain each # pen point can be tracked allpendata = self.project.pendata segment_filter = (allpendata['time'] >= segment.starttime) & ( allpendata['time'] <= segment.endtime) allpendata['segment_id'][segment_filter] = segment.parent.id self.setActiveObject(self.project.selectedtimeregion) self.handleSelectedPenDataUpdate(None,None) self.sigSegmentRemoved.emit(segment, seg_ix) segment.parent.removeChild(segment) else: print " - Remove action IGNORED" print "<< removeSegment" def handleProjectChange(self, project): if self._current_project: pass self._current_project = project self.setActiveObject(self.project.selectedtimeregion) self.updateAppTitle() #self.saveProjectAction.setEnabled(project.modified) self.exportSampleReportAction.setEnabled(True) def zoomInTimeline(self): # TODO: Move method to _penDataTimeLineWidget self._penDataTimeLineWidget.getPlotItem().getViewBox().scaleBy(x=0.5) def zoomOutTimeline(self): # TODO: Move method to _penDataTimeLineWidget self._penDataTimeLineWidget.getPlotItem().getViewBox().scaleBy(x=2.0)#,center=(xmin+xmax)/2) def gotoSelectTimelinePeriod(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax , selpendat= self._penDataTimeLineWidget.currentSelection.selectedtimerangeanddata xpad = (xmax-xmin)/2 pdat=self.project.pendata rx=(max(0,xmin-xpad),min(xmax+xpad,self._penDataTimeLineWidget.maxTime)) if SETTINGS['timeplot_enable_ymouse']: ry = ( min(selpendat['x'].min(), selpendat['y'].min()), max(selpendat['x'].max(), selpendat['y'].max())) else: ry = (0, max(pdat['x'].max(),pdat['y'].max())) self._penDataTimeLineWidget.getPlotItem().setRange(xRange=rx, yRange=ry) def jumpTimeSelectionForward(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(pendata_ix_range): nix_min = pendata_ix_range[1]+1 if self.project.pendata['pressure'][nix_min]==0.0: start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix next_starts = start_ixs[start_ixs>nix_min] if len(next_starts)>0: nix_min=next_starts[0] else: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved forward.<br>Reason: NTs index not available.") return nxmin = self.project.pendata['time'][nix_min] nxmax = min(nxmin +(xmax-xmin), self.project.pendata['time'][-1]) if nxmin >= nxmax: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved forward.<br>Reason: End of data reached.") return self.project.selectedtimeregion.setRegion([nxmin,nxmax]) (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmax >= vmax: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmax-vmax)*1.25) def jumpTimeSelectionBackward(self): # TODO: Move method to _penDataTimeLineWidget if 0: xmin, xmax = self.project.selectedtimeregion.getRegion() nxmax =xmin-0.001 nxmin = max(nxmax-(xmax-xmin),0.0) pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(nxmin,nxmax) if len(pendata_ix_range): segmenttimeperiod = self.project.pendata['time'][pendata_ix_range] self.project.selectedtimeregion.setRegion(segmenttimeperiod) (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmin < vmin: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25) else: xmin, xmax = self.project.selectedtimeregion.getRegion() pendata_ix_range = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(pendata_ix_range): nix_max = pendata_ix_range[0]-1 if nix_max<=0: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: NTe index out of bounds.") return if self.project.pendata['pressure'][nix_max]==0.0: start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix prev_stops = stop_ixs[stop_ixs<=nix_max] if len(prev_stops)>0: nix_max=prev_stops[-1] else: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: NTe index not available.") return nxmax = self.project.pendata['time'][nix_max] nxmin = max(nxmax -(xmax-xmin), 0.0) if nxmin >= nxmax: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be moved backward.<br>Reason: End of data reached.") return self.project.selectedtimeregion.setRegion([nxmin,nxmax]) (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmin <= vmin: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25) def increaseSelectionEndPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix next_max_ix = stop_ixs[stop_ixs>(max_ix+1)][0] #print "org_max_ix, new_max_ix",max_ix,next_max_ix #print 'new start , end samples: ',self.project.pendata[[min_ix, next_max_ix]] if next_max_ix < self.project.pendata.shape[0]: segmenttimeperiod = self.project.pendata['time'][[min_ix, next_max_ix]] min_ix, next_max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod) self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, next_max_ix]]) _,nxmax=segmenttimeperiod (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmax >= vmax: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmax-vmax)*1.25) else: infoDlg(title=u"Action Aborted", prompt=u"The selected time period can not be extended<br>as it is at the end of the data samples.") def decreaseSelectionEndPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds if np.all(self.project.nonzero_pressure_mask[min_ix:max_ix]): self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) return start_ixs, stop_ixs, lengths=self.project.nonzero_region_ix prev_maxs = stop_ixs[stop_ixs<max_ix] if prev_maxs.shape[0]>0: if prev_maxs[-1] > min_ix: prev_max_ix = prev_maxs[-1] segmenttimeperiod = self.project.pendata['time'][[min_ix, prev_max_ix]] min_ix, max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod) self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) else: infoDlg(title=u"Action Aborted", prompt=u"The end time of the selected time period can not be decreased further<br>without it being equal to the selected periods start time.") def increaseSelectionStartPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds if np.all(self.project.nonzero_pressure_mask[min_ix:max_ix]): self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) return start_ixs,stop_ixs,lengths=self.project.nonzero_region_ix higher_starts=start_ixs[start_ixs>(min_ix)] if len(higher_starts)==0: infoDlg(title=u"Action Aborted", prompt=u"The start time of the selected time period can not be increased<br> any further; it is the last IPS run of the file.") elif higher_starts[0]>=max_ix-1: infoDlg(title=u"Action Aborted", prompt=u"The start time of the selected time period can not be further increased<br> without it exceeding the selected periods end time.") else: segmenttimeperiod = self.project.pendata['time'][[higher_starts[0], max_ix]] self.project.selectedtimeregion.setRegion(segmenttimeperiod) def decreaseSelectionStartPointTime(self): # TODO: Move method to _penDataTimeLineWidget xmin, xmax = self.project.selectedtimeregion.getRegion() ix_bounds = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(xmin, xmax) if len(ix_bounds)>0: min_ix, max_ix = ix_bounds start_ixs, stop_ixs, lengths=self.project.nonzero_region_ix prev_starts = start_ixs[start_ixs<min_ix] if len(prev_starts)>0 and prev_starts[-1] >= 0: prev_start_ix = prev_starts[-1] segmenttimeperiod = self.project.pendata['time'][[prev_start_ix, max_ix]] min_ix, max_ix = self.project.segmentset.calculateTrimmedSegmentIndexBoundsFromTimeRange(*segmenttimeperiod) self.project.selectedtimeregion.setRegion(self.project.pendata['time'][[min_ix, max_ix]]) nxmin,_=segmenttimeperiod (vmin,vmax),(_,_)=self._penDataTimeLineWidget.getPlotItem().getViewBox().viewRange() if nxmin < vmin: self._penDataTimeLineWidget.getPlotItem().getViewBox().translateBy(x=(nxmin-vmin)*1.25) def handleSelectedPenDataUpdate(self, timeperiod, pendata): #print '>> App.handleSelectedPenDataUpdate:',timeperiod self.createSegmentAction.setEnabled( self.project and self.project.isSelectedDataValidForNewSegment()) #print '<< App.handleSelectedPenDataUpdate' def handleDisplayAppSettingsDialogEvent(self): usersettings = readPickle(self._appdirs.user_config_dir,u'usersettings.pkl') updatedsettings, allsettings, savestate, ok = ProjectSettingsDialog.getProjectSettings(self, usersettings) if ok is True: writePickle(self._appdirs.user_config_dir,u'usersettings.pkl', savestate) if self.project and len(updatedsettings)>0: self.sigAppSettingsUpdated.emit(updatedsettings, allsettings) def closeEvent(self, event): if event == u'FORCE_EXIT': QtCore.QCoreApplication.instance().quit() return exitapp = ExitApplication.display() if exitapp: pass if event: event.accept() else: QtCore.QCoreApplication.instance().quit() else: if event: event.ignore() def __del__(self): pass
class H5Plotter(QtGui.QMainWindow): def __init__(self, file): super(H5Plotter, self).__init__() view_box = SearchableH5View(H5File(file)) self.view = view_box.tree_view self.match_model = self.view.model() self.model = self.match_model.sourceModel() self.dock_area = DockArea() self.layout = QtGui.QSplitter(Qt.Horizontal) self.setCentralWidget(self.layout) self.view.activated.connect(self.load_plot) self.layout.addWidget(view_box) self.layout.addWidget(self.dock_area) self.layout.setStretchFactor(0, 0) self.layout.setStretchFactor(1, 1) self.setWindowIcon(QtGui.QIcon("icon.ico")) QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_N), self, lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveDown)) QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_P), self, lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveUp)) QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_F), self, lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveRight)) QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_B), self, lambda: self.move_view_cursor(QtGui.QAbstractItemView.MoveLeft)) QtGui.QShortcut(QtGui.QKeySequence(Qt.CTRL | Qt.Key_S), self, view_box.search_box.setFocus) view_menu = self.menuBar().addMenu("View") toggle_attrs_action = QtGui.QAction("Attributes Visible", view_menu) toggle_attrs_action.setCheckable(True) toggle_attrs_action.triggered.connect(self.match_model.toggle_attrs_visible) view_menu.addAction(toggle_attrs_action) toggle_junk_action = QtGui.QAction("Junk Visible", view_menu) toggle_junk_action.setCheckable(True) toggle_junk_action.triggered.connect(self.match_model.toggle_junk_visible) view_menu.addAction(toggle_junk_action) def move_view_cursor(self, cursor_action): self.view.setFocus(Qt.OtherFocusReason) self.view.setCurrentIndex(self.view.moveCursor(cursor_action, Qt.NoModifier)) def load_plot(self, index): 'given an index referring to an H5Dataset, puts a plot corresponding to that dataset in the plot area' source_index = self.match_model.mapToSource(index) item = self.model.itemFromIndex(source_index) if isinstance(item.row, H5DatasetRow) and item.row.plot is None: labels = [] axes = [] for d in item.group.dims: try: label, ds = d.items()[0] labels.append(label) axes.append(ds[:]) except IndexError: print 'Could not find axis in item', item labels.append('') axes.append(None) except RuntimeError: print 'Mac bug? Probably no axis available' dock = self.make_dock(item.name, item.group[:], labels, axes) self.dock_area.addDock(dock) item.plot = dock dock.closeClicked.connect(lambda: item.__setattr__('plot', None)) def make_dock(self, name, array, labels=None, axes=None): 'returns a dockable plot widget' labels = {pos: l for l, pos in zip(labels, ('bottom', 'left'))} if len(array.shape) in (2, 3): if len(array.shape) == 2: d = CrossSectionDock(name=name, area=self.dock_area) if len(array.shape) == 3: d = MoviePlotDock(array, name=name, area=self.dock_area) pos, scale = None, None if axes is not None: pos = [0, 0] scale = [1, 1] if axes[0] is not None: pos[0] = axes[0][0] scale[0] = axes[0][1] - axes[0][0] if axes[1] is not None: pos[1] = axes[1][0] scale[1] = axes[1][1] - axes[1][0] d.setImage(array, pos=pos, scale=scale) if labels is not None: d.setLabels(labels['bottom'], labels['left'], name) if len(array.shape) == 1: w = CrosshairPlotWidget(labels=labels) if axes and axes[0] is not None: w.plot(axes[0], array) else: w.plot(array) d = CloseableDock(name=name, widget=w, area=self.dock_area) return d
def initDialogSymbol(self,results=None,KData=None,bDrawText=False,InKLine = False): # 1) creates layouts dialog = QtGui.QDialog() mainLayout = QtGui.QHBoxLayout() rightLayout = QtGui.QVBoxLayout() mainLayout.addLayout(rightLayout) dialog.setLayout(mainLayout) dialog.setWindowTitle(('Strategy Results')) import os,sys xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdataUI')) sys.path.append(xpower) from Widgets.pgCandleWidgetCross import pgCandleWidgetCross from Widgets.pgCrossAddition import pgCrossAddition from pyqtgraph.dockarea import DockArea,Dock area = DockArea() rightLayout.addWidget(area) # 2) creates widgets # 2.1)candle pgCandleView = pgCandleWidgetCross(dataForCandle=KData) self.pricePlot(pgCandleView) if(InKLine): self.indicatorsPlot(pgCandleView) #self.signalPlot(pgCandleView,yBuy = KData.take([1],axis=1),ySell = KData.take([1],axis=1)) self.signalPlot(pgCandleView) dCandle = Dock("candles",closable=True, size=(200,300)) ## give this dock the minimum possible size area.addDock(dCandle, 'bottom') dCandle.addWidget(pgCandleView) # 2.2)long_pnl 当前position_pnl曲线 if(True): PyqtGraphPnl = pgCrossAddition() self.longPnlPlot(PyqtGraphPnl,bDrawText=bDrawText) long_pnl = np.array(self.results.long_pnl) self.signalPlot(PyqtGraphPnl,yBuy = long_pnl,ySell = long_pnl) dPnl = Dock("long_pnl", closable=True, size=(200,100)) area.addDock(dPnl, 'bottom') dPnl.addWidget(PyqtGraphPnl) PyqtGraphPnl.setXLink(pgCandleView) # 2.3)long_cost if(True): PyqtGraphPositionCost = pgCrossAddition() self.longCostPlot(PyqtGraphPositionCost) dPositionCost = Dock("long_cost",closable=True, size=(200,100)) area.addDock(dPositionCost, 'bottom') dPositionCost.addWidget(PyqtGraphPositionCost) PyqtGraphPositionCost.setXLink(pgCandleView) # 2.2)long_pnl 当前position_pnl曲线 if(True): PyqtGraphPnl = pgCrossAddition() self.shortPnlPlot(PyqtGraphPnl,bDrawText=bDrawText) short_pnl = np.array(self.results.short_pnl) self.signalPlot(PyqtGraphPnl,yBuy = short_pnl,ySell = short_pnl) dPnl = Dock("short_pnl", closable=True, size=(200,100)) area.addDock(dPnl, 'bottom') dPnl.addWidget(PyqtGraphPnl) PyqtGraphPnl.setXLink(pgCandleView) # 2.3)long_cost if(True): PyqtGraphPositionCost = pgCrossAddition() self.shortCostPlot(PyqtGraphPositionCost) dPositionCost = Dock("short_cost",closable=True, size=(200,100)) area.addDock(dPositionCost, 'bottom') dPositionCost.addWidget(PyqtGraphPositionCost) PyqtGraphPositionCost.setXLink(pgCandleView) # 2.3)position_volume if(False): PyqtGraphPosition = pgCrossAddition() self.positionVolumePlot(PyqtGraphPosition) dPosition = Dock("position_volume",closable=True, size=(200,100)) area.addDock(dPosition, 'bottom') dPosition.addWidget(PyqtGraphPosition) PyqtGraphPosition.setXLink(pgCandleView) # 2.4)portfolio 总资产变动曲线 cash + equity if(True): PyqtGraphPortfolio = pgCrossAddition() self.positionValuePlot(PyqtGraphPortfolio) dPortfolio = Dock("portfolio", closable=True,size=(200,100)) area.addDock(dPortfolio, 'bottom') dPortfolio.addWidget(PyqtGraphPortfolio) PyqtGraphPortfolio.setXLink(pgCandleView) # 2.5)indicator if(True): PyqtGraphindicators = pgCrossAddition() self.pricePlot(PyqtGraphindicators) self.indicatorsPlot(PyqtGraphindicators) self.signalPlot(PyqtGraphindicators) dIndicator = Dock("indicator",closable=True, size=(200,100)) dIndicator.addWidget(PyqtGraphindicators) area.addDock(dIndicator, 'bottom', dCandle) PyqtGraphindicators.setXLink(pgCandleView) # 2.2)position_pnl 当前position_pnl曲线 if(False): PyqtGraphPortfolioInstruments = pgCrossAddition() self.instrumentPnlPlot(PyqtGraphPortfolioInstruments,bDrawText=bDrawText) position_pnl = np.array(self.results.position_pnl) self.signalPlot(PyqtGraphPortfolioInstruments,yBuy = position_pnl,ySell = position_pnl) dPnl = Dock("instrumentsPNL", closable=True, size=(200,100)) area.addDock(dPnl, 'bottom',dPositionCost) dPnl.addWidget(PyqtGraphPortfolioInstruments) PyqtGraphPortfolioInstruments.setXLink(pgCandleView) return dialog
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))
class MainWindow(QtGui.QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.setWindowTitle("Liveplot") self.dockarea = DockArea() self.setCentralWidget(self.dockarea) self.namelist = NameList(self) self.addDockWidget(QtConst.LeftDockWidgetArea, self.namelist) self.ctx = zmq.Context() sock = self.ctx.socket(zmq.SUB) sock.bind('tcp://127.0.0.1:7755') sock.setsockopt(zmq.SUBSCRIBE, '') self.conn = ZMQSocket(sock) self.conn.readyRead.connect(lambda: self.read_from(self.conn)) self.bytes = bytearray() self.target_size = 0 self.meta = None self.insert_dock_right = True self.conns = [] def accept(self): logging.debug('connection accepted') conn = self.listener.nextPendingConnection() if hasattr(socket, 'fromfd'): socket.fromfd(conn.socketDescriptor(), socket.AF_INET, socket.SOCK_STREAM).setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**22) self.conns.append(conn) conn.readyRead.connect(lambda: self.read_from(conn)) # noinspection PyNoneFunctionAssignment def read_from(self, conn): logging.debug('reading data') if not self.target_size: self.meta = conn._socket.recv_json() self.target_size = self.meta['arrsize'] if self.target_size > 0: n = self.target_size - len(self.bytes) data = bytearray(conn.read(n)) self.bytes.extend(data) if len(self.bytes) == self.target_size: self.process_bytes() if conn.bytesAvailable(): self.read_from(conn) def process_bytes(self): self.target_size = 0 if len(self.bytes) > 0: arr = np.frombuffer(buffer(self.bytes), dtype=self.meta['dtype']) try: arr.resize(self.meta['shape']) except ValueError: arr = arr.reshape(self.meta['shape']) else: arr = None self.bytes = bytearray() self.do_operation(arr) def do_operation(self, arr=None): def clear(name): self.namelist[name].clear() def close(name): self.namelist[name].close() def remove(name): del self.namelist[name] meta = self.meta operation = meta['operation'] name = meta['name'] if name in self.namelist: pw = self.namelist[name] if pw.closed: pw.closed = False self.dockarea.addDock(pw) else: if name != "*" and operation != "remove" and ("rank" in meta): pw = self.add_new_plot(meta['rank'], name) return if operation == 'clear' and name == "*": map(clear, self.namelist.keys()) if operation == 'close' and name == "*": map(close, self.namelist.keys()) if operation == 'remove' and name == "*": map(remove, self.namelist.keys()) return if operation == 'clear': pw.clear() if operation == 'close': pw.close() if operation == 'remove': del self.namelist[name] elif operation == 'plot_y': start_step = meta['start_step'] if start_step is not None: x0, dx = start_step nx = len(arr) xs = np.linspace(x0, x0 + (nx-1)*dx, nx) pw.plot(xs, arr) else: pw.plot(arr) elif operation == 'plot_xy': pw.plot(arr[0], arr[1], parametric=True) elif operation == 'plot_z': start_step = meta['start_step'] if start_step is not None: (x0, dx), (y0, dy) = start_step pw.setImage(arr, pos=(x0, y0), scale=(dx, dy)) else: pw.setImage(arr) elif operation == 'append_y': xs, ys = pw.get_data() new_ys = list(ys) new_ys.append(meta['value']) start_step = meta['start_step'] if start_step is not None: x0, dx = start_step nx = len(new_ys) xs = np.linspace(x0, x0 + (nx-1)*dx, nx) pw.plot(xs, new_ys) else: pw.plot(new_ys) elif operation == 'append_xy': xs, ys = pw.get_data() xn, yn = meta['value'] new_xs = list(xs) new_xs.append(xn) new_ys = list(ys) new_ys.append(yn) pw.plot(new_xs, new_ys, parametric=True) elif operation == 'append_z': image = pw.get_data() if image is None: image = np.array([arr]) else: try: image = np.vstack((image, [arr])) except ValueError: image = np.array([arr]) start_step = meta['start_step'] if start_step is not None: (x0, dx), (y0, dy) = start_step pw.setImage(image, pos=(x0, y0), scale=(dx, dy)) else: pw.setImage(image) def add_new_plot(self, rank, name): pw = widgets.get_widget(rank, name) self.add_plot(pw) self.namelist[name] = pw return pw def add_plot(self, pw): self.insert_dock_right = not self.insert_dock_right self.dockarea.addDock(pw, position=['bottom', 'right'][self.insert_dock_right]) def sizeHint(self): return QtCore.QSize(1000, 600)
def setup_widgets(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) # Docks dock_occcupancy = Dock("Occupancy", size=(400, 400)) dock_tot = Dock("Time over threshold values (TOT)", size=(200, 200)) dock_hit_timing = Dock("Hit count histogram", size=(200, 200)) dock_status = Dock("Status", size=(800, 40)) dock_area.addDock(dock_occcupancy, 'top') dock_area.addDock(dock_tot, 'right', dock_occcupancy) dock_area.addDock(dock_hit_timing, 'bottom', dock_tot) dock_area.addDock(dock_status, 'top') # Status dock on top cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz") self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz") self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz") self.timestamp_label = QtGui.QLabel("Data Timestamp\n") self.plot_delay_label = QtGui.QLabel("Plot Delay\n") self.scan_parameter_label = QtGui.QLabel("Parameter ID\n") self.spin_box = Qt.QSpinBox(value=0) self.spin_box.setMaximum(1000000) self.spin_box.setSuffix(" Readouts") self.reset_button = QtGui.QPushButton('Reset') layout.addWidget(self.timestamp_label, 0, 0, 0, 1) layout.addWidget(self.plot_delay_label, 0, 1, 0, 1) layout.addWidget(self.rate_label, 0, 2, 0, 1) layout.addWidget(self.hit_rate_label, 0, 3, 0, 1) layout.addWidget(self.event_rate_label, 0, 4, 0, 1) layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1) layout.addWidget(self.spin_box, 0, 6, 0, 1) layout.addWidget(self.reset_button, 0, 7, 0, 1) dock_status.addWidget(cw) # Connect widgets self.reset_button.clicked.connect(lambda: self.send_command('RESET')) self.spin_box.valueChanged.connect( lambda value: self.send_command(str(value))) # Different plot docks occupancy_graphics = pg.GraphicsLayoutWidget() occupancy_graphics.show() view = occupancy_graphics.addViewBox() view.invertY(True) self.occupancy_img = pg.ImageItem(border='w') # Set colormap from matplotlib lut = generatePgColormap("viridis").getLookupTable(0.0, 1.0, 256) self.occupancy_img.setLookupTable(lut, update=True) # view.addItem(self.occupancy_img) plot = pg.PlotWidget(viewBox=view, labels={ 'bottom': 'Column', 'left': 'Row' }) plot.addItem(self.occupancy_img) dock_occcupancy.addWidget(plot) tot_plot_widget = pg.PlotWidget(background="w") self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) tot_plot_widget.showGrid(y=True) dock_tot.addWidget(tot_plot_widget) hit_timing_widget = pg.PlotWidget() self.hist_hit_count = hit_timing_widget.plot(np.linspace( -0.5, 100.5, 101), np.zeros((100)), stepMode=True) hit_timing_widget.showGrid(y=True) dock_hit_timing.addWidget(hit_timing_widget) self.plot_delay = 0
class OnlineMonitorApplication(QtGui.QMainWindow): def __init__(self, socket_addr): super(OnlineMonitorApplication, self).__init__() self.setup_plots() self.add_widgets() self.fps = 0 # data frames per second self.hps = 0 # hits per second self.eps = 0 # events per second self.plot_delay = 0 self.updateTime = ptime.time() self.total_hits = 0 self.total_events = 0 self.setup_data_worker_and_start(socket_addr) self.reset_plots() def closeEvent(self, event): super(OnlineMonitorApplication, self).closeEvent(event) # wait for thread self.worker.stop() self.thread.wait( 2 ) # fixes message: QThread: Destroyed while thread is still running def setup_data_worker_and_start(self, socket_addr): self.thread = QtCore.QThread() # no parent self.worker = DataWorker() # no parent self.worker.meta_data.connect(self.on_meta_data) self.worker.interpreted_data.connect(self.on_interpreted_data) self.worker.run_start.connect(self.on_run_start) self.worker.run_config_data.connect(self.on_run_config_data) self.worker.global_config_data.connect(self.on_global_config_data) self.worker.filename.connect(self.on_filename) self.spin_box.valueChanged.connect( self.worker.on_set_integrate_readouts) self.reset_button.clicked.connect(self.on_reset) self.worker.moveToThread(self.thread) self.worker.connect(socket_addr) # self.aboutToQuit.connect(self.worker.stop) # QtGui.QApplication self.thread.started.connect(self.worker.process_data) self.worker.finished.connect(self.thread.quit) self.worker.finished.connect(self.worker.deleteLater) self.thread.finished.connect(self.thread.deleteLater) self.thread.start() def setup_plots(self): pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') def add_widgets(self): # Main window with dock area self.dock_area = DockArea() self.setCentralWidget(self.dock_area) # Docks dock_occcupancy = Dock("Occupancy", size=(400, 400)) dock_run_config = Dock("Run configuration", size=(400, 400)) dock_global_config = Dock("Global configuration", size=(400, 400)) dock_tot = Dock("ToT", size=(400, 400)) dock_tdc = Dock("TDC", size=(400, 400)) dock_tdc_distance = Dock("TDC distance", size=(400, 400)) dock_event_status = Dock("Event status", size=(400, 400)) dock_trigger_status = Dock("Trigger status", size=(400, 400)) dock_service_records = Dock("Service records", size=(400, 400)) dock_hit_timing = Dock("Hit timing (rel. BCID)", size=(400, 400)) dock_status = Dock("Status", size=(800, 40)) self.dock_area.addDock(dock_global_config, 'left') self.dock_area.addDock(dock_run_config, 'above', dock_global_config) self.dock_area.addDock(dock_occcupancy, 'above', dock_run_config) self.dock_area.addDock(dock_tdc_distance, 'right', dock_occcupancy) self.dock_area.addDock(dock_tdc, 'above', dock_tdc_distance) self.dock_area.addDock(dock_tot, 'above', dock_tdc) self.dock_area.addDock(dock_service_records, 'bottom', dock_occcupancy) self.dock_area.addDock(dock_trigger_status, 'above', dock_service_records) self.dock_area.addDock(dock_event_status, 'above', dock_trigger_status) self.dock_area.addDock(dock_hit_timing, 'bottom', dock_tot) self.dock_area.addDock(dock_status, 'top') # Status widget cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz") self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz") self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz") self.timestamp_label = QtGui.QLabel("Data Timestamp\n") self.plot_delay_label = QtGui.QLabel("Plot Delay\n") self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n") self.spin_box = Qt.QSpinBox(value=1) self.spin_box.setMaximum(1000000) self.spin_box.setSuffix(" Readouts") self.reset_button = QtGui.QPushButton('Reset') layout.addWidget(self.timestamp_label, 0, 0, 0, 1) layout.addWidget(self.plot_delay_label, 0, 1, 0, 1) layout.addWidget(self.rate_label, 0, 2, 0, 1) layout.addWidget(self.hit_rate_label, 0, 3, 0, 1) layout.addWidget(self.event_rate_label, 0, 4, 0, 1) layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1) layout.addWidget(self.spin_box, 0, 6, 0, 1) layout.addWidget(self.reset_button, 0, 7, 0, 1) dock_status.addWidget(cw) # Run config dock self.run_conf_list_widget = Qt.QListWidget() dock_run_config.addWidget(self.run_conf_list_widget) # Global config dock self.global_conf_list_widget = Qt.QListWidget() dock_global_config.addWidget(self.global_conf_list_widget) # Different plot docks occupancy_graphics = pg.GraphicsLayoutWidget() occupancy_graphics.show() view = occupancy_graphics.addViewBox() self.occupancy_img = pg.ImageItem(border='w') view.addItem(self.occupancy_img) view.setRange(QtCore.QRectF(0, 0, 80, 336)) dock_occcupancy.addWidget(occupancy_graphics) tot_plot_widget = pg.PlotWidget(background="w") self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17, endpoint=True), np.zeros((16)), stepMode=True) tot_plot_widget.showGrid(y=True) dock_tot.addWidget(tot_plot_widget) tdc_plot_widget = pg.PlotWidget(background="w") self.tdc_plot = tdc_plot_widget.plot(np.linspace(-0.5, 4095.5, 4097, endpoint=True), np.zeros((4096)), stepMode=True) tdc_plot_widget.showGrid(y=True) tdc_plot_widget.setXRange(0, 800, update=True) dock_tdc.addWidget(tdc_plot_widget) tdc_distance_plot_widget = pg.PlotWidget(background="w") self.tdc_distance_plot = tdc_distance_plot_widget.plot(np.linspace( -0.5, 255.5, 257, endpoint=True), np.zeros((256)), stepMode=True) tdc_distance_plot_widget.showGrid(y=True) tdc_distance_plot_widget.setXRange(0, 800, update=True) dock_tdc_distance.addWidget(tdc_distance_plot_widget) event_status_widget = pg.PlotWidget() self.event_status_plot = event_status_widget.plot(np.linspace( -0.5, 15.5, 17, endpoint=True), np.zeros((16)), stepMode=True) event_status_widget.showGrid(y=True) dock_event_status.addWidget(event_status_widget) trigger_status_widget = pg.PlotWidget() self.trigger_status_plot = trigger_status_widget.plot(np.linspace( -0.5, 7.5, 9, endpoint=True), np.zeros((8)), stepMode=True) trigger_status_widget.showGrid(y=True) dock_trigger_status.addWidget(trigger_status_widget) service_record_widget = pg.PlotWidget() self.service_record_plot = service_record_widget.plot(np.linspace( -0.5, 31.5, 33, endpoint=True), np.zeros((32)), stepMode=True) service_record_widget.showGrid(y=True) dock_service_records.addWidget(service_record_widget) hit_timing_widget = pg.PlotWidget() self.hit_timing_plot = hit_timing_widget.plot(np.linspace( -0.5, 15.5, 17, endpoint=True), np.zeros((16)), stepMode=True) hit_timing_widget.showGrid(y=True) dock_hit_timing.addWidget(hit_timing_widget) def on_reset(self): self.worker.reset() self.total_hits = 0 self.total_events = 0 self.reset_plots() self.update_rate(0, 0, 0, 0, 0) def on_run_start(self): # clear config data widgets self.run_conf_list_widget.clear() self.global_conf_list_widget.clear() self.setWindowTitle('Online Monitor') def on_run_config_data(self, config_data): self.setup_run_config_text(**config_data) def on_global_config_data(self, config_data): self.setup_global_config_text(**config_data) def on_filename(self, config_data): self.setup_filename(**config_data) def setup_run_config_text(self, conf): for key, value in sorted(conf.iteritems()): item = Qt.QListWidgetItem("%s: %s" % (key, value)) self.run_conf_list_widget.addItem(item) def setup_global_config_text(self, conf): for key, value in sorted(conf.iteritems()): item = Qt.QListWidgetItem("%s: %s" % (key, value)) self.global_conf_list_widget.addItem(item) def setup_filename(self, conf): self.setWindowTitle('Online Monitor - %s' % conf) def on_interpreted_data(self, interpreted_data): self.update_plots(**interpreted_data) def reset_plots(self): self.update_plots(np.zeros((80, 336, 1), dtype=np.uint8), np.zeros((16, ), dtype=np.uint8), np.zeros((4096, ), dtype=np.uint8), np.zeros((256, ), dtype=np.uint8), np.zeros((16, ), dtype=np.uint8), np.zeros((32, ), dtype=np.uint8), np.zeros((8, ), dtype=np.uint8), np.zeros((16, ), dtype=np.uint8)) def update_plots(self, occupancy, tot_hist, tdc_counters, tdc_distance, error_counters, service_records_counters, trigger_error_counters, rel_bcid_hist): self.occupancy_img.setImage(occupancy[:, ::-1, 0], autoDownsample=True) self.tot_plot.setData(x=np.linspace(-0.5, 15.5, 17, endpoint=True), y=tot_hist, fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) self.tdc_plot.setData(x=np.linspace(-0.5, 4095.5, 4097, endpoint=True), y=tdc_counters, fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) self.tdc_distance_plot.setData(x=np.linspace(-0.5, 255.5, 257, endpoint=True), y=tdc_distance, fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) self.event_status_plot.setData(x=np.linspace(-0.5, 15.5, 17, endpoint=True), y=error_counters, fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) self.service_record_plot.setData(x=np.linspace(-0.5, 31.5, 33, endpoint=True), y=service_records_counters, fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) self.trigger_status_plot.setData(x=np.linspace(-0.5, 7.5, 9, endpoint=True), y=trigger_error_counters, fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) self.hit_timing_plot.setData(x=np.linspace(-0.5, 15.5, 17, endpoint=True), y=rel_bcid_hist[:16], fillLevel=0, brush=(0, 0, 255, 150), stepMode=True) def on_meta_data(self, meta_data): self.update_monitor(**meta_data) def update_monitor(self, timestamp_start, timestamp_stop, readout_error, scan_parameters, n_hits, n_events): self.timestamp_label.setText( "Data Timestamp\n%s" % time.asctime(time.localtime(timestamp_stop))) self.scan_parameter_label.setText( "Scan Parameters\n%s" % ', '.join('%s: %s' % (str(key), str(val)) for key, val in scan_parameters.iteritems())) now = ptime.time() recent_total_hits = n_hits recent_total_events = n_events self.plot_delay = self.plot_delay * 0.9 + (now - timestamp_stop) * 0.1 self.plot_delay_label.setText( "Plot Delay\n%s" % ((time.strftime('%H:%M:%S', time.gmtime(self.plot_delay))) if abs(self.plot_delay) > 5 else "%1.2f ms" % (self.plot_delay * 1.e3))) recent_fps = 1.0 / (now - self.updateTime) # calculate FPS recent_hps = (recent_total_hits - self.total_hits) / (now - self.updateTime) recent_eps = (recent_total_events - self.total_events) / (now - self.updateTime) self.updateTime = now self.total_hits = recent_total_hits self.total_events = recent_total_events self.fps = self.fps * 0.7 + recent_fps * 0.3 self.hps = self.hps + (recent_hps - self.hps) * 0.3 / self.fps self.eps = self.eps + (recent_eps - self.eps) * 0.3 / self.fps self.update_rate(self.fps, self.hps, recent_total_hits, self.eps, recent_total_events) def update_rate(self, fps, hps, recent_total_hits, eps, recent_total_events): self.rate_label.setText("Readout Rate\n%d Hz" % fps) if self.spin_box.value( ) == 0: # show number of hits, all hits are integrated self.hit_rate_label.setText("Total Hits\n%d" % int(recent_total_hits)) else: self.hit_rate_label.setText("Hit Rate\n%d Hz" % int(hps)) if self.spin_box.value() == 0: # show number of events self.event_rate_label.setText("Total Events\n%d" % int(recent_total_events)) else: self.event_rate_label.setText("Event Rate\n%d Hz" % int(eps))
class GUIBuilder(QMainWindow): def __init__(self, instance): super(GUIBuilder, self).__init__() self.setCentralWidget(QWidget()) layout = QVBoxLayout(self.centralWidget()) self.plots_layout = DockArea() layout.addWidget(self.plots_layout) self.form_layout = QFormLayout() self.form_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) layout.addLayout(self.form_layout) self.buttons_layout = QHBoxLayout() layout.addLayout(self.buttons_layout) self.instance = instance self.plot_widgets = {} self.plot_data_items = {} self.plot_color_generators = {} seen_form_items = [] seen_plot_items = [] for node in ast.walk(ast.parse(getsource(type(instance)))): if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): if node.func.id.startswith('gb_get_') or node.func.id.startswith('gb_set_'): segs = node.func.id.split('_') caster = __builtins__[segs[2]] name = "_".join(segs[3:]) if name in seen_form_items: continue seen_form_items.append(name) if caster is bool: editor = QCheckBox() if node.func.id.startswith('gb_get_') and node.args: editor.setChecked(node.args[0].id == 'True') get_fn = lambda e=editor: e.isChecked() set_fn = lambda v, e=editor: e.setChecked(v) else: editor = QLineEdit() if node.func.id.startswith('gb_get_') and node.args: if isinstance(node.args[0], ast.Num): init = node.args[0].n else: init = node.args[0].s editor.setText(str(caster(init))) get_fn = lambda e=editor, c=caster: c(e.text()) set_fn = lambda val, e=editor: e.setText(str(val)) base_name = "_".join(segs[2:]) get_name = "gb_get_" + base_name set_name = "gb_set_" + base_name __builtins__[get_name] = lambda init=0, get_fn=get_fn: get_fn() __builtins__[set_name] = lambda val, set_fn=set_fn: set_fn(val) self.form_layout.addRow(prettify(name), editor) if node.func.id.startswith('gb_plot_'): segs = node.func.id.split("_") plot_type = segs[2] plot_name = segs[3] if len(segs) >= 5: data_item_name = "_".join(segs[4:]) else: data_item_name = "" if (plot_name, data_item_name) in seen_plot_items: continue seen_plot_items.append((plot_name, data_item_name)) if plot_name not in self.plot_widgets: if plot_type in ['y', 'xy']: pw = PlotWidget() self.plot_widgets[plot_name] = pw self.plot_color_generators[plot_name] = itertools.cycle('rgb') pw.addLegend() else: raise ValueError("Unknown plot type in {}: {}".format(node.func.id, plot_type)) dock = Dock(name=prettify(plot_name), widget=pw) self.plots_layout.addDock(dock, 'above') self.add_plot_item(node.func.id, plot_name, data_item_name) if isinstance(node, ast.FunctionDef): if node.name.endswith("_gb_button"): name = "_".join(node.name.split("_")[:-2]) button = QPushButton(prettify(name)) button.clicked.connect(getattr(instance, node.name)) self.buttons_layout.addWidget(button) def add_plot_item(self, fn_name, plot_name, data_item_name): plot_widget = self.plot_widgets[plot_name] color_generator = self.plot_color_generators[plot_name] plot_type = fn_name.split("_")[2] if plot_type == "xy": def plot_fn(x, y): if data_item_name in self.plot_data_items: self.plot_data_items[data_item_name].setData(x, y) else: self.plot_data_items[data_item_name] = plot_widget.plot( x, y, name=prettify(data_item_name), pen=color_generator.next() ) elif plot_type == "y": def plot_fn(y): if data_item_name in self.plot_data_items: self.plot_data_items[data_item_name].setData(y) else: self.plot_data_items[data_item_name] = plot_widget.plot( y, name=prettify(data_item_name), pen=color_generator.next() ) else: raise ValueError("Unknown plot type in {}: {}".format(fn_name, plot_type)) __builtins__[fn_name] = plot_fn
def __init__(self, scanZ, recWidget=None, *args, **kwargs): super().__init__(*args, **kwargs) self.setMinimumSize(2, 350) self.mainRec = recWidget self.webcam = instruments.Webcam() self.z = scanZ self.z.zHostPosition = 'left' self.z.zobject.HostBackLashEnable = False self.setPoint = 0 self.V = Q_(1, 'V') self.um = Q_(1, 'um') self.nm = Q_(1, 'nm') self.setFrameStyle(QtGui.QFrame.Panel | QtGui.QFrame.Raised) self.scansPerS = 10 self.ProcessData = ProcessData(self.webcam) # Focus lock widgets self.kpEdit = QtGui.QLineEdit('4') self.kpEdit.setFixedWidth(60) self.kpEdit.textChanged.connect(self.unlockFocus) self.kpLabel = QtGui.QLabel('kp') self.kiEdit = QtGui.QLineEdit('0.01') self.kiEdit.setFixedWidth(60) self.kiEdit.textChanged.connect(self.unlockFocus) self.kiLabel = QtGui.QLabel('ki') self.lockButton = QtGui.QPushButton('Lock') self.lockButton.setCheckable(True) self.lockButton.clicked.connect(self.toggleFocus) self.lockButton.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) moveLabel = QtGui.QLabel('Move [nm]') moveLabel.setAlignment(QtCore.Qt.AlignCenter) self.moveEdit = QtGui.QLineEdit('0') self.moveEdit.setFixedWidth(60) self.moveEdit.returnPressed.connect(self.zMoveEdit) self.focusDataBox = QtGui.QCheckBox('Save focus data') self.focusPropertiesDisplay = QtGui.QLabel(' st_dev = 0 max_dev = 0') self.graph = FocusLockGraph(self, self.mainRec) self.focusTime = 1000 / self.scansPerS self.focusTimer = QtCore.QTimer() self.focusTimer.timeout.connect(self.update) self.focusTimer.start(self.focusTime) self.locked = False self.n = 1 self.max_dev = 0 self.focusCalib = FocusCalibration(self) self.focusCalibThread = QtCore.QThread(self) self.focusCalib.moveToThread(self.focusCalibThread) self.focusCalibButton = QtGui.QPushButton('Calibrate') self.focusCalibButton.clicked.connect(self.focusCalib.start) self.focusCalibThread.start() try: prevCal = np.around(np.loadtxt('calibration')[0]/10) text = '1 px --> {} nm'.format(prevCal) self.calibrationDisplay = QtGui.QLineEdit(text) except: self.calibrationDisplay = QtGui.QLineEdit('0 px --> 0 nm') self.calibrationDisplay.setReadOnly(False) self.webcamgraph = WebcamGraph(self) dockArea = DockArea() graphDock = Dock("Focus laser graph", size=(400, 200)) graphDock.addWidget(self.graph) dockArea.addDock(graphDock) webcamDock = Dock("Focus laser view", size=(200, 200)) webcamDock.addWidget(self.webcamgraph) dockArea.addDock(webcamDock, 'right', graphDock) # GUI layout grid = QtGui.QGridLayout() self.setLayout(grid) grid.addWidget(dockArea, 0, 0, 1, 6) grid.addWidget(self.focusCalibButton, 1, 0) grid.addWidget(self.calibrationDisplay, 2, 0) grid.addWidget(self.focusDataBox, 1, 1) grid.addWidget(moveLabel, 1, 2) grid.addWidget(self.moveEdit, 2, 2) grid.addWidget(self.kpLabel, 1, 3) grid.addWidget(self.kpEdit, 1, 4) grid.addWidget(self.kiLabel, 2, 3) grid.addWidget(self.kiEdit, 2, 4) grid.addWidget(self.lockButton, 1, 5, 2, 1) grid.setColumnMinimumWidth(5, 170)
class DockWin(QtGui.QMainWindow): docklist = [] def __init__(self): logging.debug('Creating main window.') QtGui.QMainWindow.__init__(self) self.setWindowTitle("colorgraphs dock") self.dockarea = DockArea() self.setCentralWidget(self.dockarea) self.resize(*_MAIN_WINDOW_SIZE) self.initUI() self.show() self.raise_() def initUI(self): palette = QtGui.QPalette() palette.setColor(QtGui.QPalette.Background,QtCore.Qt.white) self.setPalette(palette) # loadAction = QtGui.QAction(QtGui.QIcon(os.path.join(_IMG_PATH,'load.png')), '&Load', self) # loadAction.setShortcut('Ctr+O') # loadAction.setStatusTip('Load dataset') # loadAction.triggered.connect(load_action) # saveAction = QtGui.QAction(QtGui.QIcon(os.path.join(_IMG_PATH,'save.png')), '&Save', self) # saveAction.setShortcut('Ctr+S') # saveAction.setStatusTip('Save dataset') # saveAction.triggered.connect(save_action) # self.statusBar() # toolbar = self.addToolBar('Load') # toolbar.addAction(loadAction) # toolbar.addAction(saveAction) def create_dock(self, name='', loc='right', widget=None): if name == '': name = 'Graph%s' %len(self.docklist) if name in [dock.name() for dock in self.docklist]: dock = {dock.name(): dock for dock in self.docklist}[name] dock.close() self.docklist.remove(dock) dock = Dock(name) if widget: self.dockarea.addDock(dock, loc, widget) else: self.dockarea.addDock(dock, loc) DockWin.docklist.append(dock) return dock def add_widget(self, w, loc='right'): ''' Add widget to the dock. w = widget, loc = location ('right', 'left', 'behind', etc.) ''' dock = self.create_dock(w.name, loc) dock.addWidget(w) w.show() def add_widgets(self, wlist): ''' Add a number of widgets to the dock. Spread evenly. ''' for w in wlist: dock = self.create_dock(w.name, loc) for dock in docklist: dock.addWidget(w) def close_all(self): docklist = self.docklist for dock in docklist: dock.close() docklist.remove(dock) del(dock) def plot(self, *args, **kwargs): w = plotwidget(*args, **kwargs) self.add_widget(w) def _repr_png_(self): for d in self.dockarea.docks.values(): display(d.widgets[0]) def close(self): logging.debug('Close')
class OnlineMonitorApplication(QtGui.QMainWindow): def __init__(self, socket_addr): super(OnlineMonitorApplication, self).__init__() self.setup_plots() self.add_widgets() self.fps = 0 # data frames per second self.hps = 0 # hits per second self.eps = 0 # events per second self.plot_delay = 0 self.updateTime = ptime.time() self.total_hits = 0 self.total_events = 0 self.setup_data_worker_and_start(socket_addr) def closeEvent(self, event): super(OnlineMonitorApplication, self).closeEvent(event) # wait for thread self.worker.stop() # self.thread.wait() def setup_data_worker_and_start(self, socket_addr): self.thread = QtCore.QThread() # no parent self.worker = DataWorker() # no parent self.worker.meta_data.connect(self.on_meta_data) self.worker.interpreted_data.connect(self.on_interpreted_data) self.worker.run_start.connect(self.on_run_start) self.worker.config_data.connect(self.on_config_data) self.spin_box.valueChanged.connect(self.worker.on_set_integrate_readouts) self.worker.moveToThread(self.thread) self.worker.connect(socket_addr) # self.aboutToQuit.connect(self.worker.stop) # QtGui.QApplication self.thread.started.connect(self.worker.process_data) self.worker.finished.connect(self.thread.quit) # self.worker.finished.connect(self.worker.deleteLater) # self.thread.finished.connect(self.thread.deleteLater) self.thread.start() def setup_plots(self): pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') def add_widgets(self): # Main window with dock area self.dock_area = DockArea() self.setCentralWidget(self.dock_area) # Docks dock_occcupancy = Dock("Occupancy", size=(400, 400)) dock_run_config = Dock("Configuration", size=(400, 400)) dock_tot = Dock("Time over threshold values (TOT)", size=(400, 400)) dock_tdc = Dock("Time digital converter values (TDC)", size=(400, 400)) dock_event_status = Dock("Event status", size=(400, 400)) dock_trigger_status = Dock("Trigger status", size=(400, 400)) dock_service_records = Dock("Service records", size=(400, 400)) dock_hit_timing = Dock("Hit timing (rel. BCID)", size=(400, 400)) dock_status = Dock("Status", size=(800, 40)) self.dock_area.addDock(dock_run_config, 'left') self.dock_area.addDock(dock_occcupancy, 'above', dock_run_config) self.dock_area.addDock(dock_tdc, 'right', dock_occcupancy) self.dock_area.addDock(dock_tot, 'above', dock_tdc) self.dock_area.addDock(dock_service_records, 'bottom', dock_occcupancy) self.dock_area.addDock(dock_trigger_status, 'above', dock_service_records) self.dock_area.addDock(dock_event_status, 'above', dock_trigger_status) self.dock_area.addDock(dock_hit_timing, 'bottom', dock_tot) self.dock_area.addDock(dock_status, 'top') # Status widget cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz") self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz") self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz") self.timestamp_label = QtGui.QLabel("Data Timestamp\n") self.plot_delay_label = QtGui.QLabel("Plot Delay\n") self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n") self.spin_box = Qt.QSpinBox(value=1) layout.addWidget(self.timestamp_label, 0, 0, 0, 1) layout.addWidget(self.plot_delay_label, 0, 1, 0, 1) layout.addWidget(self.rate_label, 0, 2, 0, 1) layout.addWidget(self.hit_rate_label, 0, 3, 0, 1) layout.addWidget(self.event_rate_label, 0, 4, 0, 1) layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1) layout.addWidget(self.spin_box, 0, 6, 0, 1) dock_status.addWidget(cw) # Config dock self.run_conf_list_widget = Qt.QListWidget() dock_run_config.addWidget(self.run_conf_list_widget) # Different plot docks occupancy_graphics = pg.GraphicsLayoutWidget() occupancy_graphics.show() view = occupancy_graphics.addViewBox() self.occupancy_img = pg.ImageItem(border='w') view.addItem(self.occupancy_img) view.setRange(QtCore.QRectF(0, 0, 80, 336)) dock_occcupancy.addWidget(occupancy_graphics) tot_plot_widget = pg.PlotWidget(background="w") self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) tot_plot_widget.showGrid(y=True) dock_tot.addWidget(tot_plot_widget) tdc_plot_widget = pg.PlotWidget(background="w") self.tdc_plot = tdc_plot_widget.plot(np.linspace(-0.5, 4095.5, 4097), np.zeros((4096)), stepMode=True) tdc_plot_widget.showGrid(y=True) tdc_plot_widget.setXRange(0, 800, update=True) dock_tdc.addWidget(tdc_plot_widget) event_status_widget = pg.PlotWidget() self.event_status_plot = event_status_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) event_status_widget.showGrid(y=True) dock_event_status.addWidget(event_status_widget) trigger_status_widget = pg.PlotWidget() self.trigger_status_plot = trigger_status_widget.plot(np.linspace(-0.5, 7.5, 9), np.zeros((8)), stepMode=True) trigger_status_widget.showGrid(y=True) dock_trigger_status.addWidget(trigger_status_widget) service_record_widget = pg.PlotWidget() self.service_record_plot = service_record_widget.plot(np.linspace(-0.5, 31.5, 33), np.zeros((32)), stepMode=True) service_record_widget.showGrid(y=True) dock_service_records.addWidget(service_record_widget) hit_timing_widget = pg.PlotWidget() self.hit_timing_plot = hit_timing_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) hit_timing_widget.showGrid(y=True) dock_hit_timing.addWidget(hit_timing_widget) @pyqtSlot() def on_run_start(self): # clear config data widget self.run_conf_list_widget.clear() self.run_conf_list_widget.addItem(Qt.QListWidgetItem("No run configuration")) @pyqtSlot(dict) def on_config_data(self, config_data): self.setup_config_text(**config_data) def setup_config_text(self, conf): for key, value in conf.iteritems(): item = Qt.QListWidgetItem("%s: %s" % (key, value)) self.run_conf_list_widget.addItem(item) @pyqtSlot(dict) def on_interpreted_data(self, interpreted_data): self.update_plots(**interpreted_data) def update_plots(self, occupancy, tot_hist, tdc_counters, error_counters, service_records_counters, trigger_error_counters, rel_bcid_hist): self.occupancy_img.setImage(occupancy[:, ::-1, 0], autoDownsample=True) self.tot_plot.setData(x=np.linspace(-0.5, 15.5, 17), y=tot_hist, fillLevel=0, brush=(0, 0, 255, 150)) self.tdc_plot.setData(x=np.linspace(-0.5, 4096.5, 4097), y=tdc_counters, fillLevel=0, brush=(0, 0, 255, 150)) self.event_status_plot.setData(x=np.linspace(-0.5, 15.5, 17), y=error_counters, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) self.service_record_plot.setData(x=np.linspace(-0.5, 31.5, 33), y=service_records_counters, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) self.trigger_status_plot.setData(x=np.linspace(-0.5, 7.5, 9), y=trigger_error_counters, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) self.hit_timing_plot.setData(x=np.linspace(-0.5, 15.5, 17), y=rel_bcid_hist, stepMode=True, fillLevel=0, brush=(0, 0, 255, 150)) @pyqtSlot(dict) def on_meta_data(self, meta_data): self.update_monitor(**meta_data) def update_monitor(self, timestamp_start, timestamp_stop, readout_error, scan_parameters, n_hits, n_events): self.timestamp_label.setText("Data Timestamp\n%s" % time.asctime(time.localtime(timestamp_stop))) self.scan_parameter_label.setText("Scan Parameters\n%s" % ', '.join('%s: %s' % (str(key), str(val)) for key, val in scan_parameters.iteritems())) now = ptime.time() recent_total_hits = n_hits recent_total_events = n_events self.plot_delay = self.plot_delay * 0.9 + (now - timestamp_stop) * 0.1 self.plot_delay_label.setText("Plot Delay\n%s" % ((time.strftime('%H:%M:%S', time.gmtime(self.plot_delay))) if self.plot_delay > 5 else "%1.2f ms" % (self.plot_delay * 1.e3))) recent_fps = 1.0 / (now - self.updateTime) # calculate FPS recent_hps = (recent_total_hits - self.total_hits) / (now - self.updateTime) recent_eps = (recent_total_events - self.total_events) / (now - self.updateTime) self.updateTime = now self.total_hits = recent_total_hits self.total_events = recent_total_events self.fps = self.fps * 0.7 + recent_fps * 0.3 self.hps = self.hps + (recent_hps - self.hps) * 0.3 / self.fps self.eps = self.eps + (recent_eps - self.eps) * 0.3 / self.fps self.rate_label.setText("Readout Rate\n%d Hz" % self.fps) if self.spin_box.value() == 0: # show number of hits, all hits are integrated self.hit_rate_label.setText("Total Hits\n%d" % int(recent_total_hits)) else: self.hit_rate_label.setText("Hit Rate\n%d Hz" % int(self.hps)) if self.spin_box.value() == 0: # show number of events self.event_rate_label.setText("Total Events\n%d" % int(recent_total_events)) else: self.event_rate_label.setText("Event Rate\n%d Hz" % int(self.eps))
class OnlineMonitorApplication(QtGui.QMainWindow): def __init__(self, socket_addr): super(OnlineMonitorApplication, self).__init__() self.setup_plots() self.add_widgets() self.fps = 0 self.eps = 0 # events per second self.total_events = 0 self.total_readouts = 0 self.last_total_events = 0 self.updateTime = ptime.time() self.setup_data_worker_and_start(socket_addr) self.cpu_load = max(psutil.cpu_percent(percpu=True)) def closeEvent(self, event): super(OnlineMonitorApplication, self).closeEvent(event) # wait for thread self.worker.stop() self.thread.wait(1) # fixes message: QThread: Destroyed while thread is still running def setup_data_worker_and_start(self, socket_addr): self.thread = QtCore.QThread() # no parent self.worker = DataWorker() # no parent self.worker.interpreted_data.connect(self.on_interpreted_data) self.worker.run_start.connect(self.on_run_start) self.worker.config_data.connect(self.on_config_data) self.spin_box.valueChanged.connect(self.worker.on_set_integrate_readouts) self.worker.moveToThread(self.thread) self.worker.connect(socket_addr) self.thread.started.connect(self.worker.process_data) self.worker.finished.connect(self.thread.quit) self.thread.start() def setup_plots(self): pg.setConfigOption('background', 'w') pg.setConfigOption('foreground', 'k') def add_widgets(self): # Main window with dock area self.dock_area = DockArea() self.setCentralWidget(self.dock_area) # Docks dock_waveform = Dock("Waveform", size=(600, 400)) dock_histogram = Dock("Histogram", size=(600, 400)) dock_status = Dock("Status", size=(1200, 40)) self.dock_area.addDock(dock_waveform, 'left') self.dock_area.addDock(dock_histogram, 'right', dock_waveform) self.dock_area.addDock(dock_status, 'top') # Status widget cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() layout.setColumnStretch(2, 1) cw.setLayout(layout) self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz") self.total_events_label = QtGui.QLabel("Total Events\n0") self.spin_box = Qt.QSpinBox(value=20, maximum=1000) self.reset_button = Qt.QPushButton('Reset', self) self.reset_button.clicked.connect(self.reset_plots) layout.addWidget(self.event_rate_label, 0, 1, 1, 1) layout.addWidget(self.total_events_label, 1, 1, 1, 1) layout.addWidget(self.spin_box, 0, 3, 1, 1) layout.addWidget(self.reset_button, 1, 3, 1, 1) dock_status.addWidget(cw) # Different plot docks waveform_widget = pg.PlotWidget(background="w") self.waveform_plot = waveform_widget.plot(range(0, 200), np.zeros(shape=(200))) self.thr_line = pg.InfiniteLine(pos=1000, angle=0, pen={'color':0.0, 'style':QtCore.Qt.DashLine}) waveform_widget.addItem(self.thr_line) dock_waveform.addWidget(waveform_widget) histogram_widget = pg.PlotWidget(background="w") self.histogram_plot = histogram_widget.plot(range(0, 2**14 + 1), np.zeros(shape=(2**14)), stepMode=True) histogram_widget.showGrid(y=True) self.thr_line_hist = pg.InfiniteLine(pos=1000, angle=90, pen={'color':0.0, 'style':QtCore.Qt.DashLine}) histogram_widget.addItem(self.thr_line_hist) dock_histogram.addWidget(histogram_widget) @pyqtSlot() def on_run_start(self): pass @pyqtSlot(dict) def on_config_data(self, config_data): pass def setup_config_text(self, conf): pass @pyqtSlot(dict) def on_interpreted_data(self, interpreted_data): self.update_plots(**interpreted_data) def update_plots(self, waveform, bin_edges, histogram, threshold, n_actual_events): self.total_events += n_actual_events self.total_readouts += 1 actual_cpu_load = max(psutil.cpu_percent(percpu=True)) self.cpu_load = 0.95 * self.cpu_load + 0.05 * actual_cpu_load if self.cpu_load < 55 and self.spin_box.value() > 0 and self.total_readouts % self.spin_box.value() == 0: # only refresh plot every spin_box.value() readout self.waveform_plot.setData(waveform, fillLevel=0, brush=(0, 0, 255, 150)) self.histogram_plot.setData(x=bin_edges, y=histogram, fillLevel=0, brush=(0, 0, 255, 150)) self.thr_line.setValue(threshold) self.thr_line_hist.setValue(threshold) self.update_monitor() def update_monitor(self): now = ptime.time() recent_eps = (self.total_events - self.last_total_events) / (now - self.updateTime) self.last_total_events = self.total_events self.updateTime = now self.eps = self.eps * 0.98 + recent_eps * 0.02 if self.spin_box.value() == 0: # show number of events self.event_rate_label.setText("Total Events\n%d" % int(self.total_events)) else: self.event_rate_label.setText("Event Rate\n%d Hz" % int(self.eps)) self.total_events_label.setText("Total Events\n%d" % int(self.total_events)) def reset_plots(self): self.worker.reset_hist() self.total_events = 0 self.total_readouts = 0 self.last_total_events = 0 self.updateTime = ptime.time() self.fps = 0 self.eps = 0 # events per second self.waveform_plot.setData(x=range(0, 200), y=np.zeros(200), fillLevel=0, brush=(0, 0, 255, 150)) self.histogram_plot.setData(x=range(0, 2**14+1), y=np.zeros(2**14), fillLevel=0, brush=(0, 0, 255, 150)) self.thr_line.setValue(1000) self.thr_line_hist.setValue(1000) self.update_monitor()
def setup_widgets(self, parent, name): dock_area = DockArea() parent.addTab(dock_area, name) # Docks dock_occcupancy = Dock("Occupancy", size=(400, 400)) dock_run_config = Dock("Run configuration", size=(400, 400)) dock_global_config = Dock("Global configuration", size=(400, 400)) dock_tot = Dock("Time over threshold values (TOT)", size=(400, 400)) dock_tdc = Dock("Time digital converter values (TDC)", size=(400, 400)) dock_event_status = Dock("Event status", size=(400, 400)) dock_trigger_status = Dock("Trigger status", size=(400, 400)) dock_service_records = Dock("Service records", size=(400, 400)) dock_hit_timing = Dock("Hit timing (rel. BCID)", size=(400, 400)) dock_status = Dock("Status", size=(800, 40)) dock_area.addDock(dock_global_config, 'left') dock_area.addDock(dock_run_config, 'above', dock_global_config) dock_area.addDock(dock_occcupancy, 'above', dock_run_config) dock_area.addDock(dock_tdc, 'right', dock_occcupancy) dock_area.addDock(dock_tot, 'above', dock_tdc) dock_area.addDock(dock_service_records, 'bottom', dock_occcupancy) dock_area.addDock(dock_trigger_status, 'above', dock_service_records) dock_area.addDock(dock_event_status, 'above', dock_trigger_status) dock_area.addDock(dock_hit_timing, 'bottom', dock_tot) dock_area.addDock(dock_status, 'top') # Status dock on top cw = QtGui.QWidget() cw.setStyleSheet("QWidget {background-color:white}") layout = QtGui.QGridLayout() cw.setLayout(layout) self.rate_label = QtGui.QLabel("Readout Rate\n0 Hz") self.hit_rate_label = QtGui.QLabel("Hit Rate\n0 Hz") self.event_rate_label = QtGui.QLabel("Event Rate\n0 Hz") self.timestamp_label = QtGui.QLabel("Data Timestamp\n") self.plot_delay_label = QtGui.QLabel("Plot Delay\n") self.scan_parameter_label = QtGui.QLabel("Scan Parameters\n") self.spin_box = Qt.QSpinBox(value=0) self.spin_box.setMaximum(1000000) self.spin_box.setSuffix(" Readouts") self.reset_button = QtGui.QPushButton('Reset') layout.addWidget(self.timestamp_label, 0, 0, 0, 1) layout.addWidget(self.plot_delay_label, 0, 1, 0, 1) layout.addWidget(self.rate_label, 0, 2, 0, 1) layout.addWidget(self.hit_rate_label, 0, 3, 0, 1) layout.addWidget(self.event_rate_label, 0, 4, 0, 1) layout.addWidget(self.scan_parameter_label, 0, 5, 0, 1) layout.addWidget(self.spin_box, 0, 6, 0, 1) layout.addWidget(self.reset_button, 0, 7, 0, 1) dock_status.addWidget(cw) # Connect widgets self.reset_button.clicked.connect(lambda: self.send_command('RESET')) self.spin_box.valueChanged.connect(lambda value: self.send_command(str(value))) # Run config dock self.run_conf_list_widget = Qt.QListWidget() dock_run_config.addWidget(self.run_conf_list_widget) # Global config dock self.global_conf_list_widget = Qt.QListWidget() dock_global_config.addWidget(self.global_conf_list_widget) # Different plot docks occupancy_graphics = pg.GraphicsLayoutWidget() occupancy_graphics.show() view = occupancy_graphics.addViewBox() self.occupancy_img = pg.ImageItem(border='w') view.addItem(self.occupancy_img) view.setRange(QtCore.QRectF(0, 0, 80, 336)) dock_occcupancy.addWidget(occupancy_graphics) tot_plot_widget = pg.PlotWidget(background="w") self.tot_plot = tot_plot_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) tot_plot_widget.showGrid(y=True) dock_tot.addWidget(tot_plot_widget) tdc_plot_widget = pg.PlotWidget(background="w") self.tdc_plot = tdc_plot_widget.plot(np.linspace(-0.5, 4095.5, 4097), np.zeros((4096)), stepMode=True) tdc_plot_widget.showGrid(y=True) tdc_plot_widget.setXRange(0, 800, update=True) dock_tdc.addWidget(tdc_plot_widget) event_status_widget = pg.PlotWidget() self.event_status_plot = event_status_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) event_status_widget.showGrid(y=True) dock_event_status.addWidget(event_status_widget) trigger_status_widget = pg.PlotWidget() self.trigger_status_plot = trigger_status_widget.plot(np.linspace(-0.5, 7.5, 9), np.zeros((8)), stepMode=True) trigger_status_widget.showGrid(y=True) dock_trigger_status.addWidget(trigger_status_widget) service_record_widget = pg.PlotWidget() self.service_record_plot = service_record_widget.plot(np.linspace(-0.5, 31.5, 33), np.zeros((32)), stepMode=True) service_record_widget.showGrid(y=True) dock_service_records.addWidget(service_record_widget) hit_timing_widget = pg.PlotWidget() self.hit_timing_plot = hit_timing_widget.plot(np.linspace(-0.5, 15.5, 17), np.zeros((16)), stepMode=True) hit_timing_widget.showGrid(y=True) dock_hit_timing.addWidget(hit_timing_widget) self.plot_delay = 0
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)
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 DedicatedCounters(DedicatedCountersForm, DedicatedCountersBase ): dataAvailable = QtCore.pyqtSignal( object ) OpStates = enum.enum('idle', 'running', 'paused') def __init__(self, config, dbConnection, pulserHardware, globalVariablesUi, shutterUi, externalInstrumentObservable, parent=None): DedicatedCountersForm.__init__(self) DedicatedCountersBase.__init__(self, parent) self.curvesDict = {} self.dataSlotConnected = False self.config = config self.configName = 'DedicatedCounter' self.pulserHardware = pulserHardware self.state = self.OpStates.idle self.xData = [numpy.array([])]*20 self.yData = [numpy.array([])]*20 self.refValue = [None] * 20 self.integrationTime = 0 self.integrationTimeLookup = dict() self.tick = 0 self.analogCalbrations = None self.globalVariablesUi = globalVariablesUi self.shutterUi = shutterUi self.externalInstrumentObservable = externalInstrumentObservable self.dbConnection = dbConnection self.plotDict = dict() self.area = None # [ # AnalogInputCalibration.PowerDetectorCalibration(), # AnalogInputCalibration.PowerDetectorCalibrationTwo(), # AnalogInputCalibration.AnalogInputCalibration(), # AnalogInputCalibration.AnalogInputCalibration() ] @property def settings(self): return self.settingsUi.settings def setupUi(self, parent): DedicatedCountersForm.setupUi(self, parent) self.setupPlots() self.actionSave.triggered.connect( self.onSave ) self.actionClear.triggered.connect( self.onClear ) self.actionStart.triggered.connect( self.onStart ) self.actionStop.triggered.connect( self.onStop ) self.settingsUi = DedicatedCountersSettings.DedicatedCountersSettings(self.config,self.plotDict) self.settingsUi.setupUi(self.settingsUi) self.settingsDock.setWidget( self.settingsUi ) self.settingsUi.valueChanged.connect( self.onSettingsChanged ) #Plot buttons self.addPlot = QtGui.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self) self.addPlot.setToolTip("Add new plot") self.addPlot.triggered.connect(self.onAddPlot) self.toolBar.addAction(self.addPlot) self.removePlot = QtGui.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self) self.removePlot.setToolTip("Remove a plot") self.removePlot.triggered.connect(self.onRemovePlot) self.toolBar.addAction(self.removePlot) self.renamePlot = QtGui.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self) self.renamePlot.setToolTip("Rename a plot") self.renamePlot.triggered.connect(self.onRenamePlot) self.toolBar.addAction(self.renamePlot) # Input Calibrations self.calibrationUi = InputCalibrationUi.InputCalibrationUi(self.config, 4) self.calibrationUi.setupUi(self.calibrationUi) self.calibrationDock = QtWidgets.QDockWidget("Input Calibration") self.calibrationDock.setObjectName("Input Calibration") self.calibrationDock.setWidget( self.calibrationUi ) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.calibrationDock) self.analogCalbrations = self.calibrationUi.calibrations # Display Channels 0-3 self.displayUi = DedicatedDisplay.DedicatedDisplay(self.config, "Channel 0-3") self.displayUi.setupUi(self.displayUi) self.displayDock = QtWidgets.QDockWidget("Channel 0-3") self.displayDock.setObjectName("Channel 0-3") self.displayDock.setWidget( self.displayUi ) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.displayDock) # Display Channel 4-7 self.displayUi2 = DedicatedDisplay.DedicatedDisplay(self.config, "Channel 4-7") self.displayUi2.setupUi(self.displayUi2) self.displayDock2 = QtWidgets.QDockWidget("Channel 4-7") self.displayDock2.setObjectName("Channel 4-7") self.displayDock2.setWidget(self.displayUi2) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.displayDock2) # Display ADC 0-3 self.displayUiADC = DedicatedDisplay.DedicatedDisplay(self.config, "Analog Channels") self.displayUiADC.setupUi(self.displayUiADC) self.displayDockADC = QtWidgets.QDockWidget("Analog Channels") self.displayDockADC.setObjectName("Analog Channels") self.displayDockADC.setWidget(self.displayUiADC) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.displayDockADC) # Arrange the dock widgets self.tabifyDockWidget( self.displayDockADC, self.displayDock2) self.tabifyDockWidget( self.displayDock2, self.displayDock ) self.tabifyDockWidget( self.calibrationDock, self.settingsDock ) self.calibrationDock.hide() # AutoLoad self.autoLoad = AutoLoad.AutoLoad(self.config, self.dbConnection, self.pulserHardware, self.dataAvailable, self.globalVariablesUi,self.shutterUi, self.externalInstrumentObservable) self.autoLoad.setupUi(self.autoLoad) self.autoLoadDock = QtWidgets.QDockWidget("Auto Loader") self.autoLoadDock.setObjectName("Auto Loader") self.autoLoadDock.setWidget( self.autoLoad ) self.autoLoad.valueChanged.connect( self.onSettingsChanged ) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.autoLoadDock) # external Status display self.statusDisplay = StatusDisplay(self.config, self.pulserHardware.pulserConfiguration()) self.statusDisplay.setupUi(self.statusDisplay) self.statusDock = QtWidgets.QDockWidget("Status display") self.statusDock.setObjectName("Status display") self.statusDock.setWidget( self.statusDisplay ) self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.statusDock) if self.configName+'.MainWindow.State' in self.config: QtGui.QMainWindow.restoreState(self,self.config[self.configName+'.MainWindow.State']) self.onSettingsChanged() def onSettingsChanged(self): self.integrationTimeLookup[ self.pulserHardware.getIntegrationTimeBinary(self.settings.integrationTime) & 0xffffff] = self.settings.integrationTime self.pulserHardware.integrationTime = self.settings.integrationTime self.autoLoadCounterMask = self.autoLoad.settings.counterMask self.plotCounterMask = self.settingsUi.settings.counterMask self.counterDisplayData = self.autoLoad.settings.counterDisplayData self.plotDisplayData = self.settingsUi.settings.plotDisplayData self.countDict = self.settingsUi.settings.counterDict self.adcDict = self.settingsUi.settings.adcDict if self.state == self.OpStates.running: mask = 0 mask += self.autoLoadCounterMask | self.plotCounterMask self.pulserHardware.counterMask = mask self.pulserHardware.adcMask = self.settings.adcMask for windowName, dataSourceNames in self.plotDisplayData.items(): if windowName in self.plotDict: self.curvesDict.setdefault(windowName, dict()) counterIndexList = [self.countDict[n] for n in dataSourceNames if n in self.countDict] adcIndexList = [self.adcDict[n] for n in dataSourceNames if n in self.adcDict] mycurves = self.curvesDict[windowName] for cIdx in counterIndexList: mycurves.setdefault(cIdx, self.plotDict[windowName]['view'].plot(pen=penList[cIdx + 1][0])) for aIdx in adcIndexList: mycurves.setdefault(aIdx + 16, self.plotDict[windowName]['view'].plot(pen=penList[cIdx + 1][0])) for eIdx in set(mycurves) - set(counterIndexList) - set(i + 16 for i in adcIndexList): curve = mycurves.pop(eIdx) self.plotDict[windowName]['view'].removeItem(curve) self.xData[eIdx] = numpy.array([]) self.yData[eIdx] = numpy.array([]) def saveConfig(self): self.config[self.configName+'.pos'] = self.pos() self.config[self.configName+'.size'] = self.size() self.config[self.configName+'.Settings'] = self.settings self.config[self.configName+'.MainWindow.State'] = QtWidgets.QMainWindow.saveState(self) self.config[self.configName+'.PlotNames'] = list(self.plotDict.keys()) self.displayUi.saveConfig() self.displayUi2.saveConfig() self.displayUiADC.saveConfig() self.autoLoad.saveConfig() self.calibrationUi.saveConfig() self.settingsUi.saveConfig() self.statusDisplay.saveConfig() def onClose(self): self.autoLoad.onClose() def closeEvent(self, e): self.onClose() def reject(self): self.config[self.configName+'.pos'] = self.pos() self.config[self.configName+'.size'] = self.size() self.pulserHardware.dedicatedDataAvailable.disconnect( self.onData ) self.hide() def show(self): if self.configName+'.pos' in self.config: self.move(self.config[self.configName+'.pos']) if self.configName+'.size' in self.config: self.resize(self.config[self.configName+'.size']) super(DedicatedCounters,self).show() if not self.dataSlotConnected: self.pulserHardware.dedicatedDataAvailable.connect( self.onData ) self.dataSlotConnected = True def onStart(self): self.pulserHardware.counterMask = self.settings.counterMask self.pulserHardware.adcMask = self.settings.adcMask self.state = self.OpStates.running self.onSettingsChanged() def onStop(self): self.pulserHardware.counterMask = 0 self.pulserHardware.adcMask = 0 self.state = self.OpStates.idle self.onSettingsChanged() def onSave(self): logger = logging.getLogger(__name__) self.plotDisplayData = self.settingsUi.settings.plotDisplayData for plotName in self.plotDisplayData.keys(): for n in range(20): if len(self.xData[n])>0 and len(self.yData[n])>0: trace = TraceCollection() trace.x = self.xData[n] trace.y = self.yData[n] if n < 16: trace.description["counter"] = str(plotName) else: trace.description["ADC"] = str(plotName) filename, _ = DataDirectory().sequencefile("DedicatedCounter_{0}.txt".format(n)) trace.addTracePlotting( TracePlotting(name="Counter {0}".format(n)) ) trace.save() logger.info("saving dedicated counters") def onClear(self): self.xData = [numpy.array([])]*20 self.yData = [numpy.array([])]*20 self.tick = 0 for name, subdict in self.curvesDict.items(): for n in list(subdict.keys()): subdict[n].setData(self.xData[n], self.yData[n]) def onData(self, data): self.tick += 1 self.displayUi.values = data.data[0:4] self.displayUi2.values = data.data[4:8] self.displayUiADC.values = self.convertAnalog(data.analog()) data.analogValues = self.displayUiADC.values # if data.data[16] is not None and data.data[16] in self.integrationTimeLookup: # self.dataIntegrationTime = self.integrationTimeLookup[ data.data[16] ] # else: self.dataIntegrationTime = self.settings.integrationTime data.integrationTime = self.dataIntegrationTime self.plotDisplayData = self.settingsUi.settings.plotDisplayData msIntegrationTime = self.dataIntegrationTime.m_as('ms') for index, value in enumerate(data.data[:16]): if value is not None: y = self.settings.displayUnit.convert(value, msIntegrationTime) self.yData[index] = rollingUpdate(self.yData[index], y, self.settings.pointsToKeep) self.xData[index] = rollingUpdate(self.xData[index], data.timestamp, self.settings.pointsToKeep) for index, value in enumerate(data.analogValues): if value is not None: myindex = 16 + index refValue = self.refValue[myindex] if is_Q(value): if refValue is not None and refValue.dimensionality == value.dimensionality: y = value.m_as(refValue) else: self.refValue[myindex] = value y = value.m else: y = value self.yData[myindex] = rollingUpdate(self.yData[myindex], y, self.settings.pointsToKeep) self.xData[myindex] = rollingUpdate(self.xData[myindex], data.timestamp, self.settings.pointsToKeep) for name, plotwin in self.curvesDict.items(): if plotwin: with BlockAutoRange(next(iter(plotwin.values()))): for index, plotdata in plotwin.items(): plotdata.setData(self.xData[index], self.yData[index]) self.statusDisplay.setData(data) self.dataAvailable.emit(data) # logging.getLogger(__name__).info("Max bytes read {0}".format(data.maxBytesRead)) self.statusDisplay.setData(data) self.dataAvailable.emit(data) def convertAnalog(self, data): converted = list() for channel, cal in enumerate(self.analogCalbrations): converted.append( cal.convertMagnitude(data[channel]) ) return converted def setupPlots(self): self.area = DockArea() self.setCentralWidget(self.area) self.plotDict = SequenceDict() # initialize all the plot windows we want plotNames = self.config.get(self.configName+'.PlotNames', ['Plot']) if len(plotNames) < 1: plotNames.append('Plot') if 'Autoload' not in plotNames: plotNames.append('Autoload') for name in plotNames: dock = Dock(name) widget = DateTimePlotWidget(self, name=name) view = widget._graphicsView self.area.addDock(dock, "bottom") dock.addWidget(widget) self.plotDict[name] = {"dock":dock, "widget":widget, "view":view} def onAddPlot(self): name, ok = QtGui.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ') if ok and name!= 'Autoload': name = str(name) dock = Dock(name) widget = DateTimePlotWidget(self) view = widget._graphicsView self.area.addDock(dock, "bottom") dock.addWidget(widget) self.plotDict[name] = {"dock":dock, "widget":widget, "view":view} def onRemovePlot(self): self.editablePlots = {} self.editablePlots.update(self.plotDict) if 'Autoload' in self.editablePlots: self.editablePlots.pop('Autoload') logger = logging.getLogger(__name__) if len(self.plotDict) > 0: name, ok = QtGui.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", self.editablePlots.keys(), editable=False) if ok and name != 'Autoload': if ok: name = str(name) self.plotDict[name]["dock"].close() del self.plotDict[name] else: logger.info("There are no plots which can be removed") def onRenamePlot(self): self.plotDisplayData = self.settingsUi.settings.plotDisplayData self.editablePlots = {} self.editablePlots.update(self.plotDict) if 'Autoload' in self.editablePlots: self.editablePlots.pop('Autoload') logger = logging.getLogger(__name__) if len(self.plotDict) > 0: name, ok = QtGui.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", self.editablePlots.keys(), editable=False) if ok and name != 'Autoload': newName, newOk = QtGui.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ') if newOk and newName != 'Autoload': name = str(name) newName = str(newName) self.plotDict[name]["dock"].label.setText(QtCore.QString(newName)) self.plotDict[newName] = self.plotDict[name] for plotName in list(self.plotDisplayData.keys()): plotString = str(plotName) if name == plotString: plotIndex = self.plotDisplayData.index(plotName) self.plotDisplayData.renameAt(plotIndex, newName) del self.plotDict[name] self.onSettingsChanged() else: logger.info("There are no plots which can be renamed")
class AWGUi(AWGForm, AWGBase): varDictChanged = QtCore.pyqtSignal(object) def __init__(self, deviceClass, config, globalDict, parent=None): AWGBase.__init__(self, parent) AWGForm.__init__(self) self.config = config self.configname = 'AWGUi.' + deviceClass.displayName self.globalDict = globalDict self.autoSave = self.config.get(self.configname+'.autoSave', True) self.waveformCache = OrderedDict() self.settingsDict = self.config.get(self.configname+'.settingsDict', dict()) self.settingsName = self.config.get(self.configname+'.settingsName', '') # self.settingsDict=dict() # self.settingsName='' self.recentFiles = self.config.get(self.configname+'.recentFiles', dict()) #dict of form {basename: filename}, where filename has path and basename doesn't self.lastDir = self.config.get(self.configname+'.lastDir', getProject().configDir) Settings.deviceProperties = deviceClass.deviceProperties Settings.saveIfNecessary = self.saveIfNecessary Settings.replot = self.replot for settings in list(self.settingsDict.values()): #make sure all pickled settings are consistent with device, in case it changed for channel in range(deviceClass.deviceProperties['numChannels']): if channel >= len(settings.channelSettingsList): #create new channels if it's necessary settings.channelSettingsList.append({ 'segmentDataRoot':AWGSegmentNode(None), 'segmentTreeState':None, 'plotEnabled':True, 'plotStyle':Settings.plotStyles.lines}) else: settings.channelSettingsList[channel].setdefault('segmentDataRoot', AWGSegmentNode(None)) settings.channelSettingsList[channel].setdefault('segmentTreeState', None) settings.channelSettingsList[channel].setdefault('plotEnabled', True) settings.channelSettingsList[channel].setdefault('plotStyle', Settings.plotStyles.lines) self.settings = Settings() #we always run settings through the constructor if self.settingsName in self.settingsDict: self.settings.update(self.settingsDict[self.settingsName]) self.device = deviceClass(self.settings) def setupUi(self, parent): logger = logging.getLogger(__name__) AWGForm.setupUi(self, parent) self.setWindowTitle(self.device.displayName) self._varAsOutputChannelDict = dict() self.area = DockArea() self.splitter.insertWidget(0, self.area) self.awgChannelUiList = [] for channel in range(self.device.deviceProperties['numChannels']): awgChannelUi = AWGChannelUi(channel, self.settings, self.globalDict, self.waveformCache, parent=self) awgChannelUi.setupUi(awgChannelUi) awgChannelUi.dependenciesChanged.connect(self.onDependenciesChanged) self.awgChannelUiList.append(awgChannelUi) dock = Dock("AWG Channel {0}".format(channel)) dock.addWidget(awgChannelUi) self.area.addDock(dock, 'right') self.device.waveforms[channel] = awgChannelUi.waveform self.refreshVarDict() # Settings control self.saveButton.clicked.connect( self.onSave ) self.removeButton.clicked.connect( self.onRemove ) self.reloadButton.clicked.connect( self.onReload ) self.settingsModel = QtCore.QStringListModel() self.settingsComboBox.setModel(self.settingsModel) self.settingsModel.setStringList( sorted(self.settingsDict.keys()) ) self.settingsComboBox.setCurrentIndex( self.settingsComboBox.findText(self.settingsName) ) self.settingsComboBox.currentIndexChanged[str].connect( self.onLoad ) self.settingsComboBox.lineEdit().editingFinished.connect( self.onComboBoxEditingFinished ) self.autoSaveCheckBox.setChecked(self.autoSave) self.saveButton.setEnabled( not self.autoSave ) self.saveButton.setVisible( not self.autoSave ) self.reloadButton.setEnabled( not self.autoSave ) self.reloadButton.setVisible( not self.autoSave ) self.autoSaveCheckBox.stateChanged.connect(self.onAutoSave) #programming options table self.programmingOptionsTable.setupUi(globalDict=self.globalDict, parameterDict=self.device.parameters()) self.programmingOptionsTable.valueChanged.connect( self.device.update ) # Table self.tableModel = AWGTableModel(self.settings, self.globalDict) self.tableView.setModel(self.tableModel) self.tableModel.valueChanged.connect(self.onValue) self.delegate = MagnitudeSpinBoxDelegate(self.globalDict) self.tableView.setItemDelegateForColumn(self.tableModel.column.value, self.delegate) #File self.filenameModel = QtCore.QStringListModel() self.filenameComboBox.setModel(self.filenameModel) self.filenameModel.setStringList( [basename for basename, filename in list(self.recentFiles.items()) if os.path.exists(filename)] ) self.filenameComboBox.setCurrentIndex(self.filenameComboBox.findText(os.path.basename(self.settings.filename))) self.filenameComboBox.currentIndexChanged[str].connect(self.onFilename) self.removeFileButton.clicked.connect(self.onRemoveFile) self.newFileButton.clicked.connect(self.onNewFile) self.openFileButton.clicked.connect(self.onOpenFile) self.saveFileButton.clicked.connect(self.onSaveFile) self.reloadFileButton.clicked.connect(self.onReloadFile) #cache self.cacheDepthSpinBox.setValue(self.settings.cacheDepth) self.cacheDepthSpinBox.valueChanged.connect(self.onCacheDepth) self.clearCacheButton.clicked.connect(self.onClearCache) #status bar self.label = QtGui.QLabel('Sample Rate: {0}'.format(self.settings.deviceProperties['sampleRate'])) self.statusbar.addWidget(self.label) #Restore GUI state state = self.config.get(self.configname+'.state') pos = self.config.get(self.configname+'.pos') size = self.config.get(self.configname+'.size') isMaximized = self.config.get(self.configname+'.isMaximized') dockAreaState = self.config.get(self.configname+'.dockAreaState') guiState = self.config.get(self.configname+".guiState") restoreGuiState(self, guiState) try: if pos: self.move(pos) if size: self.resize(size) if isMaximized: self.showMaximized() if state: self.restoreState(state) for awgChannelUi in self.awgChannelUiList: channelGuiState = self.config[self.configname+"channel{0}.guiState".format(awgChannelUi.channel)] restoreGuiState(awgChannelUi, channelGuiState) except Exception as e: logger.warning("Error on restoring state in AWGUi {0}. Exception occurred: {1}".format(self.device.displayName, e)) try: if dockAreaState: self.area.restoreState(dockAreaState) except Exception as e: logger.warning("Cannot restore dock state in AWGUi {0}. Exception occurred: {1}".format(self.device.displayName, e)) self.area.deleteLater() self.area = DockArea() self.splitter.insertWidget(0, self.area) for channelUi in self.awgChannelUiList: dock = Dock("AWG Channel {0}".format(channel)) dock.addWidget(channelUi) self.area.addDock(dock, 'right') self.saveIfNecessary() def onCacheDepth(self, newVal): self.settings.cacheDepth = newVal self.saveIfNecessary() def onClearCache(self): self.waveformCache.clear() def onComboBoxEditingFinished(self): """a settings name is typed into the combo box""" currentText = str(self.settingsComboBox.currentText()) if self.settingsName != currentText: self.settingsName = currentText if self.settingsName not in self.settingsDict: self.settingsDict[self.settingsName] = copy.deepcopy(self.settings) self.onLoad(self.settingsName) def saveIfNecessary(self): """save the current settings if autosave is on and something has changed""" currentText = str(self.settingsComboBox.currentText()) if self.settingsDict.get(self.settingsName)!=self.settings or currentText!=self.settingsName: if self.autoSave: self.onSave() else: self.saveButton.setEnabled(True) def replot(self): """plot all channels""" for channelUi in self.awgChannelUiList: channelUi.replot() def onSave(self): """save current settings""" self.settingsName = str(self.settingsComboBox.currentText()) self.settingsDict[self.settingsName] = copy.deepcopy(self.settings) with BlockSignals(self.settingsComboBox) as w: self.settingsModel.setStringList( sorted(self.settingsDict.keys()) ) w.setCurrentIndex(w.findText(self.settingsName)) self.saveButton.setEnabled(False) def saveConfig(self): """save GUI configuration to config""" self.config[self.configname+".guiState"] = saveGuiState(self) for awgChannelUi in self.awgChannelUiList: self.config[self.configname+"channel{0}.guiState".format(awgChannelUi.channel)] = saveGuiState(awgChannelUi) self.settings.channelSettingsList[awgChannelUi.channel]['segmentTreeState'] = awgChannelUi.segmentView.saveTreeState() self.config[self.configname+'.state'] = self.saveState() self.config[self.configname+'.pos'] = self.pos() self.config[self.configname+'.size'] = self.size() self.config[self.configname+'.isMaximized'] = self.isMaximized() self.config[self.configname+'.isVisible'] = self.isVisible() self.config[self.configname+'.dockAreaState'] = self.area.saveState() self.config[self.configname+'.settingsDict'] = self.settingsDict self.config[self.configname+'.settingsName'] = self.settingsName self.config[self.configname+'.autoSave'] = self.autoSave self.config[self.configname+'.recentFiles'] = self.recentFiles self.config[self.configname+'.lastDir'] = self.lastDir def onRemove(self): """Remove current settings from combo box""" name = str(self.settingsComboBox.currentText()) if name in self.settingsDict: self.settingsDict.pop(name) self.settingsName = list(self.settingsDict.keys())[0] if self.settingsDict else '' with BlockSignals(self.settingsComboBox) as w: self.settingsModel.setStringList( sorted(self.settingsDict.keys()) ) w.setCurrentIndex(w.findText(self.settingsName)) self.onLoad(self.settingsName) def onReload(self): """Reload settings""" name = str(self.settingsComboBox.currentText()) self.onLoad(name) def onLoad(self, name): """load settings""" for channelUi in self.awgChannelUiList: self.settings.channelSettingsList[channelUi.channel]['segmentTreeState'] = channelUi.segmentView.saveTreeState() name = str(name) if name in self.settingsDict: self.settingsName = name self.tableModel.beginResetModel() [channelUi.segmentModel.beginResetModel() for channelUi in self.awgChannelUiList] self.settings.update(self.settingsDict[self.settingsName]) self.programmingOptionsTable.setParameters( self.device.parameters() ) self.saveButton.setEnabled(False) with BlockSignals(self.filenameComboBox) as w: w.setCurrentIndex(w.findText(os.path.basename(self.settings.filename))) with BlockSignals(self.cacheDepthSpinBox) as w: w.setValue(self.settings.cacheDepth) for channelUi in self.awgChannelUiList: channelUi.waveform.updateDependencies() channelUi.plotCheckbox.setChecked(self.settings.channelSettingsList[channelUi.channel]['plotEnabled']) with BlockSignals(channelUi.styleComboBox) as w: w.setCurrentIndex(self.settings.channelSettingsList[channelUi.channel]['plotStyle']) channelUi.segmentModel.root = self.settings.channelSettingsList[channelUi.channel]['segmentDataRoot'] channelUi.replot() self.onDependenciesChanged() self.saveButton.setEnabled(False) self.tableModel.endResetModel() [channelUi.segmentModel.endResetModel() for channelUi in self.awgChannelUiList] for channelUi in self.awgChannelUiList: channelUi.segmentView.restoreTreeState(self.settings.channelSettingsList[channelUi.channel]['segmentTreeState']) def onAutoSave(self, checked): """autosave is changed""" self.autoSave = checked self.saveButton.setEnabled( not checked ) self.saveButton.setVisible( not checked ) self.reloadButton.setEnabled( not checked ) self.reloadButton.setVisible( not checked ) if checked: self.onSave() def onValue(self, var=None, value=None): """variable value is changed in the table""" self.saveIfNecessary() self.replot() def evaluate(self, name): """re-evaluate the text in the tableModel (happens when a global changes)""" self.tableModel.evaluate(name) self.programmingOptionsTable.evaluate(name) def refreshVarDict(self): """refresh the variable dictionary by checking all waveform dependencies""" allDependencies = set() [channelUi.waveform.updateDependencies() for channelUi in self.awgChannelUiList] [allDependencies.update(channelUi.waveform.dependencies) for channelUi in self.awgChannelUiList] default = lambda varname:{'value':Q(1, 'us'), 'text':None} if varname.startswith('Duration') else {'value':Q(0), 'text':None} deletions = [varname for varname in self.settings.varDict if varname not in allDependencies] [self.settings.varDict.pop(varname) for varname in deletions] #remove all values that aren't dependencies anymore [self.settings.varDict.setdefault(varname, default(varname)) for varname in allDependencies] #add missing values self.settings.varDict.sort(key = lambda val: -1 if val[0].startswith('Duration') else ord( str(val[0])[0] )) self.varDictChanged.emit(self.varAsOutputChannelDict) for channelUi in self.awgChannelUiList: channelUi.replot() def onDependenciesChanged(self, channel=None): """When dependencies change, refresh all variables""" self.tableModel.beginResetModel() self.refreshVarDict() self.tableModel.endResetModel() self.saveIfNecessary() def onFilename(self, basename): """filename combo box is changed. Open selected file""" basename = str(basename) filename = self.recentFiles[basename] if os.path.isfile(filename) and filename!=self.settings.filename: self.openFile(filename) def onRemoveFile(self): """Remove file button is clicked. Remove filename from combo box.""" text = str(self.filenameComboBox.currentText()) index = self.filenameComboBox.findText(text) if text in self.recentFiles: self.recentFiles.pop(text) with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(-1) self.onFilename(w.currentText()) def onNewFile(self): """New button is clicked. Pop up dialog asking for new name, and create file.""" filename, _ = QtWidgets.QFileDialog.getSaveFileName(self, 'New File', self.lastDir, 'YAML (*.yml)') if filename: self.lastDir, basename = os.path.split(filename) self.recentFiles[basename] = filename self.settings.filename = filename with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(w.findText(basename)) self.onSaveFile() def onOpenFile(self): """Open file button is clicked. Pop up dialog asking for filename.""" filename, _ = QtWidgets.QFileDialog.getOpenFileName(self, 'Select File', self.lastDir, 'YAML (*.yml)') if filename: self.openFile(filename) def openFile(self, filename): """Open the file 'filename'""" if os.path.exists(filename): self.lastDir, basename = os.path.split(filename) self.recentFiles[basename] = filename self.settings.filename = filename with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(w.findText(basename)) with open(filename, 'r') as f: yamldata = yaml.load(f) variables = yamldata.get('variables') channelData = yamldata.get('channelData') self.tableModel.beginResetModel() [channelUi.segmentModel.beginResetModel() for channelUi in self.awgChannelUiList] if channelData: for channelUi in self.awgChannelUiList: if channelUi.channel < len(channelData): self.settings.channelSettingsList[channelUi.channel]['segmentDataRoot'] = self.convertListToNodes(channelData[channelUi.channel], isRoot=True) channelUi.segmentModel.root = self.settings.channelSettingsList[channelUi.channel]['segmentDataRoot'] if variables: for varname, vardata in list(variables.items()): self.settings.varDict.setdefault(varname, dict()) self.settings.varDict[varname]['value'] = Q(vardata['value'], vardata['unit']) self.settings.varDict[varname]['text'] = vardata['text'] for channelUi in self.awgChannelUiList: channelUi.waveform.updateDependencies() channelUi.replot() self.onDependenciesChanged() self.tableModel.endResetModel() [channelUi.segmentModel.endResetModel() for channelUi in self.awgChannelUiList] [channelUi.segmentView.expandAll() for channelUi in self.awgChannelUiList] else: logging.getLogger(__name__).warning("file '{0}' does not exist".format(filename)) if filename in self.recentFiles: del self.recentFiles[filename] with BlockSignals(self.filenameComboBox) as w: self.filenameModel.setStringList(list(self.recentFiles.keys())) w.setCurrentIndex(-1) def convertNodeToList(self, node): nodeList = [] for childNode in node.children: if childNode.nodeType==nodeTypes.segment: nodeList.append( {'equation':childNode.equation, 'duration':childNode.duration, 'enabled':childNode.enabled} ) elif childNode.nodeType==nodeTypes.segmentSet: nodeList.append( {'repetitions':childNode.repetitions, 'enabled':childNode.enabled, 'segments':self.convertNodeToList(childNode)} ) return nodeList def convertListToNodes(self, data, parent=None, enabled=True, repetitions=None, isRoot=False): node = AWGSegmentNode(parent=None) if isRoot else AWGSegmentSet(parent=parent, enabled=enabled, repetitions=repetitions) for segment in data: if 'duration' in segment: childNode = AWGSegment(parent=node, equation=segment['equation'], duration=segment['duration'], enabled=segment['enabled']) node.children.append(childNode) elif 'repetitions' in segment: segmentSet = self.convertListToNodes(segment['segments'], parent=node, enabled=segment['enabled'], repetitions=segment['repetitions']) node.children.append(segmentSet) else: logging.getLogger(__name__).error("Unable to convert list to nodes") return node def onSaveFile(self): """Save button is clicked. Save data to segment file""" channelData = [] for channelSettings in self.settings.channelSettingsList: segmentData = self.convertNodeToList(channelSettings['segmentDataRoot']) channelData.append(segmentData) yamldata = {'channelData': channelData} variables={varname: {'value':float(varValueTextDict['value'].toStringTuple()[0]), 'unit':varValueTextDict['value'].toStringTuple()[1], 'text':varValueTextDict['text']} for varname, varValueTextDict in list(self.settings.varDict.items())} yamldata.update({'variables':variables}) with open(self.settings.filename, 'w') as f: yaml.dump(yamldata, f, default_flow_style=False) def onReloadFile(self): self.openFile(self.settings.filename) @QtCore.pyqtProperty(dict) def varAsOutputChannelDict(self): """dict of output channels, for use in scans""" for varname in self.settings.varDict: if varname not in self._varAsOutputChannelDict: self._varAsOutputChannelDict[varname] = VarAsOutputChannel(self, varname, self.globalDict) deletions = [varname for varname in self._varAsOutputChannelDict if varname not in self.settings.varDict] [self._varAsOutputChannelDict.pop(varname) for varname in deletions] #remove all values that aren't dependencies anymore return self._varAsOutputChannelDict def close(self): self.saveConfig() numTempAreas = len(self.area.tempAreas) for i in range(numTempAreas): if len(self.area.tempAreas) > 0: self.area.tempAreas[0].win.close() super(AWGUi, self).close()
class InstrumentLoggingUi(WidgetContainerBase, WidgetContainerForm): plotConfigurationChanged = QtCore.pyqtSignal( object ) def __init__(self, project, config): super(InstrumentLoggingUi, self).__init__() self.config = config self.project = project self.dockWidgetList = list() self.plotDict = dict() self.instrument = "" def __enter__(self): return self def __exit__(self, excepttype, value, traceback): return False def setupUi(self, parent): super(InstrumentLoggingUi, self).setupUi(parent) logger = logging.getLogger() self.parent = parent self.tabList = list() self.tabDict = dict() self.setupPlots() # Traceui self.penicons = pens.penicons().penicons() self.traceui = Traceui.Traceui(self.penicons, self.config, "Main", self.plotDict ) self.traceui.setupUi(self.traceui) self.setupAsDockWidget(self.traceui, "Traces", QtCore.Qt.LeftDockWidgetArea) # new fit widget self.fitWidget = FitUi(self.traceui, self.config, "Main") self.fitWidget.setupUi(self.fitWidget) self.fitWidgetDock = self.setupAsDockWidget(self.fitWidget, "Fit", QtCore.Qt.LeftDockWidgetArea) self.instrumentLoggingHandler = InstrumentLoggingHandler(self.traceui, self.plotDict, self.config, 'externalInput') self.ExternalParametersSelectionUi = InstrumentLoggingSelection(self.config, classdict=LoggingInstruments, newDataSlot=self.instrumentLoggingHandler.addData, plotNames=list(self.plotDict.keys()), instrumentLoggingHandler=self.instrumentLoggingHandler ) self.ExternalParametersSelectionUi.setupUi( self.ExternalParametersSelectionUi ) self.ExternalParameterSelectionDock = QtWidgets.QDockWidget("Params Selection") self.ExternalParameterSelectionDock.setObjectName("_ExternalParameterSelectionDock") self.ExternalParameterSelectionDock.setWidget(self.ExternalParametersSelectionUi) self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.ExternalParameterSelectionDock) self.instrumentLoggingHandler.paramTreeChanged.connect( self.ExternalParametersSelectionUi.refreshParamTree) self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config) self.instrumentLoggingDisplay.setupUi( self.ExternalParametersSelectionUi.enabledParametersObjects, self.instrumentLoggingDisplay ) self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget("Params Reading") self.instrumentLoggingDisplayDock.setObjectName("_ExternalParameterDisplayDock") self.instrumentLoggingDisplayDock.setWidget(self.instrumentLoggingDisplay) self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.instrumentLoggingDisplayDock) self.ExternalParametersSelectionUi.selectionChanged.connect( self.instrumentLoggingDisplay.setupParameters ) self.instrumentLoggingHandler.newData.connect( self.instrumentLoggingDisplay.update ) self.instrumentLoggingQueryUi = InstrumentLoggerQueryUi(self.config, self.traceui, self.plotDict ) self.instrumentLoggingQueryUi.setupUi( self.instrumentLoggingQueryUi ) self.instrumentLoggingQueryUiDock = self.setupAsDockWidget(self.instrumentLoggingQueryUi, "Query", QtCore.Qt.LeftDockWidgetArea) self.addPlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self) self.addPlot.setToolTip("Add new plot") self.addPlot.triggered.connect(self.onAddPlot) self.toolBar.addAction(self.addPlot) self.removePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self) self.removePlot.setToolTip("Remove a plot") self.removePlot.triggered.connect(self.onRemovePlot) self.toolBar.addAction(self.removePlot) self.renamePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self) self.renamePlot.setToolTip("Rename a plot") self.renamePlot.triggered.connect(self.onRenamePlot) self.toolBar.addAction(self.renamePlot) self.setWindowTitle("Instrument Logger ({0})".format(self.project) ) if 'MainWindow.State' in self.config: self.parent.restoreState(self.config['MainWindow.State']) try: if 'pyqtgraph-dockareastate' in self.config: self.area.restoreState(self.config['pyqtgraph-dockareastate']) except Exception as e: logger.warning("Cannot restore dock state in experiment {0}. Exception occurred: ".format(self.experimentName) + str(e)) QtCore.QTimer.singleShot(60000, self.onCommitConfig ) def setupPlots(self): self.area = DockArea() self.setCentralWidget(self.area) self.plotDict = dict() # initialize all the plot windows we want plotNames = self.config.get( 'PlotNames', ['Scan'] ) if len(plotNames)<1: plotNames.append('Scan') for name in plotNames: dock = Dock(name) widget = DateTimePlotWidget(self, name=name) view = widget._graphicsView self.area.addDock(dock, "bottom") dock.addWidget(widget) self.plotDict[name] = {"dock":dock, "widget":widget, "view":view} def setupAsDockWidget(self, widget, name, area=QtCore.Qt.RightDockWidgetArea, stackAbove=None, stackBelow=None ): dock = QtWidgets.QDockWidget(name) dock.setObjectName(name) dock.setWidget( widget ) self.addDockWidget(area, dock ) self.dockWidgetList.append( dock ) if stackAbove is not None: self.tabifyDockWidget( stackAbove, dock ) elif stackBelow is not None: self.tabifyDockWidget( dock, stackBelow ) return dock def onAddPlot(self): name, ok = QtWidgets.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ') if ok: name = str(name) dock = Dock(name) widget = DateTimePlotWidget(self) view = widget._graphicsView self.area.addDock(dock, "bottom") dock.addWidget(widget) self.plotDict[name] = {"dock":dock, "widget":widget, "view":view} self.plotConfigurationChanged.emit( self.plotDict ) def onRemovePlot(self): logger = logging.getLogger(__name__) if len(self.plotDict) > 0: name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", list(self.plotDict.keys()), editable=False) if ok: name = str(name) self.plotDict[name]["dock"].close() del self.plotDict[name] self.plotConfigurationChanged.emit( self.plotDict ) else: logger.info("There are no plots which can be removed") def onRenamePlot(self): logger = logging.getLogger(__name__) if len(self.plotDict) > 0: name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", list(self.plotDict.keys()), editable=False) if ok: newName, newOk = QtWidgets.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ') if newOk: name = str(name) newName = str(newName) self.plotDict[name]["dock"].label.setText(str(newName)) self.plotDict[newName] = self.plotDict[name] del self.plotDict[name] self.plotConfigurationChanged.emit( self.plotDict ) else: logger.info("There are no plots which can be renamed") def onSave(self): logger = logging.getLogger(__name__) logger.info( "Saving config" ) filename, _ = DataDirectory.DataDirectory().sequencefile("InstrumentLogger-configuration.db") self.saveConfig() self.config.saveConfig(filename) def onClose(self): self.parent.close() def closeEvent(self, e): logger = logging.getLogger(__name__) logger.info( "Close Event" ) logger = logging.getLogger("") logger.debug( "Saving Configuration" ) self.saveConfig() def saveConfig(self): self.config['MainWindow.State'] = self.parent.saveState() for tab in self.tabList: tab.saveConfig() self.config['MainWindow.pos'] = self.pos() self.config['MainWindow.size'] = self.size() self.config['PlotNames'] = list(self.plotDict.keys()) self.config['pyqtgraph-dockareastate'] = self.area.saveState() self.ExternalParametersSelectionUi.saveConfig() self.instrumentLoggingHandler.saveConfig() self.instrumentLoggingQueryUi.saveConfig() self.instrumentLoggingDisplay.saveConfig() def onCommitConfig(self): self.saveConfig() QtCore.QTimer.singleShot(60000, self.onCommitConfig )
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
def initDialog(self,results=None,KData=None,bDrawText=False): ''' orders,记录当日00:00前一日开盘时间发送的交易命令 trasactions,记录当日00:00前一日已执行的orders positions,记录当日00:00时,各个symbols的positions 所以,这三个量都是数组,且大小不定,所以,不宜图形方式展示,适宜table方式展示 其他单值参数都可以考虑图形化方式 特别是pnl,cash,portfolio等 perf的生成时点是00:00,其内容为00:00前一天的活动 perf转化记录入result时,需要设置Index, 此Index的值为生成记录时点后的一天的收盘时间。 例如: 有三个交易日:2015-12-01,12-02,12-03 开收盘时间:Asia/Shanghai:09:30--15:00 (utc:01:30--07:00) 使用instant_fill==True方式执行订单 每日开盘时Buy(1) 有如下Events列表会生成并被处理 1)2015-12-01 00:00 utc 生成perf perf内容:由于是第一交易日的开始时间(非开市时间),无内容可记 记录入result: 记录Index:result.index = 2015-12-01 07:00 2)2015-12-01 01:30 utc 生成order,生成transaction,生成position 3)2015-12-02 00:00 utc 生成perf perf内容:2015-12-01 00:00 utc 至 2015-12-02 00:00 utc期间发生的交易事项及内容 记录入result: 记录Index:result.index = 2015-12-02 07:00 之后的4)5)6)同上 不合逻辑的地方需特别注意: 1)perf的生成时间和记录时间不一致,00:00生成(当日开始(非开市)),07:00记录(当日收市) 2)perf记录的是00:00之前一日的交易,记录时点却是当日收盘(当日收盘时间的记录,给人直观的理解应是记录当日开盘到收盘期间发生的业务) ''' # 1) creates layouts dialog = QtGui.QDialog() mainLayout = QtGui.QHBoxLayout() rightLayout = QtGui.QVBoxLayout() mainLayout.addLayout(rightLayout) dialog.setLayout(mainLayout) dialog.setWindowTitle(('Strategy Results')) # 2) creates widgets # 2.1)candle import os,sys xpower = os.path.abspath(os.path.join(os.path.dirname(__file__),os.pardir,os.pardir,os.pardir,'midProjects','histdataUI')) sys.path.append(xpower) from Widgets.pgCandleWidgetCross import pgCandleWidgetCross from Widgets.pgCrossAddition import pgCrossAddition pgCandleView = pgCandleWidgetCross(dataForCandle=KData) self.pricePlot(pgCandleView) # 2.2)Pnl PyqtGraphPnl = pgCrossAddition() self.pnlPlot(PyqtGraphPnl,bDrawText=bDrawText) # 2.3)Position #PyqtGraphPosition = pgCrossAddition() #self.positionPlot(PyqtGraphPosition) # 2.4)portfolio PyqtGraphPortfolio = pgCrossAddition() self.portfolioPlot(PyqtGraphPortfolio) # 2.5)price PyqtGraphindicators = pgCrossAddition() self.pricePlot(PyqtGraphindicators) self.indicatorsPlot(PyqtGraphindicators) # 2.6)order #PyqtGraphOrder = pgCrossAddition() #self.orderPlot(PyqtGraphOrder) #self.pricePlot(PyqtGraphOrder) from pyqtgraph.dockarea import DockArea,Dock area = DockArea() ## Create docks, place them into the window one at a time. ## Note that size arguments are only a suggestion; docks will still have to ## fill the entire dock area and obey the limits of their internal widgets. d1 = Dock("candles", size=(200,300)) ## give this dock the minimum possible size d2 = Dock("pnl", closable=True, size=(200,100)) #d3 = Dock("position", size=(200,100)) d4 = Dock("portfolio", size=(200,100)) d5 = Dock("price", size=(200,100)) #d6 = Dock("order time,amount",size=(200,100)) area.addDock(d1, 'bottom') area.addDock(d2, 'bottom') #area.addDock(d3, 'bottom') area.addDock(d4, 'bottom') area.addDock(d5, 'bottom', d1) #area.addDock(d6, 'bottom', d1) rightLayout.addWidget(area) d1.addWidget(pgCandleView) d2.addWidget(PyqtGraphPnl) #d3.addWidget(PyqtGraphPosition) d4.addWidget(PyqtGraphPortfolio) d5.addWidget(PyqtGraphindicators) #d6.addWidget(PyqtGraphOrder) PyqtGraphPnl.setXLink(pgCandleView) #PyqtGraphPosition.setXLink(pgCandleView) PyqtGraphPortfolio.setXLink(pgCandleView) PyqtGraphindicators.setXLink(pgCandleView) #PyqtGraphOrder.setXLink(pgCandleView) return dialog
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()
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
def __init__(self, stedlaser, slm, scanZ, scanXY, webcamFocusLock, aotf, leicastand, *args, **kwargs): super().__init__(*args, **kwargs) # os.chdir('C:\\Users\\STEDred\Documents\TempestaSnapshots') self.slm = slm self.scanZ = scanZ self.aotf = aotf self.scanXY = scanXY self.dmi8 = leicastand self.imspector = sp.Imspector() self.filewarning = FileWarning() self.s = Q_(1, 's') self.lastTime = time.clock() self.fps = None # Actions in menubar menubar = self.menuBar() fileMenu = menubar.addMenu('&File') self.savePresetAction = QtGui.QAction('Save configuration...', self) self.savePresetAction.setShortcut('Ctrl+S') self.savePresetAction.setStatusTip('Save camera & recording settings') savePresetFunction = lambda: guitools.savePreset(self) self.savePresetAction.triggered.connect(savePresetFunction) fileMenu.addAction(self.savePresetAction) fileMenu.addSeparator() self.exportTiffAction = QtGui.QAction('Export HDF5 to Tiff...', self) self.exportTiffAction.setShortcut('Ctrl+E') self.exportTiffAction.setStatusTip('Export HDF5 file to Tiff format') self.exportTiffAction.triggered.connect(guitools.TiffConverterThread) fileMenu.addAction(self.exportTiffAction) self.exportlastAction = QtGui.QAction('Export last recording to Tiff', self) self.exportlastAction.setEnabled(False) self.exportlastAction.setShortcut('Ctrl+L') self.exportlastAction.setStatusTip('Export last recording to Tiff ' + 'format') fileMenu.addAction(self.exportlastAction) fileMenu.addSeparator() exitAction = QtGui.QAction(QtGui.QIcon('exit.png'), '&Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(QtGui.QApplication.closeAllWindows) fileMenu.addAction(exitAction) # Potentially remove all this? self.presetsMenu = QtGui.QComboBox() self.presetDir = datapath if not (os.path.isdir(self.presetDir)): self.presetDir = os.path.join(os.getcwd(), 'control\\Presets') for preset in os.listdir(self.presetDir): self.presetsMenu.addItem(preset) self.loadPresetButton = QtGui.QPushButton('Load preset') loadPresetFunction = lambda: guitools.loadPreset(self) self.loadPresetButton.pressed.connect(loadPresetFunction) # Dock widget dockArea = DockArea() # Laser Widget laserDock = Dock("Laser Control", size=(400, 500)) self.lasers = stedlaser self.laserWidgets = LaserWidget.LaserWidget(self.lasers, self.aotf) laserDock.addWidget(self.laserWidgets) dockArea.addDock(laserDock, 'right') # SLM widget slmDock = Dock("SLM", size=(400, 300)) self.slmWidget = slmWidget.slmWidget(self.slm) slmDock.addWidget(self.slmWidget) dockArea.addDock(slmDock, "bottom", laserDock) # Widefield camera widget #widefieldDock = Dock("Widefield", size=(500, 500)) #self.widefieldWidget = widefield.WidefieldWidget(webcamWidefield) #widefieldDock.addWidget(self.widefieldWidget) #dockArea.addDock(widefieldDock, "left") # Focus lock widget focusDock = Dock("Focus lock", size=(500, 500)) self.focusWidget = focus.FocusWidget(self.scanZ, webcamFocusLock, self.imspector) focusDock.addWidget(self.focusWidget) #dockArea.addDock(focusDock, "below", widefieldDock) dockArea.addDock(focusDock, "left") # Timelapse widget timelapseDock = Dock("Timelapse", size=(500, 200)) self.timelapseWidget = timelapse.TimelapseWidget(self.imspector) timelapseDock.addWidget(self.timelapseWidget) #dockArea.addDock(timelapseDock, "top", widefieldDock) dockArea.addDock(timelapseDock, "top", focusDock) # Objective mot_corr widget motcorrDock = Dock("Glycerol motCORR", size=(500, 200)) self.MotcorrWidget = motcorr.MotcorrWidget(self.dmi8) motcorrDock.addWidget(self.MotcorrWidget) dockArea.addDock(motcorrDock, "below", timelapseDock) # XY-scanner tiling widget tilingDock = Dock("Tiling", size=(500, 200)) self.tilingWidget = tiling.TilingWidget(self.scanXY, self.focusWidget, self.imspector) tilingDock.addWidget(self.tilingWidget) dockArea.addDock(tilingDock, "below", timelapseDock) self.setWindowTitle('Tempesta - RedSTED edition') self.cwidget = QtGui.QWidget() self.setCentralWidget(self.cwidget) # Widgets' layout layout = QtGui.QGridLayout() self.cwidget.setLayout(layout) # layout.setColumnMinimumWidth(0, 100) # layout.setColumnMinimumWidth(1, 350) # layout.setColumnMinimumWidth(2, 150) # layout.setColumnMinimumWidth(3, 200) # layout.setRowMinimumHeight(0, 350) # layout.setRowMinimumHeight(1, 350) # layout.setRowMinimumHeight(2, 350) # layout.setRowMinimumHeight(3, 30) layout.addWidget(dockArea, 0, 3, 5, 1)
class InstrumentLoggingUi(WidgetContainerBase, WidgetContainerForm): levelNameList = ["debug", "info", "warning", "error", "critical"] levelValueList = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, logging.CRITICAL] plotConfigurationChanged = QtCore.pyqtSignal( object ) def __init__(self, project, config): super(InstrumentLoggingUi, self).__init__() self.config = config self.project = project self.dockWidgetList = list() self.plotDict = dict() self.instrument = "" self.loggingLevel = config.get('Settings.loggingLevel', logging.INFO) self.consoleMaximumLines = config.get('Settings.consoleMaximumLinesNew', 100) self.consoleEnable = config.get('Settings.consoleEnable', False) self.printMenu = None if self.loggingLevel not in self.levelValueList: self.loggingLevel = logging.INFO def __enter__(self): return self def __exit__(self, excepttype, value, traceback): return False def setupUi(self, parent): super(InstrumentLoggingUi, self).setupUi(parent) self.dockWidgetConsole.hide() self.loggerUi = LoggerLevelsUi(self.config) self.loggerUi.setupUi(self.loggerUi) self.loggerDock = QtWidgets.QDockWidget("Logging") self.loggerDock.setWidget(self.loggerUi) self.loggerDock.setObjectName("_LoggerDock") self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.loggerDock) self.loggerDock.hide() logger = logging.getLogger() self.toolBar.addWidget(ExceptionLogButton()) # Setup Console Dockwidget self.levelComboBox.addItems(self.levelNameList) self.levelComboBox.currentIndexChanged[int].connect( self.setLoggingLevel ) self.levelComboBox.setCurrentIndex( self.levelValueList.index(self.loggingLevel) ) self.consoleClearButton.clicked.connect( self.onClearConsole ) self.linesSpinBox.valueChanged.connect( self.onConsoleMaximumLinesChanged ) self.linesSpinBox.setValue( self.consoleMaximumLines ) self.checkBoxEnableConsole.stateChanged.connect( self.onEnableConsole ) self.checkBoxEnableConsole.setChecked( self.consoleEnable ) self.parent = parent self.tabDict = SequenceDict() self.setupPlots() self.preferencesUi = PreferencesUi(config, self) self.preferencesUi.setupUi(self.preferencesUi) self.preferencesUiDock = QtWidgets.QDockWidget("Print Preferences") self.preferencesUiDock.setWidget(self.preferencesUi) self.preferencesUiDock.setObjectName("_preferencesUi") self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.preferencesUiDock) # Traceui self.penicons = pens.penicons().penicons() self.traceui = Traceui.Traceui(self.penicons, self.config, "Main", self.plotDict) self.traceui.setupUi(self.traceui) setattr(self.traceui, 'autoSaveTraces', self.config.get('autoSaveTraces', False)) self.traceui.autoSaveAction = QtWidgets.QAction('Autosave traces', self.traceui) self.traceui.autoSaveAction.setCheckable(True) self.traceui.autoSaveAction.setChecked(self.traceui.autoSaveTraces) self.traceui.autoSaveAction.triggered.connect(lambda checked: setattr(self.traceui, 'autoSaveTraces', checked)) self.traceui.addAction(self.traceui.autoSaveAction) traceuiDock = self.setupAsDockWidget(self.traceui, "Traces", QtCore.Qt.LeftDockWidgetArea) # new fit widget self.fitWidget = FitUi(self.traceui, self.config, "Main") self.fitWidget.setupUi(self.fitWidget) self.fitWidgetDock = self.setupAsDockWidget(self.fitWidget, "Fit", QtCore.Qt.LeftDockWidgetArea, stackBelow=traceuiDock) self.instrumentLoggingHandler = InstrumentLoggingHandler(self.traceui, self.plotDict, self.config, 'externalInput') self.ExternalParametersSelectionUi = InstrumentLoggingSelection(self.config, classdict=LoggingInstruments, plotNames=list(self.plotDict.keys()), instrumentLoggingHandler=self.instrumentLoggingHandler ) self.ExternalParametersSelectionUi.setupUi( self.ExternalParametersSelectionUi ) self.ExternalParameterSelectionDock = QtWidgets.QDockWidget("Params Selection") self.ExternalParameterSelectionDock.setObjectName("_ExternalParameterSelectionDock") self.ExternalParameterSelectionDock.setWidget(self.ExternalParametersSelectionUi) self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.ExternalParameterSelectionDock) self.instrumentLoggingHandler.paramTreeChanged.connect( self.ExternalParametersSelectionUi.refreshParamTree) self.instrumentLoggingHandler.setInputChannels( self.ExternalParametersSelectionUi.inputChannels() ) self.ExternalParametersSelectionUi.inputChannelsChanged.connect( self.instrumentLoggingHandler.setInputChannels ) self.instrumentLoggingDisplay = InstrumentLoggingDisplay(self.config) self.instrumentLoggingDisplay.setupUi( self.ExternalParametersSelectionUi.inputChannels(), self.instrumentLoggingDisplay ) self.instrumentLoggingDisplayDock = QtWidgets.QDockWidget("Params Reading") self.instrumentLoggingDisplayDock.setObjectName("_ExternalParameterDisplayDock") self.instrumentLoggingDisplayDock.setWidget(self.instrumentLoggingDisplay) self.addDockWidget( QtCore.Qt.RightDockWidgetArea, self.instrumentLoggingDisplayDock) self.ExternalParametersSelectionUi.inputChannelsChanged.connect( self.instrumentLoggingDisplay.setupParameters ) self.instrumentLoggingHandler.newData.connect( self.instrumentLoggingDisplay.update ) self.instrumentLoggingQueryUi = InstrumentLoggerQueryUi(self.config, self.traceui, self.plotDict ) self.instrumentLoggingQueryUi.setupUi( self.instrumentLoggingQueryUi ) self.instrumentLoggingQueryUiDock = self.setupAsDockWidget(self.instrumentLoggingQueryUi, "Query", QtCore.Qt.LeftDockWidgetArea) self.addPlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/add-plot.png"), "Add new plot", self) self.addPlot.setToolTip("Add new plot") self.addPlot.triggered.connect(self.onAddPlot) self.toolBar.addAction(self.addPlot) self.removePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/remove-plot.png"), "Remove a plot", self) self.removePlot.setToolTip("Remove a plot") self.removePlot.triggered.connect(self.onRemovePlot) self.toolBar.addAction(self.removePlot) self.renamePlot = QtWidgets.QAction( QtGui.QIcon(":/openicon/icons/rename-plot.png"), "Rename a plot", self) self.renamePlot.setToolTip("Rename a plot") self.renamePlot.triggered.connect(self.onRenamePlot) self.toolBar.addAction(self.renamePlot) self.setWindowTitle( "Instrument Logger ({0})".format(self.project) ) if 'MainWindow.State' in self.config: self.parent.restoreState(self.config['MainWindow.State']) try: if 'pyqtgraph-dockareastate' in self.config: self.area.restoreState(self.config['pyqtgraph-dockareastate']) except Exception as e: logger.error("Cannot restore dock state in experiment {0}. Exception occurred: ".format(self.experimentName) + str(e)) self.initMenu() self.actionProject.triggered.connect( self.onProjectSelection) self.actionExit.triggered.connect(self.onClose) def onProjectSelection(self): ui = ProjectInfoUi(self.project) ui.show() ui.exec_() def onEnableConsole(self, state): self.consoleEnable = state==QtCore.Qt.Checked def onClearConsole(self): self.textEditConsole.clear() def onConsoleMaximumLinesChanged(self, maxlines): self.consoleMaximumLines = maxlines self.textEditConsole.document().setMaximumBlockCount(maxlines) def setLoggingLevel(self, index): self.loggingLevel = self.levelValueList[index] def setupPlots(self): self.area = DockArea() self.setCentralWidget(self.area) self.plotDict = dict() # initialize all the plot windows we want plotNames = self.config.get( 'PlotNames', ['Scan'] ) if len(plotNames)<1: plotNames.append('Scan') for name in plotNames: dock = Dock(name) widget = DateTimePlotWidget(self, name=name) view = widget._graphicsView self.area.addDock(dock, "bottom") dock.addWidget(widget) self.plotDict[name] = {"dock":dock, "widget":widget, "view":view} def setupAsDockWidget(self, widget, name, area=QtCore.Qt.RightDockWidgetArea, stackAbove=None, stackBelow=None ): dock = QtWidgets.QDockWidget(name) dock.setObjectName(name) dock.setWidget( widget ) self.addDockWidget(area, dock ) self.dockWidgetList.append( dock ) if stackAbove is not None: self.tabifyDockWidget( stackAbove, dock ) elif stackBelow is not None: self.tabifyDockWidget( dock, stackBelow ) return dock def onAddPlot(self): name, ok = QtWidgets.QInputDialog.getText(self, 'Plot Name', 'Please enter a plot name: ') if ok: name = str(name) dock = Dock(name) widget = DateTimePlotWidget(self) view = widget._graphicsView self.area.addDock(dock, "bottom") dock.addWidget(widget) self.plotDict[name] = {"dock":dock, "widget":widget, "view":view} self.plotConfigurationChanged.emit( self.plotDict ) def onRemovePlot(self): logger = logging.getLogger(__name__) if len(self.plotDict) > 0: name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to remove: ", list(self.plotDict.keys()), editable=False) if ok: name = str(name) self.plotDict[name]["dock"].close() del self.plotDict[name] self.plotConfigurationChanged.emit( self.plotDict ) else: logger.info("There are no plots which can be removed") def onRenamePlot(self): logger = logging.getLogger(__name__) if len(self.plotDict) > 0: name, ok = QtWidgets.QInputDialog.getItem(self, "Select Plot", "Please select which plot to rename: ", list(self.plotDict.keys()), editable=False) if ok: newName, newOk = QtWidgets.QInputDialog.getText(self, 'New Plot Name', 'Please enter a new plot name: ') if newOk: name = str(name) newName = str(newName) self.plotDict[name]["dock"].label.setText(str(newName)) self.plotDict[newName] = self.plotDict[name] del self.plotDict[name] self.plotConfigurationChanged.emit( self.plotDict ) else: logger.info("There are no plots which can be renamed") def onSave(self): logger = logging.getLogger(__name__) logger.info( "Saving config" ) filename, _ = DataDirectory.DataDirectory().sequencefile("InstrumentLogger-configuration.db") self.saveConfig() self.config.saveConfig(filename) def onClose(self): self.parent.close() def onMessageWrite(self,message,level=logging.DEBUG): if self.consoleEnable and level>= self.loggingLevel: cursor = self.textEditConsole.textCursor() cursor.movePosition(QtGui.QTextCursor.End) if level < logging.ERROR: self.textEditConsole.setTextColor(QtCore.Qt.black) else: self.textEditConsole.setTextColor(QtCore.Qt.red) cursor.insertText(message) self.textEditConsole.setTextCursor(cursor) self.textEditConsole.ensureCursorVisible() def closeEvent(self, e): logger = logging.getLogger(__name__) logger.info( "Close Event" ) logger = logging.getLogger("") logger.debug( "Saving Configuration" ) self.saveConfig() def saveConfig(self): self.config['MainWindow.State'] = self.parent.saveState() for tab in list(self.tabDict.values()): tab.saveConfig() self.config['MainWindow.pos'] = self.pos() self.config['MainWindow.size'] = self.size() self.config['PlotNames'] = list(self.plotDict.keys()) self.config['pyqtgraph-dockareastate'] = self.area.saveState() self.config['Settings.loggingLevel'] = self.loggingLevel self.config['Settings.consoleMaximumLinesNew'] = self.consoleMaximumLines self.config['Settings.consoleEnable'] = self.consoleEnable self.config['autoSaveTraces'] = self.traceui.autoSaveTraces self.ExternalParametersSelectionUi.saveConfig() self.instrumentLoggingHandler.saveConfig() self.instrumentLoggingQueryUi.saveConfig() self.preferencesUi.saveConfig() def onPrint(self, target): printer = QtPrintSupport.QPrinter(mode=QtPrintSupport.QPrinter.ScreenResolution) if self.preferencesUi.preferences().printPreferences.doPrint: dialog = QtPrintSupport.QPrintDialog(printer, self) dialog.setWindowTitle("Print Document") if dialog.exec_() != QtWidgets.QDialog.Accepted: return; printer.setResolution(self.preferencesUi.preferences().printPreferences.printResolution) pdfPrinter = QtPrintSupport.QPrinter() pdfPrinter.setOutputFormat(QtPrintSupport.QPrinter.PdfFormat); pdfPrinter.setOutputFileName(DataDirectory.DataDirectory().sequencefile(target+".pdf")[0]) self.doPrint(target, printer, pdfPrinter, self.preferencesUi.preferences().printPreferences) def doPrint(self, target, printer, pdfPrinter, preferences): widget = self.plotDict[target]['widget'] if preferences.savePdf: with SceneToPrint(widget): painter = QtGui.QPainter(pdfPrinter) widget.render( painter ) del painter # create an exporter instance, as an argument give it # the item you wish to export with SceneToPrint(widget, preferences.gridLinewidth, preferences.curveLinewidth): exporter = ImageExporter(widget._graphicsView.scene()) # set export parameters if needed pageWidth = printer.pageRect().width() pageHeight = printer.pageRect().height() exporter.parameters()['width'] = pageWidth*preferences.printWidth # (note this also affects height parameter) # save to file png = exporter.export(toBytes=True) if preferences.savePng: png.save(DataDirectory.DataDirectory().sequencefile(target+".png")[0]) if preferences.doPrint: painter = QtGui.QPainter( printer ) painter.drawImage(QtCore.QPoint(pageWidth*preferences.printX, pageHeight*preferences.printY), png) def initMenu(self): """Initialize print menu and view menu""" #View menu self.menuView.clear() dockList = self.findChildren(QtWidgets.QDockWidget) for dock in dockList: self.menuView.addAction(dock.toggleViewAction()) # Print menu if self.printMenu is not None: self.printMenu.clear() else: self.printMenu = self.menuFile.addMenu("Print") for plot in list(self.plotDict.keys()): action = self.printMenu.addAction( plot ) action.triggered.connect( partial(self.onPrint, plot ))