def build_context_menu(self, builder): if self.model.context.is_online_master(): # If no new data points are coming in, setting the history size wouldn't do # anything. # TODO: is_online_master() should really be something like # SinglePointModel.ever_updates(). num_history_box = QtWidgets.QSpinBox() num_history_box.setMinimum(1) num_history_box.setMaximum(2**16) num_history_box.setValue(self._history_length) num_history_box.valueChanged.connect(self.set_history_length) container = QtWidgets.QWidget() layout = QtWidgets.QHBoxLayout() container.setLayout(layout) label = QtWidgets.QLabel("N: ") layout.addWidget(label) layout.addWidget(num_history_box) action = builder.append_widget_action() action.setDefaultWidget(container) builder.ensure_separator() super().build_context_menu(builder)
def __init__(self, model: Model): super().__init__() self._alternate_plots = OrderedDict() self.model = model self.layout = QtWidgets.QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) self.widget_stack = QtWidgets.QStackedWidget() self.message_label = QtWidgets.QLabel( "Waiting for channel metadata for scan…") self.widget_stack.addWidget(self.message_label) self.layout.addWidget(self.widget_stack) if isinstance(self.model, SinglePointModel): self.plot = Rolling1DPlotWidget(self.model, self._get_alternate_names) self.model.channel_schemata_changed.connect( self._create_subscan_roots) else: try: self.plot = _make_dimensional_plot(self.model, self._get_alternate_names) except NotImplementedError as err: self._show_error(str(err)) return self.widget_stack.addWidget(self.plot) self._alternate_plots["main plot"] = self.plot self.plot.error.connect(self._show_error) self.plot.ready.connect(lambda: self._show(self.plot)) self.plot.alternate_plot_requested.connect(self._show_alternate_plot)
def __init__(self, roots, context): super().__init__() self.root_widgets = OrderedDict((label, RootWidget(root, context)) for label, root in roots.items()) self.layout = QtWidgets.QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) self.tab_widget = QtWidgets.QTabWidget() for label, widget in self.root_widgets.items(): self.tab_widget.addTab(widget, label) self.layout.addWidget(self.tab_widget)
def _install_context_menu(self, x_schema): entries = [] for d in extract_linked_datasets(x_schema["param"]): action = QtWidgets.QAction("Set '{}' from crosshair".format(d), self) action.triggered.connect( lambda: self._set_dataset_from_crosshair_x(d)) entries.append(action) if entries: separator = QtWidgets.QAction("", self) separator.setSeparator(True) entries.append(separator) self.plotItem.getContextMenus = lambda ev: entries
def main(): args = get_argparser().parse_args() app = QtWidgets.QApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) file = h5py.File(args.path, "r") try: file["datasets"]["ndscan.axes"][()] except KeyError: QtWidgets.QMessageBox.critical( None, "Not an ndscan file", "No ndscan result datasets found in file: '{}'".format(args.path)) sys.exit(1) try: context = Context() context.set_title(os.path.basename(args.path)) # Old ndscan versions had a rid dataset instead of source_id. datasets = file["datasets"] if "ndscan.source_id" in datasets: context.set_source_id(datasets["ndscan.source_id"][()]) else: context.set_source_id("rid_{}".format(datasets["ndscan.rid"][()])) root = HDF5Root(datasets, context) except Exception as e: QtWidgets.QMessageBox.critical( None, "Error parsing ndscan file", "Error parsing datasets in '{}': {}".format(args.path, e)) sys.exit(2) widget = PlotContainerWidget(root.get_model()) widget.show() sys.exit(app.exec_())
def build_context_menu(self, builder): if self.model.context.is_online_master(): x_datasets = extract_linked_datasets(self.x_schema["param"]) y_datasets = extract_linked_datasets(self.y_schema["param"]) for d, axis in chain(zip(x_datasets, repeat("x")), zip(y_datasets, repeat("y"))): action = builder.append_action( "Set '{}' from crosshair".format(d)) action.triggered.connect(lambda *a, axis=axis, d=d: ( self._set_dataset_from_crosshair(d, axis))) if len(x_datasets) == 1 and len(y_datasets) == 1: action = builder.append_action("Set both from crosshair") def set_both(): self._set_dataset_from_crosshair(x_datasets[0], "x") self._set_dataset_from_crosshair(y_datasets[0], "y") action.triggered.connect(set_both) builder.ensure_separator() self.channel_menu_group = QtWidgets.QActionGroup(self) for name in self.data_names: action = builder.append_action(name) action.setCheckable(True) action.setActionGroup(self.channel_menu_group) action.setChecked(name == self.plot.active_channel_name) action.triggered.connect( lambda *a, name=name: self.plot.activate_channel(name)) builder.ensure_separator() super().build_context_menu(builder)
def _install_context_menu(self, data_names): entries = [] x_datasets = extract_linked_datasets(self.x_schema["param"]) y_datasets = extract_linked_datasets(self.y_schema["param"]) for d, axis in chain(zip(x_datasets, repeat("x")), zip(y_datasets, repeat("y"))): action = QtWidgets.QAction("Set '{}' from crosshair".format(d), self) action.triggered.connect( lambda *a, d=d: self._set_dataset_from_crosshair(d, axis)) entries.append(action) if len(x_datasets) == 1 and len(y_datasets) == 1: action = QtWidgets.QAction("Set both from crosshair".format(d), self) def set_both(): self._set_dataset_from_crosshair(x_datasets[0], "x") self._set_dataset_from_crosshair(y_datasets[0], "y") action.triggered.connect(set_both) entries.append(action) def append_separator(): separator = QtWidgets.QAction("", self) separator.setSeparator(True) entries.append(separator) if entries: append_separator() self.channel_menu_group = QtWidgets.QActionGroup(self) first_action = None for name in data_names: action = QtWidgets.QAction(name, self) if not first_action: first_action = action action.setCheckable(True) action.setActionGroup(self.channel_menu_group) action.triggered.connect( lambda *a, name=name: self.plot.activate_channel(name)) entries.append(action) if first_action: first_action.setChecked(True) append_separator() self.plotItem.getContextMenus = lambda ev: entries
def main(): logging.basicConfig(level=logging.INFO) app = QApplication([]) loop = QEventLoop(app) asyncio.set_event_loop(loop) atexit.register(loop.close) win = MainWindow(app, None) container = QtWidgets.QWidget(win) layout = QtWidgets.QGridLayout() container.setLayout(layout) scanner = ScanWidget() scanner.setFocusPolicy(QtCore.Qt.StrongFocus) layout.addWidget(scanner, 0, 0, -1, 1) spinbox = ScientificSpinBox() spinbox.setFocusPolicy(QtCore.Qt.StrongFocus) spinbox.setStyleSheet("QDoubleSpinBox {color:blue}") spinbox.setMinimumSize(110, 0) layout.addWidget(spinbox, 0, 1) scanner.startChanged.connect(spinbox.setValue) spinbox.valueChanged.connect(scanner.setStart) scanner.setStart(-100) spinbox = QtWidgets.QSpinBox() spinbox.setFocusPolicy(QtCore.Qt.StrongFocus) spinbox.setMinimum(1) spinbox.setMaximum((1 << 31) - 1) layout.addWidget(spinbox, 1, 1) scanner.numChanged.connect(spinbox.setValue) spinbox.valueChanged.connect(scanner.setNum) scanner.setNum(11) spinbox = ScientificSpinBox() spinbox.setFocusPolicy(QtCore.Qt.StrongFocus) spinbox.setStyleSheet("QDoubleSpinBox {color:red}") layout.addWidget(spinbox, 2, 1) scanner.stopChanged.connect(spinbox.setValue) spinbox.valueChanged.connect(scanner.setStop) scanner.setStop(200) win.setCentralWidget(container) win.show() loop.run_until_complete(win.exit_request.wait())
def __init__(self, args): super().__init__() self.args = args self.setWindowTitle("ndscan plot") self.resize(600, 600) self.layout = QtWidgets.QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) self.widget_stack = QtWidgets.QStackedWidget() self.message_label = QtWidgets.QLabel( "Waiting for ndscan metadata for rid {}…".format(self.args.rid)) self.widget_stack.addWidget(self.message_label) self.layout.addWidget(self.widget_stack) self.title_set = False self.plot_initialised = False
def __init__(self, root: Root, context: Context): super().__init__() self.root = root self.root.model_changed.connect(self._update_plot) self.context = context self.context.title_changed.connect(self._set_window_title) self.layout = QtWidgets.QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) # TODO: Use context info/… to identify plot to user in message. self.message_label = QtWidgets.QLabel("No data.") self.widget_stack = QtWidgets.QStackedWidget() self.widget_stack.addWidget(self.message_label) self.layout.addWidget(self.widget_stack) self.plot_container = None
def _install_context_menu(self): self.num_history_box = QtWidgets.QSpinBox() self.num_history_box.setMinimum(1) self.num_history_box.setMaximum(2**16) self.num_history_box.setValue(100) self.num_history_box.valueChanged.connect(self.set_history_length) container = QtWidgets.QWidget() layout = QtWidgets.QHBoxLayout() container.setLayout(layout) label = QtWidgets.QLabel("N: ") layout.addWidget(label) layout.addWidget(self.num_history_box) action = QtWidgets.QWidgetAction(self) action.setDefaultWidget(container) separator = QtWidgets.QAction("", self) separator.setSeparator(True) entries = [action, separator] self.plotItem.getContextMenus = lambda ev: entries
def quamash_init(self): app = QtWidgets.QApplication([]) self.loop = QEventLoop(app) asyncio.set_event_loop(self.loop)
def append_widget_action(self) -> QtWidgets.QWidgetAction: action = QtWidgets.QWidgetAction(self._target_menu) self._append(action) return action
def append_action(self, title) -> QtWidgets.QAction: action = QtWidgets.QAction(title, self._target_menu) self._append(action) return action
def append_separator(): separator = QtWidgets.QAction("", self) separator.setSeparator(True) entries.append(separator)
def main(): args = get_argparser().parse_args() app = QtWidgets.QApplication(sys.argv) loop = QEventLoop(app) asyncio.set_event_loop(loop) try: file = h5py.File(args.path, "r") except Exception as e: QtWidgets.QMessageBox.critical(None, "Unable to load file", str(e)) sys.exit(1) try: datasets = file["datasets"] except KeyError: QtWidgets.QMessageBox.critical( None, "Not an ARTIQ results file", "No ARTIQ dataset records found in file: '{}'".format(args.path)) sys.exit(1) prefix = fetch_explicit_prefix(args) if prefix is not None: try: # 'axes' existed since the earliest schema revisions, so we can use it to # detect whether the file/prefix the user specified vaguely looks like it # has been generated by ndscan. datasets[prefix + "axes"][()] except KeyError: QtWidgets.QMessageBox.critical( None, "Not an ndscan file", "Datasets '{}*' in file '{}' do not look like ndscan results.".format( prefix, args.path)) sys.exit(1) prefixes = [prefix] else: prefixes = find_ndscan_roots(datasets) if not prefixes: QtWidgets.QMessageBox.critical( None, "Not an ndscan file", "No ndscan result datasets found in file: '{}'".format(args.path)) sys.exit(1) try: context = Context() context.set_title(os.path.basename(args.path)) # Take source_id from first prefix. This is pretty arbitrary, but for # experiment-generated files, they will all be the same anyway. if (prefixes[0] + "source_id") in datasets: context.set_source_id(datasets[prefixes[0] + "source_id"][()]) else: # Old ndscan versions had a rid dataset instead of source_id. context.set_source_id("rid_{}".format(datasets[prefixes[0] + "rid"][()])) roots = [HDF5Root(datasets, p, context) for p in prefixes] except Exception as e: QtWidgets.QMessageBox.critical( None, "Error parsing ndscan file", "Error parsing datasets in '{}': {}".format(args.path, e)) sys.exit(2) if len(roots) == 1: widget = PlotContainerWidget(roots[0].get_model()) else: label_map = shorten_to_unambiguous_suffixes( prefixes, lambda fqn, n: ".".join(fqn.split(".")[-(n + 1):])) widget = MultiRootWidget( OrderedDict(zip((strip_suffix(label_map[p], ".") for p in prefixes), roots)), context) widget.show() widget.resize(800, 600) sys.exit(app.exec_())