-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/bec signals #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
2c12e95
feat: improve bec signals and how-tos
wakonig 7bf9725
feat: add what-to-remember section to device session
wakonig da3169c
feat: add "What to remember" sections for device configuration, EPICS…
wakonig ca11172
feat: add "What to remember" sections for pseudo positioners and simu…
wakonig 7242e50
feat: add "What to remember" sections for async and sync file writing…
wakonig File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| related: | ||
| - title: BEC Signals for Custom Devices | ||
| url: learn/devices/bec-signals.md | ||
| - title: File writing | ||
| url: learn/file-writer/introduction.md | ||
| - title: ReadoutPriority in BEC | ||
| url: learn/devices/readout-priority.md | ||
| --- | ||
|
|
||
| # Add a File Event Signal to a Custom Device | ||
|
|
||
| !!! Info "Overview" | ||
| Add a `FileEventSignal` to a custom ophyd device when the real measurement data is written to an external file and BEC must track the output path and completion state. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - You already have a custom device class in Python. | ||
| - Your device writes scan data to a file such as HDF5. | ||
| - Your device knows the final output path before or during acquisition. | ||
| - Your acquisition flow exposes a completion state or status callback. | ||
|
|
||
| !!! learn "[Learn about BEC signal classes](../../learn/devices/bec-signals.md){ data-preview }" | ||
|
|
||
| ## 1. Declare the signal on the device class | ||
|
|
||
| Add `FileEventSignal` as a component on your device class: | ||
|
|
||
| ```python | ||
| from ophyd import Component as Cpt | ||
| from ophyd_devices import FileEventSignal | ||
| from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase | ||
|
|
||
|
|
||
| class MyDetector(PSIDeviceBase): | ||
| file_event = Cpt(FileEventSignal, name="file_event") | ||
| ``` | ||
|
|
||
| ## 2. Emit the initial file event before acquisition starts | ||
|
|
||
| As soon as the final output path is known, publish an initial file event with `done=False`. | ||
|
|
||
| This is the same pattern used in `csaxs_bec/devices/jungfraujoch/eiger.py`: | ||
|
|
||
| ```python | ||
| self.file_event.put( | ||
| file_path=self._full_path, | ||
| done=False, | ||
| successful=False, | ||
| hinted_h5_entries={"data": "entry/data/data"}, | ||
| ) | ||
| ``` | ||
|
|
||
| In many devices this is a good fit for `on_stage()`. | ||
|
|
||
| ## 3. Emit the final file event when acquisition completes | ||
|
|
||
| When the asynchronous acquisition finishes, publish a second file event with the resolved completion status. | ||
|
|
||
| ```python | ||
| def _file_event_callback(self, status: DeviceStatus) -> None: | ||
| self.file_event.put( | ||
| file_path=self._full_path, | ||
| done=status.done, | ||
| successful=status.success, | ||
| hinted_h5_entries={"data": "entry/data/data"}, | ||
| ) | ||
| ``` | ||
|
|
||
| Attach this callback to the status object returned by your asynchronous acquisition or completion logic. | ||
|
|
||
| ## 4. Provide HDF5 dataset hints when applicable | ||
|
|
||
| For HDF5-based detectors, set `hinted_h5_entries` so downstream BEC components know where the primary data lives inside the file. | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| hinted_h5_entries={"data": "entry/data/data"} | ||
| ``` | ||
|
|
||
| This is especially important for downstream file linking and data discovery. | ||
|
|
||
| ## 5. Verify the file event flow | ||
|
|
||
| Run a short acquisition and confirm that: | ||
|
|
||
| - the initial file event is emitted with the expected `file_path` | ||
| - the final file event is emitted after completion | ||
| - `successful` reflects the actual acquisition outcome | ||
| - the path points to the final file, not a temporary staging location | ||
|
|
||
| If your file format or downstream consumer needs extra context, include fields such as `file_type` or `metadata`. | ||
|
|
||
| ## 6. Use the file event in BEC | ||
| With the file event signal in place, BEC can now track the produced file and its completion state alongside the rest of the acquisition. For more information on how to use files in BEC and how to link them, see the [File Writer documentation](../../learn/file-writer/introduction.md). | ||
|
|
||
|
|
||
| !!! success "Congratulations!" | ||
| You have successfully added a `FileEventSignal` to a custom device. BEC can now track the produced file and its completion state alongside the rest of the acquisition. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| related: | ||
| - title: BEC Signals for Custom Devices | ||
| url: learn/devices/bec-signals.md | ||
| - title: Introduction to ophyd | ||
| url: learn/devices/introduction-to-ophyd.md | ||
| - title: ReadoutPriority in BEC | ||
| url: learn/devices/readout-priority.md | ||
| --- | ||
|
|
||
| # Add a Preview Signal to a Custom Device | ||
|
wakonig marked this conversation as resolved.
|
||
|
|
||
| !!! Info "Overview" | ||
| Add a `PreviewSignal` to a custom ophyd device when you want BEC to forward live 1D or 2D preview data such as images, spectra, or monitor streams. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - You already have a custom device class in Python. | ||
| - Your device receives preview-like data from a callback, background thread, stream, or external client. | ||
| - You know whether the preview data is 1D or 2D. | ||
|
|
||
| !!! learn "[Learn about BEC signal classes](../../learn/devices/bec-signals.md){ data-preview }" | ||
|
|
||
| ## 1. Declare the signal on the device class | ||
|
|
||
| Add `PreviewSignal` as a component on your device class. | ||
|
|
||
| Use `ndim=2` for images: | ||
|
|
||
| ```python | ||
| from ophyd import Component as Cpt | ||
| from ophyd_devices import PreviewSignal | ||
| from ophyd_devices.interfaces.base_classes.psi_device_base import PSIDeviceBase | ||
|
|
||
|
|
||
| class MyDetector(PSIDeviceBase): | ||
| preview_image = Cpt(PreviewSignal, name="preview_image", ndim=2) | ||
| ``` | ||
|
|
||
| Use `ndim=1` instead for line-like previews such as spectra. | ||
|
|
||
| ## 2. Connect it to your preview callback | ||
|
|
||
| When your device receives new preview data, extract the payload first and then publish it with `put(...)`. | ||
|
|
||
| `PreviewSignal` accepts preview data in multiple forms: | ||
|
|
||
| - a Python `list` | ||
| - a NumPy array | ||
| - a fully constructed `DevicePreviewMessage` | ||
|
|
||
|
|
||
| ```python | ||
| def _preview_callback(self, message: dict) -> None: | ||
| if message.get("type", "") != "image": | ||
| return | ||
|
|
||
| data = message.get("data", {}).get("default") | ||
| if data is None: | ||
| return | ||
|
|
||
| self.preview_image.put(data) | ||
| ``` | ||
|
|
||
| You first receive or assemble the preview payload in your callback or stream handler, and only then set it on the signal with `put(...)`. | ||
|
|
||
| If you pass a list or NumPy array, `PreviewSignal` wraps it into the BEC preview message type for you. If you already have a `DevicePreviewMessage`, you can pass that directly. | ||
|
|
||
| !!! warning "Stay aware of the data rate" | ||
| When connecting a `PreviewSignal`, make sure that the incoming preview data rate is not too high. The purpose of a preview is to provide a lightweight stream that can be forwarded to GUIs and clients without overwhelming the network or BEC. If your preview data arrives at a very high rate, consider adding throttling or decimation logic in your callback before sending it to the signal. | ||
|
|
||
| ## 3. Adjust orientation if needed | ||
|
|
||
| If your upstream image arrives in a different orientation than you want to show in BEC, configure the signal declaration with `transpose` or `num_rotation_90`. | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| preview_image = Cpt( | ||
| PreviewSignal, | ||
| name="preview_image", | ||
| ndim=2, | ||
| transpose=True, | ||
| num_rotation_90=1, | ||
| ) | ||
| ``` | ||
|
|
||
| ## 4. Verify the preview in BEC | ||
|
|
||
| Start the device, trigger the upstream preview source, and confirm that the preview appears in the relevant BEC client or GUI. | ||
|
|
||
| If nothing appears: | ||
|
|
||
| - verify that your callback is being called | ||
| - verify that `data` is not `None` | ||
| - verify that `ndim` matches the actual payload shape | ||
| - verify that the device is configured with a suitable `readoutPriority` | ||
|
|
||
| !!! success "Congratulations!" | ||
| You have successfully added a `PreviewSignal` to a custom device. BEC can now forward your live preview stream independently of the final stored data. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| related: | ||
| - title: BEC Signals for Custom Devices | ||
| url: learn/devices/bec-signals.md | ||
| - title: ReadoutPriority in BEC | ||
| url: learn/devices/readout-priority.md | ||
| - title: Introduction to ophyd | ||
| url: learn/devices/introduction-to-ophyd.md | ||
| --- | ||
|
|
||
| # Add a Progress Signal to a Custom Device | ||
|
|
||
| !!! Info "Overview" | ||
| Add a `ProgressSignal` to a custom ophyd device when you want BEC to track scan progress from that device, for example while data is being acquired or processed asynchronously. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - You already have a custom device class in Python. | ||
| - Your device has a natural progress measure such as completed triggers, completed frames, or processed points. | ||
| - You know the current value and the expected maximum value during the operation. | ||
|
|
||
| !!! learn "[Learn about BEC signal classes](../../learn/devices/bec-signals.md){ data-preview }" | ||
|
|
||
| ## 1. Declare the signal on the device class | ||
|
|
||
| Add `ProgressSignal` as a component on your device class: | ||
|
|
||
| ```python | ||
| from ophyd import Component as Cpt, Device | ||
| from ophyd_devices import ProgressSignal | ||
|
|
||
|
|
||
| class MyDetector(Device): | ||
| progress = Cpt(ProgressSignal, name="progress") | ||
| ``` | ||
|
|
||
| This creates one signal that emits BEC progress messages. | ||
|
|
||
| ## 2. Decide what progress means for the device | ||
|
|
||
| Choose one quantity that moves toward completion in a clear way. | ||
|
|
||
| Typical examples are: | ||
|
|
||
| - completed frames out of total frames | ||
| - completed scan points out of total points | ||
| - processed events out of total events | ||
|
|
||
| The most common pattern is to send: | ||
|
|
||
| - the current value | ||
| - the maximum value | ||
| - whether the operation is done | ||
|
|
||
| ## 3. Update the signal during runtime | ||
|
|
||
| When the device makes progress, send a progress update with `put(...)`. | ||
|
|
||
| Example: | ||
|
|
||
| ```python | ||
| self.progress.put(value=25, max_value=100, done=False) | ||
| ``` | ||
|
|
||
| When the operation is finished: | ||
|
|
||
| ```python | ||
| self.progress.put(value=100, max_value=100, done=True) | ||
| ``` | ||
|
|
||
| ## 4. Connect it to your callback or worker loop | ||
|
|
||
| `ProgressSignal` is usually updated from a callback, subscription, worker thread, or polling loop. | ||
|
|
||
| Typical pattern: | ||
|
|
||
| ```python | ||
| def _update_progress(self, completed, total): | ||
| self.progress.put( | ||
| value=completed, | ||
| max_value=total, | ||
| done=completed >= total, | ||
| ) | ||
| ``` | ||
|
|
||
| This keeps the progress signal close to the logic that already knows how much work has been completed. | ||
|
|
||
| ## 5. Verify the progress updates | ||
|
|
||
| Run a short acquisition and confirm that: | ||
|
|
||
| - the device sends progress updates while work is ongoing | ||
| - `value` increases in the expected direction | ||
| - `max_value` is stable and meaningful | ||
| - `done` becomes `true` when the operation finishes | ||
|
|
||
| If progress does not appear in BEC, first check whether the callback or worker loop that computes progress is actually running. | ||
|
|
||
| !!! success "Congratulations!" | ||
| You have successfully added a `ProgressSignal` to a custom device. BEC can now track the device's runtime progress during the scan. |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.