| related |
|
|---|
self.components contains reusable scan logic for common scan patterns.
Where actions gives a scan high-level operations such as staging, reading, or publishing progress,
components builds on top of those operations to make frequently used scan patterns easier to
reuse.
Many scans need the same kinds of logic:
- loop over prepared positions
- move devices and wait for motion to finish
- trigger and read at each point
- capture starting positions for relative scans
- check limits before motion begins
Without shared components, each scan would need to reimplement that behavior for itself.
components exists so scans can reuse those patterns directly and stay focused on what is actually
scan-specific.
The difference is mostly one of level.
actionsprovides scan-facing operations such asstage_all_devices(),read_baseline_devices(), orset(...)componentscombines those operations into reusable scan patterns such as step scans, trigger-and-read sequences, or move-and-wait flows
That is why components are best understood as reusable building blocks on top of actions.
A concrete scan will often use both:
actionsfor lifecycle work and reportingcomponentsfor the repeated motion and acquisition pattern insideprepare_scanorscan_core
Some of the most commonly used helpers are listed below.
| Helper | Role | Typical hook |
|---|---|---|
step_scan(...) |
Runs the standard repeated move/trigger/read pattern for prepared point lists. | scan_core |
step_scan_at_each_point(...) |
Handles the usual per-point logic used inside a step scan. | at_each_point |
trigger_and_read() |
Runs the common trigger/read sequence without rewriting the device coordination each time. | scan_core |
move_and_wait(...) |
Moves devices and waits for motion to complete before continuing. | prepare_scan or post_scan |
get_start_positions(...) |
Captures the starting device positions, for example for relative scans. | prepare_scan |
check_limits(...) |
Checks planned motion against device limits before the scan starts moving hardware. | prepare_scan |
optimize_trajectory(...) |
Reorders prepared positions to reduce unnecessary motion for scans that benefit from path optimization. | prepare_scan |
The important point is not to memorize every helper name. The important point is that common scan behavior is reused instead of being rewritten in every scan class.
In a step scan, the scan-specific code often looks something like this:
- prepare the positions
- check limits
- update
scan_info - let
components.step_scan(...)handle the repeated move/trigger/read sequence
That is a cleaner pattern than manually open-coding every move, wait, trigger, and read inside the scan class.
This is also why components help readability: once you know the shared helpers, you can see more quickly which parts of a scan are generic and which parts are genuinely specific to that scan.
The same framework supports both software-triggered and hardware-triggered scans.
Scans such as acquire, time_scan, line_scan, and grid_scan usually follow a simple pattern:
- move to the next position if needed
- wait for motion to finish
- apply settling time
- trigger devices
- read monitored devices
In many cases this logic is handled through components.step_scan(...) and
components.trigger_and_read().
Scans such as cont_line_fly_scan or monitor_scan use the same lifecycle, but their
scan_core hook looks different:
- the motor may move continuously between only a start and stop point
- per-point work may be driven by readback updates or by repeated trigger/read cycles while motion is still active
- progress is often reported through readback instructions rather than a fixed point table
So the framework stays the same, but the reused execution pattern changes to suit the scan style.
After components, continue with position generators.
That page covers the reusable helpers used to build point lists and trajectories before the scan execution pattern begins.
!!! info "What to remember"
- components contains reusable scan patterns built on top of actions.
- Components help scans reuse common motion and acquisition logic more elegantly.
- Components are most useful when a scan needs a familiar execution pattern without reimplementing it from scratch.