Beispiel #1
0
    def _on_new_button_clicked(self):
        axes = Axes()
        figure = Figure((axes, ), title="")
        line = Lines(x=self.x_selector.currentText(),
                     ys=[self.y_selector.currentText()],
                     axes=axes,
                     max_runs=3)

        if self.model.search.active_run:
            line.add_run(self.model.search.active_run)

        self.model.auto_plot_builder.plot_builders.append(line)
        self.model.auto_plot_builder.figures.append(figure)
    def handle_new_stream(self, run, stream_name):
        if stream_name != "primary":
            # Nothing to do for this stream.
            return

        # Look for the scan_type='dichro' hint
        scan_type = run.metadata["start"]["hints"].get('scan_type', None)
        if scan_type != 'dichro':
            return

        # Detect x variable from hints in metadata.
        first_scan_dimension = run.metadata["start"]["hints"]["dimensions"][0]
        scanning_fields, _ = first_scan_dimension
        x = scanning_fields[0]

        # Collect monitor and detector
        if "monitor" in run.metadata["start"]["hints"].keys():
            self._monitor = run.metadata["start"]["hints"]["monitor"]
        # TODO: This will only use the first detector, but maybe could
        # expand to all detectors.
        if "detectors" in run.metadata["start"]["hints"].keys():
            self._detector = run.metadata["start"]["hints"]["detectors"][0]

        # If we already have a figure for this x, reuse it (over-plot).
        try:
            (xanes_lines, xmcd_lines) = self._x_to_lines[x]
        except KeyError:
            # We don't have a figure for this x. Make one.
            xanes_axes = Axes(x_label=x, title="XANES")
            xmcd_axes = Axes(x_label=x, title="XMCD")
            figure = Figure((xanes_axes, xmcd_axes), title="XANES and XMCD")
            # Set up objects that will select the approriate data and do the
            # desired transformation for plotting.
            xanes_lines = Lines(
                x=lambda primary: downsampled(primary[x]),
                ys=[lambda primary: xanes(primary[self._monitor],
                                          primary[self._detector],
                                          self.fluo)],
                axes=xanes_axes,
            )
            xmcd_lines = Lines(
                x=lambda primary: downsampled(primary[x]),
                ys=[lambda primary: xmcd(primary[self._monitor],
                                         primary[self._detector],
                                         self.fluo)],
                axes=xmcd_axes,
            )
            self._x_to_lines[x] = (xanes_lines, xmcd_lines)
            # Keep track of these plot builders to enable *removing* runs from
            # them.
            self.plot_builders.append(xanes_lines)
            self.plot_builders.append(xmcd_lines)
            # Appending this figures list will trigger to view to show our new
            # figure.
            self.figures.append(figure)
        # Add this Run to the figure.
        xanes_lines.add_run(run)
        xmcd_lines.add_run(run)
    def __init__(self):
        super(Base, self).__init__() # Call the inherited classes __init__ method
        self.setupUi(self)

        self.MotorSelector1.addItem("Pinhole X")
        self.MotorSelector1.addItem("Pinhole Y")
        self.MotorSelector1.addItem("Pinhole Z")
        ###Set initial scan range values
        self.StartInput1.setText('0')
        self.StopInput1.setText('10')
        self.StepsInput1.setText('11')

        self.DetectorSelector1.addItem("Diode")

        self.model = Lines(x='motor', ys=['det'], max_runs=3)
        self.view = QtFigure(self.model.figure)

        self.dataVizWidget.setLayout(QtWidgets.QVBoxLayout())
        self.dataVizWidget.layout().addWidget(self.view)
def test_publisher_and_qt_remote_dispatcher(
    kafka_bootstrap_servers, temporary_topics, publisher_factory, qapp, hw
):
    """Test publishing and dispatching bluesky documents in Kafka messages.
    Messages will be "dispatched" by a `bluesky_kafka.RemoteDispatcher`.
    Parameters
    ----------
    kafka_bootstrap_servers: str (pytest fixture)
        comma-delimited string of Kafka broker host:port, for example "localhost:9092"
    temporary_topics: context manager (pytest fixture)
        creates and cleans up temporary Kafka topics for testing
    publisher_factory: pytest fixture
        fixture-as-a-factory for creating Publishers
    qapp: pytest-qt fixture
        needed to force processing of Qt events
    hw: pytest fixture
        ophyd simulated hardware objects
    """

    with temporary_topics(topics=["test.qt.remote.dispatcher"]) as (topic,):

        bluesky_publisher = publisher_factory(
            topic=topic,
            key=f"{topic}.key",
            flush_on_stop_doc=True,
        )

        # trying to test _waiting_for_start
        bluesky_publisher("descriptor", {})
        bluesky_publisher("event", {})
        # bluesky_publisher("stop", {})

        published_bluesky_documents = []

        # this function will store all documents
        # published by the RunEngine in a list
        def store_published_document(name, document):
            published_bluesky_documents.append((name, document))

        RE = RunEngine()
        RE.subscribe(bluesky_publisher)
        RE.subscribe(store_published_document)

        RE(count([hw.det]))

        # it is assumed that RE(count()) will produce four
        # documents: start, descriptor, event, stop
        assert len(published_bluesky_documents) == 4

        lines_model = Lines(x="time", ys=["det"])
        assert len(lines_model.runs) == 0

        qt_remote_dispatcher = QtRemoteDispatcher(
            topics=[topic],
            bootstrap_servers=kafka_bootstrap_servers,
            group_id=f"{topic}.consumer.group",
            consumer_config={
                # this consumer is intended to read messages that
                # were published before it starts, so it is necessary
                # to specify "earliest" here
                "auto.offset.reset": "earliest",
            },
            polling_duration=1.0,
        )

        qt_remote_dispatcher.subscribe(stream_documents_into_runs(lines_model.add_run))

        dispatched_bluesky_documents = []

        # the QtRemoteDispatcher will use this function
        # to build a list of documents delivered by Kafka
        def store_dispatched_document(name, document):
            test_logger.debug("store_dispatched_document name='%s'", name)
            dispatched_bluesky_documents.append((name, document))

        qt_remote_dispatcher.subscribe(store_dispatched_document)

        # this function will be given to QtRemoteDispatcher.start()
        # it returns False to end the polling loop
        # as soon as it sees one stop document
        def until_first_stop_document():
            dispatched_bluesky_document_names = [
                name for name, _ in dispatched_bluesky_documents
            ]
            test_logger.debug(
                "until_first_stop_document %s", dispatched_bluesky_document_names
            )
            if "stop" in dispatched_bluesky_document_names:
                return False
            else:
                return True

        # start() will return when 'until_first_stop_document' returns False
        qt_remote_dispatcher.start(
            continue_polling=until_first_stop_document,
        )

        while len(dispatched_bluesky_documents) < 3:
            # waiting for all Kafka messages to land
            test_logger.debug("processing Qt Events")
            qapp.processEvents()

            time.sleep(1.0)
            test_logger.debug(
                "waiting for all Kafka messages, %d so far",
                len(dispatched_bluesky_documents),
            )

        assert len(published_bluesky_documents) == len(dispatched_bluesky_documents)

        assert len(lines_model.runs) == 1
def main():
    with gui_qt("Example App"):
        worker_address, message_bus_address = sys.argv[1:]
        dispatcher = RemoteDispatcher(message_bus_address)
        client = ZMQCommSendThreads(zmq_server_address=worker_address)

        # NOTE: this example starts only if RE Manager is idle and the queue is cleared.
        #   Those are optional steps that ensure that the code in this example is executed correctly.

        # Check if RE Worker environment already exists and RE manager is idle.
        status = client.send_message(method="status")
        if status["manager_state"] != "idle":
            raise RuntimeError(
                f"RE Manager state must be 'idle': current state: {status['manager_state']}"
            )

        # Clear the queue.
        response = client.send_message(method="queue_clear")
        if not response["success"]:
            raise RuntimeError(
                f"Failed to clear the plan queue: {response['msg']}")

        # Open the new environment only if it does not exist.
        if not status["worker_environment_exists"]:
            # Initiate opening of RE Worker environment
            response = client.send_message(method="environment_open")
            if not response["success"]:
                raise RuntimeError(
                    f"Failed to open RE Worker environment: {response['msg']}")

            # Wait for the environment to be created.
            t_timeout = 10
            t_stop = time.time() + t_timeout
            while True:
                status2 = client.send_message(method="status")
                if (status2["worker_environment_exists"]
                        and status2["manager_state"] == "idle"):
                    break
                if time.time() > t_stop:
                    raise RuntimeError(
                        "Failed to start RE Worker: timeout occurred")
                time.sleep(0.5)

        # Add plan to queue
        response = client.send_message(
            method="queue_item_add",
            params={
                "plan": {
                    "name": "scan",
                    "args": [["det"], "motor", -5, 5, 11]
                },
                "user": "",
                "user_group": "admin",
            },
        )
        if not response["success"]:
            raise RuntimeError(
                f"Failed to add plan to the queue: {response['msg']}")

        model = Lines("motor", ["det"], max_runs=3)
        dispatcher.subscribe(stream_documents_into_runs(model.add_run))
        view = QtFigure(model.figure)
        view.show()
        dispatcher.start()

        response = client.send_message(method="queue_start")
        if not response["success"]:
            raise RuntimeError(f"Failed to start the queue: {response['msg']}")
Use within IPython like

ipython --gui=qt

In [1]: %run -m bluesky_widgets.examples.ipy_qt_figure
"""
from bluesky import RunEngine
from bluesky.plans import scan
from ophyd.sim import motor, det

from bluesky_widgets.utils.streaming import stream_documents_into_runs
from bluesky_widgets.models.plot_builders import Lines
from bluesky_widgets.qt.figures import QtFigure
from bluesky_widgets.examples.utils.generate_msgpack_data import get_catalog

model = Lines("motor", ["det"], max_runs=3)
view = QtFigure(model.figure)
view.show()

RE = RunEngine()
RE.subscribe(stream_documents_into_runs(model.add_run))

catalog = get_catalog()
scans = catalog.search({"plan_name": "scan"})
model.add_run(scans[-1], pinned=True)


def plan():
    for i in range(1, 5):
        yield from scan([det], motor, -1, 1, 1 + 2 * i)