def __init__(self, node: Node = None): super().__init__(node=node) self.fileinput = QtGui.QLineEdit() self.groupinput = QtGui.QLineEdit('data') self.reload = QtGui.QPushButton('Reload') self.optSetters = { 'filepath': self.fileinput.setText, 'groupname': self.groupinput.setText, } self.optGetters = { 'filepath': self.fileinput.text, 'groupname': self.groupinput.text, } flayout = QtGui.QFormLayout() flayout.addRow('File path:', self.fileinput) flayout.addRow('Group:', self.groupinput) vlayout = QtGui.QVBoxLayout() vlayout.addLayout(flayout) vlayout.addWidget(self.reload) self.setLayout(vlayout) self.fileinput.textEdited.connect( lambda x: self.signalOption('filepath') ) self.groupinput.textEdited.connect( lambda x: self.signalOption('groupname') ) self.reload.pressed.connect(self.node.update)
def __init__(self, parent=None): super().__init__(parent) self.spin = QtGui.QSpinBox() layout = QtGui.QFormLayout() layout.addRow('Refresh interval (s)', self.spin) self.setLayout(layout) self.spin.valueChanged.connect(self.spinValueChanged)
def __init__(self, parent=None): super().__init__(parent) self._axes = [] self._widgets = {} self.layout = QtGui.QFormLayout() self.confirm = QtGui.QPushButton('set') self.layout.addRow(self.confirm) self.setLayout(self.layout) self.confirm.clicked.connect(self.signalShape)
def subtractAverage(): x = np.arange(11) - 5. y = np.linspace(0, 10, 51) xx, yy = np.meshgrid(x, y, indexing='ij') zz = np.sin(yy) + xx data = MeshgridDataDict(x=dict(values=xx), y=dict(values=yy), z=dict(values=zz, axes=['x', 'y'])) data.validate() x = np.arange(11) - 5. y = np.linspace(0, 10, 51) xx, yy = np.meshgrid(x, y, indexing='ij') zz = np.sin(yy) + xx data2 = MeshgridDataDict(reps=dict(values=xx), y=dict(values=yy), z=dict(values=zz, axes=['reps', 'y'])) data2.validate() # make app and gui, fc app = QtGui.QApplication([]) win, fc = makeFlowchartWithAutoPlotWindow([('sub', SubtractAverage)]) win.show() # feed in data fc.setInput(dataIn=data) fc.setInput(dataIn=data2) return app.exec_()
def addNodeWidget(self, node: Node, **kwargs): """ Add a node widget as dock. :param node: node for which to add the widget. :keyword arguments: * *visible* (`bool`; default: taken from widget class definition) -- whether the widget is visible from the start * *dockArea* (`QtCore.Qt.DockWidgetArea`; default: taken from class) -- where the dock widget initially sits in the window * *icon* (`QtCore.QIcon`; default: taken from class) -- an icon to use for the toolbar """ if node.useUi and node.uiClass is not None: dockArea = kwargs.get('dockArea', node.ui.preferredDockWidgetArea) visible = kwargs.get('visible', node.uiVisibleByDefault) icon = kwargs.get('icon', node.ui.icon) d = QtGui.QDockWidget(node.name(), self) d.setWidget(node.ui) self.nodeWidgets[node.name()] = d self.addDockWidget(dockArea, d) action = d.toggleViewAction() if icon is not None: action.setIcon(icon) self.nodeToolBar.addAction(action) if not visible: d.close()
def _addAxis(self, idx, name): nameWidget = QtGui.QComboBox() for j, bx in enumerate(self._axes): nameWidget.addItem(bx) nameWidget.setCurrentText(name) dimLenWidget = QtGui.QSpinBox() dimLenWidget.setMinimum(1) dimLenWidget.setMaximum(999999) self._widgets[idx] = { 'name': nameWidget, 'shape': dimLenWidget, } self.layout.insertRow(idx, nameWidget, dimLenWidget) nameWidget.currentTextChanged.connect( lambda x: self._processAxisChange(idx, x))
def emit(self, record: logging.LogRecord) -> None: msg = self.format(record) clr = COLORS.get(record.levelno, QtGui.QColor('black')) self.widget.setTextColor(clr) self.widget.append(msg) self.widget.verticalScrollBar().setValue( self.widget.verticalScrollBar().maximum() )
def addNodeWidget(self, node: Node): """ Add a node widget as dock. :param node: node for which to add the widget. :return: """ if node.useUi and node.uiClass is not None: d = QtGui.QDockWidget(node.name(), self) d.setWidget(node.ui) self.nodeWidgets[node.name()] = d self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, d)
def __init__(self, elements: List[Tuple[str, QtGui.QWidget]], parent: Union[None, QtGui.QWidget] = None): super().__init__(parent) self.elements = {} layout = QtGui.QFormLayout() for lbl, widget in elements: self.elements[lbl] = widget layout.addRow(lbl, widget) self.setLayout(layout)
def setAxes(self, axes): if axes != self._axes: self._axes = axes self._widgets = {} for i in range(self.layout.rowCount() - 1): self.layout.removeRow(0) for i, ax in enumerate(axes): w = QtGui.QSpinBox() w.setMinimum(1) w.setMaximum(999999) self._widgets[ax] = w self.layout.insertRow(i, ax, w)
def main(): app = QtGui.QApplication([]) # flowchart and window nodes = makeNodeList() win, fc = makeFlowchartWithPlotWindow(nodes) win.show() # feed in data data = makeData() fc.setInput(dataIn=data) return app.exec_()
def __init__(self, parent=None): super().__init__(parent) self._emitUpdate = True # make radio buttons and layout ## self.buttons = { GridOption.noGrid: QtGui.QRadioButton('No grid'), GridOption.guessShape: QtGui.QRadioButton('Guess shape'), GridOption.specifyShape: QtGui.QRadioButton('Specify shape'), } btnLayout = QtGui.QVBoxLayout() self.btnGroup = QtGui.QButtonGroup(self) for opt in GridOption: btn = self.buttons[opt] self.btnGroup.addButton(btn, opt.value) btnLayout.addWidget(btn) btnBox = QtGui.QGroupBox('Grid') btnBox.setLayout(btnLayout) # make shape spec widget self.shapeSpec = ShapeSpecificationWidget() shapeLayout = QtGui.QVBoxLayout() shapeLayout.addWidget(self.shapeSpec) shapeBox = QtGui.QGroupBox('Shape') shapeBox.setLayout(shapeLayout) # Widget layout layout = QtGui.QHBoxLayout() layout.addWidget(btnBox) layout.addWidget(shapeBox) layout.addStretch() self.setLayout(layout) # Connect signals/slots # self.btnGroup.buttonToggled.connect(self.gridButtonSelected) self.shapeSpec.confirm.clicked.connect(self.shapeSpecified) # Default settings self.buttons[GridOption.noGrid].setChecked(True) self.enableShapeEdit(False)
def add(parent, name): item = self.find(parent, name) if item is None: item = QtWidgets.QTreeWidgetItem(parent, [name]) if os.path.splitext(name)[-1] in self.fileExtensions: fnt = QtGui.QFont() item.setFont(0, fnt) else: pass if isinstance(parent, DataFileList): parent.addTopLevelItem(item) else: parent.addChild(item) return item
def xySelectionWidget(): def selectionCb(selection): print(selection) app = QtGui.QApplication([]) widget = XYSelectionWidget() widget.rolesChanged.connect(selectionCb) # set up the UI, feed data in data = datadict_to_meshgrid(testdata.three_compatible_3d_sets(5, 5, 5)) dialog = widgetDialog(widget) widget.setData(data) widget.clear() widget.setData(data) return app.exec_()
def xySelection(interactive=False): if not interactive: app = QtGui.QApplication([]) fc = linearFlowchart(('xysel', XYSelector)) selector = fc.nodes()['xysel'] dialog = widgetDialog(selector.ui, 'xysel') data = datadict_to_meshgrid(testdata.three_compatible_3d_sets(4, 4, 4)) fc.setInput(dataIn=data) if not interactive: app.exec_() else: return dialog, fc
def dimReduction(interactive=False): if not interactive: app = QtGui.QApplication([]) fc = linearFlowchart(('reducer', DimensionReducer)) reducer = fc.nodes()['reducer'] dialog = widgetDialog(reducer.ui, 'reducer') data = datadict_to_meshgrid(testdata.three_compatible_3d_sets(2, 2, 2)) fc.setInput(dataIn=data) if not interactive: app.exec_() else: return dialog, fc
def dataSelectionWidget(readonly=False): def selectionCb(selection): print(selection) app = QtGui.QApplication([]) widget = DataSelectionWidget(readonly=readonly) widget.dataSelectionMade.connect(selectionCb) # set up the UI, feed data in data = testdata.three_incompatible_3d_sets(5, 5, 5) dialog = widgetDialog(widget) widget.setData(data) widget.clear() widget.setData(data) return app.exec_()
def __init__(self, parent=None, fc: Flowchart = None, **kw): super().__init__(parent) self.plot = PlotWidgetContainer(parent=self) self.setCentralWidget(self.plot) self.plotWidget: Optional[MPLAutoPlot] = None self.nodeToolBar = QtGui.QToolBar('Node control', self) self.addToolBar(self.nodeToolBar) self.nodeWidgets: Dict[str, QtGui.QDockWidget] = {} if fc is not None: self.addNodeWidgetsFromFlowchart(fc, **kw) self.setDefaultStyle()
def simple_2d_plot(): app = QtGui.QApplication([]) win = PlotWindow() plot = AutoPlot(parent=win) win.plot.setPlotWidget(plot) win.show() # plotting 1d traces if False: logger.info(f"1D trace") t0 = time.perf_counter() nsamples = 30 for i in range(nsamples): data = datadict_to_meshgrid( testdata.get_1d_scalar_cos_data(201, 2) ) win.plot.setData(data) t1 = time.perf_counter() fps = nsamples/(t1-t0) logger.info(f"Performance: {fps} FPS") # plotting images if True: logger.info(f"2D image") t0 = time.perf_counter() nsamples = 30 for i in range(nsamples): data = datadict_to_meshgrid( testdata.get_2d_scalar_cos_data(201, 101, 1) ) win.plot.setData(data) t1 = time.perf_counter() fps = nsamples/(t1-t0) logger.info(f"Performance: {fps} FPS") # plotting 2d scatter if False: logger.info(f"2D scatter") t0 = time.perf_counter() nsamples = 30 for i in range(nsamples): data = testdata.get_2d_scalar_cos_data(21, 21, 1) win.plot.setData(data) t1 = time.perf_counter() fps = nsamples/(t1-t0) logger.info(f"Performance: {fps} FPS") return app.exec_()
def loader_node(interactive=False): def cb(*vals): print(vals) if not interactive: app = QtGui.QApplication([]) fc = linearFlowchart(('loader', dds.DDH5Loader)) loader = fc.nodes()['loader'] dialog = widgetDialog(loader.ui, 'loader') if not interactive: loader.newDataStructure.connect(cb) app.exec_() else: return dialog, fc
def gridOptionWidget(): def cb(val): print(val) app = QtGui.QApplication([]) widget = GridOptionWidget() widget.optionSelected.connect(cb) # set up the UI, feed data in data = datadict_to_meshgrid( testdata.three_compatible_3d_sets(5, 5, 5) ) dialog = widgetDialog(widget) widget.setAxes(data.axes()) widget.setShape(data.shape()) return app.exec_()
def main(pathAndId): app = QtGui.QApplication([]) # flowchart and window fc = linearFlowchart( ('Dataset loader', QCodesDSLoader), ('Data selection', DataSelector), ('Grid', DataGridder), ('Dimension assignment', XYSelector), ('Sine fit', sinefit), ('plot', PlotNode), ) win = QCAutoPlotMainWindow(fc, pathAndId=pathAndId) win.show() return app.exec_()
def gridder(interactive=False): def cb(val): print(val) if not interactive: app = QtGui.QApplication([]) fc = linearFlowchart(('grid', DataGridder)) gridder = fc.nodes()['grid'] dialog = widgetDialog(gridder.ui, 'gridder') data = testdata.three_compatible_3d_sets(2, 2, 2) fc.setInput(dataIn=data) if not interactive: gridder.shapeDetermined.connect(cb) app.exec_() else: return dialog, fc
def test_data_selector(interactive=True): if not interactive: app = QtGui.QApplication([]) fc = linearFlowchart(('selector', DataSelector)) selector = fc.nodes()['selector'] dialog = widgetDialog(selector.ui, 'selector') data = testdata.three_incompatible_3d_sets(2, 2, 2) fc.setInput(dataIn=data) selector.selectedData = ['data'] # for testing purposes, insert differently structured data data2 = testdata.two_compatible_noisy_2d_sets() fc.setInput(dataIn=data2) # ... and go back. fc.setInput(dataIn=data) selector.selectedData = ['data'] if not interactive: app.exec_() else: return dialog, fc
def get_gridIcon() -> QtGui.QIcon: gridIcon = QtGui.QIcon(os.path.join(gfxPath, "grid.svg")) return gridIcon
def run(func, **kw): app = QtGui.QApplication([]) _ = func(**kw) return app.exec_()
def get_xySelectIcon() -> QtGui.QIcon: xySelectIcon = QtGui.QIcon(os.path.join(gfxPath, "xy_select.svg")) return xySelectIcon
If a logger is accessed via loggin.getLogger('plottr.*') the logging widget will capture the log and display it. """ # TODO: unify with the one from instrumentserver. should maybe go into labcore? import sys from typing import Optional, Union from plottr import QtWidgets, QtGui import logging __author__ = 'Wolfgang Pfaff' __license__ = 'MIT' COLORS = { logging.ERROR : QtGui.QColor('red'), logging.WARNING : QtGui.QColor('orange'), logging.INFO : QtGui.QColor('green'), logging.DEBUG : QtGui.QColor('gray'), } LEVEL = logging.INFO class QLogHandler(logging.Handler): def __init__(self, parent: QtWidgets.QWidget): super().__init__() self.widget = QtWidgets.QTextEdit(parent) self.widget.setReadOnly(True) def emit(self, record: logging.LogRecord) -> None:
def get_axesAssignIcon() -> QtGui.QIcon: axesAssignIcon = QtGui.QIcon(os.path.join(gfxPath, "axes_assign.svg")) return axesAssignIcon
def main(f, g): app = QtGui.QApplication([]) fc, win = autoplotDDH5(f, g) return app.exec_()