0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 11:41:49 +02:00

docs(dispatcher): docs added

This commit is contained in:
2024-08-21 23:10:57 +02:00
parent 7b5b7a8cbb
commit dd7c71bb1e
3 changed files with 166 additions and 1 deletions

View File

@ -125,7 +125,7 @@ class BECDispatcher:
topics: Union[EndpointInfo, str, list[Union[EndpointInfo, str]]], topics: Union[EndpointInfo, str, list[Union[EndpointInfo, str]]],
**kwargs, **kwargs,
) -> None: ) -> None:
"""Connect widget's pyqt slot, so that it is called on new pub/sub topic message. """Connect widget's qt slot, so that it is called on new pub/sub topic message.
Args: Args:
slot (Callable): A slot method/function that accepts two inputs: content and metadata of slot (Callable): A slot method/function that accepts two inputs: content and metadata of
@ -138,6 +138,13 @@ class BECDispatcher:
self._slots[slot].update(set(topics_str)) self._slots[slot].update(set(topics_str))
def disconnect_slot(self, slot: Callable, topics: Union[str, list]): def disconnect_slot(self, slot: Callable, topics: Union[str, list]):
"""
Disconnect a slot from a topic.
Args:
slot(Callable): The slot to disconnect
topics(Union[str, list]): The topic(s) to disconnect from
"""
# find the right slot to disconnect from ; # find the right slot to disconnect from ;
# slot callbacks are wrapped in QtThreadSafeCallback objects, # slot callbacks are wrapped in QtThreadSafeCallback objects,
# but the slot we receive here is the original callable # but the slot we receive here is the original callable
@ -153,6 +160,12 @@ class BECDispatcher:
del self._slots[connected_slot] del self._slots[connected_slot]
def disconnect_topics(self, topics: Union[str, list]): def disconnect_topics(self, topics: Union[str, list]):
"""
Disconnect all slots from a topic.
Args:
topics(Union[str, list]): The topic(s) to disconnect from
"""
self.client.connector.unregister(topics) self.client.connector.unregister(topics)
topics_str, _ = self.client.connector._convert_endpointinfo(topics) topics_str, _ = self.client.connector._convert_endpointinfo(topics)
for slot in list(self._slots.keys()): for slot in list(self._slots.keys()):
@ -162,4 +175,11 @@ class BECDispatcher:
del self._slots[slot] del self._slots[slot]
def disconnect_all(self, *args, **kwargs): def disconnect_all(self, *args, **kwargs):
"""
Disconnect all slots from all topics.
Args:
*args: Arbitrary positional arguments
**kwargs: Arbitrary keyword arguments
"""
self.disconnect_topics(self.client.connector._topics_cb) self.disconnect_topics(self.client.connector._topics_cb)

View File

@ -0,0 +1,143 @@
(developer.bec_dispatcher)=
# BECDispatcher
## Overview
The [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
is a powerful tool that
simplifies the process of connecting Qt slots to message updates from the BEC server. It enables real-time communication
between your widget and the BEC server by listening to specific message channels and triggering callbacks when new data
is received.
This tool is especially useful for creating widgets that need to respond to dynamic data, such as device readbacks or
scan updates. By
using [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher),
you
can create callback functions that react to incoming messages and update your widget's state or perform other tasks
based on the data received.
## How It Works
When you create a widget that needs to respond to updates from the BEC server, you can use
the [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
to
connect specific Qt slots (callback functions) to message endpoints. These endpoints are defined within the BEC system
and represent specific channels of information (
e.g., [`device readback`](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec_lib.endpoints.MessageEndpoints.device_readback),
[`scan_segment`](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec_lib.endpoints.MessageEndpoints.scan_segment),
etc.).
### Step-by-Step Guide
1. **Create a Callback Function**: Define a function within your widget that will handle the data received from the BEC
server. This function should usually accept two parameters: `msg_content` (the message content) and `metadata` (
additional
information about the message).
```python
# Example for a callback function that updates a widget display based on motor readback data
from qtpy.QtCore import Slot
@Slot(dict, dict)
def on_device_readback(self, msg_content, metadata):
# Process the incoming data
new_value = msg_content["signals"]['motor_x']["value"]
# Update the widget's display or perform another action
self.update_display(new_value)
```
2. **Connect the Slot to an Endpoint**: Use
the [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
to connect your callback function to a specific
endpoint. The endpoint represents the type of data or message you're interested in.
```python
from bec_lib.endpoints import MessageEndpoints
self.bec_dispatcher.connect_slot(self.on_device_readback, MessageEndpoints.device_readback("motor_x"))
```
3. **Handle Incoming Data**: Your callback function will be triggered automatically whenever a new message is received
on the connected endpoint. Use the data in `msg_content` to update your widget or perform other actions.
4. **Clean Up Connections**: If your widget is being destroyed or you no longer need to listen for updates, make sure to
disconnect your slots from
the [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
to avoid memory or thread leaks.
```python
self.bec_dispatcher.disconnect_slot(self.on_device_readback, MessageEndpoints.device_readback("motor_x"))
```
### Example: Motor Map Widget
The [`BECMotorMap`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.widgets.figure.plots.motor_map.motor_map.BECMotorMap.html#bec-widgets-widgets-figure-plots-motor-map-motor-map-becmotormap)
widget is a great example of
how [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
can be used to handle real-time data updates. This
widget listens for updates on specific motor positions and dynamically updates the motor map display.
Here's a breakdown of
how [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
is used in
the [`BECMotorMap`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.widgets.figure.plots.motor_map.motor_map.BECMotorMap.html#bec-widgets-widgets-figure-plots-motor-map-motor-map-becmotormap)
widget:
1. **Connecting to Motor Readbacks**:
The widget connects to
the [`device readback`](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec_lib.endpoints.MessageEndpoints.device_readback)
endpoints using
the [`connect_slot`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher.connect_slot)
method
of [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher).
This allows
the widget to receive real-time updates about the motor positions.
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
:language: python
:pyobject: BECMotorMap._connect_motor_to_slots
:dedent: 4
```
2. **Handling Readback Data**:
The `on_device_readback` slot is called whenever new data is received from the motor readback. This slot processes
the data and updates the motor map plot accordingly.
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
:language: python
:pyobject: BECMotorMap.on_device_readback
:dedent: 4
```
3. **Updating the Plot**:
The motor map plot is updated in response to the new data, providing a real-time visualization of the motor's
position.
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
:language: python
:pyobject: BECMotorMap._update_plot
:dedent: 4
```
4. **Disconnecting When No Longer Needed**:
The widget ensures that connections are properly cleaned up when no longer needed.
```{literalinclude} ../../../bec_widgets/widgets/figure/plots/motor_map/motor_map.py
:language: python
:pyobject: BECMotorMap._update_plot
:dedent: 4
```
## Conclusion
The [`BECDispatcher`](https://bec.readthedocs.io/projects/bec-widgets/en/latest/api_reference/_autosummary/bec_widgets.utils.bec_dispatcher.BECDispatcher.html#bec_widgets.utils.bec_dispatcher.BECDispatcher)
is a key tool for developing interactive and responsive widgets within the BEC framework. By
leveraging this tool, you can create widgets that automatically respond to real-time data updates from the BEC server,
enhancing the interactivity and functionality of your user interface.
In next tutorials we will cover how to create a custom widget using the BECDispatcher and BECWidget base class.
```{note}
For more details on specific messages and endpoints, please refer to the [Message Endpoints Documentation](https://beamline-experiment-control.readthedocs.io/en/latest/api_reference/_autosummary/bec_lib.endpoints.MessageEndpoints.html#bec-lib-endpoints-messageendpoints).
```

View File

@ -8,4 +8,6 @@ maxdepth: 2
hidden: false hidden: false
--- ---
bec_dispatcher
``` ```