Ejemplo n.º 1
0
def main(argv):
    print(__doc__)

    with gui_qt("Example App"):
        app = ExampleApp()

        # Optional: Receive live streaming data.
        if len(argv) > 1:
            from bluesky_widgets.qt.zmq_dispatcher import RemoteDispatcher
            from bluesky_widgets.utils.streaming import (
                stream_documents_into_runs, )

            address = argv[1]
            dispatcher = RemoteDispatcher(address)
            dispatcher.subscribe(stream_documents_into_runs(
                app.viewer.add_run))
            dispatcher.start()

        # We can access and modify the model as in...
        len(app.searches)
        app.searches[0]
        app.searches.active  # i.e. current tab
        app.searches.active.input.since  # time range
        app.searches.active.input.until
        app.searches.active.results
        app.searches.active.selection_as_catalog
        app.searches.active.selected_uids
Ejemplo n.º 2
0
def listen_for_data(app, address):
    # Optional: Receive live streaming data.
    from bluesky_widgets.jupyter.zmq_dispatcher import RemoteDispatcher
    from bluesky_widgets.utils.streaming import stream_documents_into_runs

    dispatcher = RemoteDispatcher(address)
    dispatcher.subscribe(stream_documents_into_runs(app.model.add_run))
    dispatcher.start()  # launches process and thread
    return dispatcher.stop
Ejemplo n.º 3
0
def stream_to_figures(fig, axes_list, start_at=0):
    fig.patch.set_alpha(0.5)
    axes_list = axes_list.ravel()

    section = np.zeros((8, 8))
    section[:4, :4] = 1
    section[4:, 4:] = 1
    init_data = np.tile(section, (1 + SHAPE[0] // 8, 1 + SHAPE[1] // 8))[
        : SHAPE[0], : SHAPE[1]
    ]

    ims = [ax.imshow(init_data) for ax in axes_list]
    if len(axes_list) > 1:
        sample_text = "S"  # abbreviate for space
    else:
        sample_text = "Sample "
    for j, ax in enumerate(axes_list):
        ax.set_title(f"{sample_text}{j + start_at} N_shots: 0")
        ax.axis("off")
    counts = Counter()

    last_seen = None

    def update_plot(event):
        nonlocal last_seen
        run = event.run
        (sample,) = run.primary.read()["sample_selector"]
        sample = int(sample)
        img = run.primary.read()["detector_image"].mean(axis=0)
        img -= img.min()
        img /= img.max()

        if len(ims) == 1:
            (im,) = ims
            if sample != last_seen:
                counts.clear()
        else:
            im = ims[int(sample) - start_at]

        prev_count = counts[sample]
        old_data = im.get_array()

        new_data = (old_data * prev_count + img) / (prev_count + 1)

        counts[sample] += 1

        im.set_data(new_data)
        im.axes.set_title(f"{sample_text}{sample} N_shots: {counts[sample]}")

        last_seen = sample
        fig.canvas.draw_idle()

    def update_plot_on_stop(run):
        run.events.completed.connect(update_plot)

    return stream_documents_into_runs(update_plot_on_stop)
Ejemplo n.º 4
0
    def __init__(self, *, show=True, title="Demo App"):
        # TODO Where does title thread through?
        super().__init__()
        if SETTINGS.subscribe_to:
            from bluesky_widgets.qt.zmq_dispatcher import RemoteDispatcher
            from bluesky_widgets.utils.streaming import (
                stream_documents_into_runs,
            )

            for address in SETTINGS.subscribe_to:
                dispatcher = RemoteDispatcher(address)
                dispatcher.subscribe(stream_documents_into_runs(self.auto_plot_builder.add_run))
                dispatcher.start()
        widget = QtViewer(self)
        self._window = Window(widget, show=show)
Ejemplo n.º 5
0
import tempfile

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.auto_plot_builders import AutoLines
from bluesky_widgets.headless.figures import HeadlessFigures
from bluesky_widgets.examples.utils.generate_msgpack_data import get_catalog

model = AutoLines(max_runs=3)
view = HeadlessFigures(model.figures)

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)


RE(plan())

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
Ejemplo n.º 7
0
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']}")
Ejemplo n.º 8
0
    def export(*args):
        filenames = view.export_all(directory)
        print("\n".join(f'"{filename}"' for filename in filenames))
        view.close()

    if run_is_live_and_not_completed(run):
        run.events.new_data.connect(export)
    else:
        export()


if __name__ == "__main__":
    bootstrap_servers = "127.0.0.1:9092"
    kafka_deserializer = partial(msgpack.loads, object_hook=mpn.decode)
    topics = ["widgets_test.bluesky.documents"]
    consumer_config = {
        "auto.commit.interval.ms": 100,
        "auto.offset.reset": "latest"
    }

    dispatcher = RemoteDispatcher(
        topics=topics,
        bootstrap_servers=bootstrap_servers,
        group_id="widgets_test",
        consumer_config=consumer_config,
    )

    dispatcher.subscribe(
        stream_documents_into_runs(export_thumbnails_when_complete))
    dispatcher.start()
Ejemplo n.º 9
0
def main():
    # First, some boilerplate to make a super-minimal Qt application that we want
    # to add some bluesky-widgets components into.
    app = QApplication(["Some App"])
    window = QMainWindow()
    central_widget = QWidget(window)
    window.setCentralWidget(central_widget)
    central_widget.setLayout(QVBoxLayout())
    central_widget.layout().addWidget(QLabel("This is part of the 'original' app."))
    window.show()

    # *** INTEGRATION WITH BLUESKY-WIDGETS STARTS HERE. ***

    # Ensure that any background workers started by bluesky-widgets stop
    # gracefully when the application closes.
    from bluesky_widgets.qt.threading import wait_for_workers_to_quit

    app.aboutToQuit.connect(wait_for_workers_to_quit)

    # Model a list of figures.
    # This will generate line plot automatically based on the structure (shape)
    # of the data and its hints. Other models could be used for more explicit
    # control of what gets plotted. See the examples in
    # http://blueskyproject.io/bluesky-widgets/reference.html#plot-builders
    from bluesky_widgets.models.auto_plot_builders import AutoLines

    model = AutoLines(max_runs=3)

    # Feed it data from the RunEngine. In actual practice, the RunEngine should
    # be in a separate process and we should be receiving these documents
    # over a network via publish--subscribe. See
    # bluesky_widgets.examples.advanced.qt_viewer_with_search for an example of
    # that. Here, we keep it simple.
    from bluesky_widgets.utils.streaming import stream_documents_into_runs
    from bluesky import RunEngine

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

    # Add a tabbed pane of figures to the app.
    from bluesky_widgets.qt.figures import QtFigures

    view = QtFigures(model.figures)  # view is a QWidget
    central_widget.layout().addWidget(view)

    # When the model receives data or is otherwise updated, any changes to
    # model.figures will be reflected in changes to the view.

    # Just for this example, generate some data before starting this app.
    # Again, in practice, this should happen in a separate process and send
    # the results over a network.

    from bluesky.plans import scan
    from ophyd.sim import motor, det

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

    RE(plan())

    # *** INTEGRATION WITH BLUESKY-WIDGETS ENDS HERE. ***

    # Run the app.
    app.exec_()
 def __init__(self, callback):
     self.callback = callback
     self._run = None
     #
     self._document_collector = stream_documents_into_runs(self.add_new_run)
Ejemplo n.º 11
0
# TODO This does not seem to have any effect.
# Am I using it wrong, or are ophyd's simulated motors
# not implementing enough of the optional API to engage it?

# Register bluesky IPython magics.
from bluesky.magics import BlueskyMagics

get_ipython().register_magics(BlueskyMagics)

# Set up plots with bluesky_widgets.
from bluesky_widgets.models.auto_plot_builders import AutoLines
from bluesky_widgets.utils.streaming import stream_documents_into_runs
from bluesky_widgets.jupyter.figures import JupyterFigures

auto_plot_model = AutoLines(max_runs=10)
RE.subscribe(stream_documents_into_runs(auto_plot_model.add_run))
auto_plot_view = JupyterFigures(auto_plot_model.figures)

# Use BestEffortCallback just for the table
# TODO: Retire our use of BestEffortCallback, using a table from
# bluesky_widgets once one is available.
from bluesky.callbacks.best_effort import BestEffortCallback
bec = BestEffortCallback()
bec.disable_plots()
RE.subscribe(bec)

# Import matplotlib and put it in interactive mode.
import matplotlib.pyplot as plt

plt.ion()
Ejemplo n.º 12
0
def start_dichro_plot(monitor='Ion Ch 4', detector='Ion Ch 5', fluo=True):
    model = AutoDichroPlot(monitor=monitor, detector=detector, fluo=fluo)
    view = QtFigures(model.figures)
    view.show()
    RE.subscribe(stream_documents_into_runs(model.add_run))
    return model, view