Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
    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
Beispiel #5
0
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_())
Beispiel #6
0
    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)
Beispiel #7
0
    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
Beispiel #8
0
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())
Beispiel #9
0
    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
Beispiel #10
0
    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
Beispiel #11
0
    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
Beispiel #12
0
 def quamash_init(self):
     app = QtWidgets.QApplication([])
     self.loop = QEventLoop(app)
     asyncio.set_event_loop(self.loop)
Beispiel #13
0
 def append_widget_action(self) -> QtWidgets.QWidgetAction:
     action = QtWidgets.QWidgetAction(self._target_menu)
     self._append(action)
     return action
Beispiel #14
0
 def append_action(self, title) -> QtWidgets.QAction:
     action = QtWidgets.QAction(title, self._target_menu)
     self._append(action)
     return action
Beispiel #15
0
 def append_separator():
     separator = QtWidgets.QAction("", self)
     separator.setSeparator(True)
     entries.append(separator)
Beispiel #16
0
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_())