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)