130 lines
5.0 KiB
Markdown
130 lines
5.0 KiB
Markdown
# SuperXAS device v4 migration plan
|
|
|
|
## Scope and source mapping
|
|
|
|
| Debye source | SuperXAS target |
|
|
| --- | --- |
|
|
| `debye_bec/debye_bec/devices/utils/utils.py` | `superxas_bec/superxas_bec/devices/utils/utils.py` |
|
|
| `debye_bec/debye_bec/devices/mo1_bragg/mo1_bragg.py` | `superxas_bec/superxas_bec/devices/mo1_bragg/mo1_bragg.py` |
|
|
| `debye_bec/debye_bec/devices/nidaq/nidaq.py` | `superxas_bec/superxas_bec/devices/nidaq/nidaq.py` |
|
|
|
|
The migration should preserve SuperXAS hardware naming, EPICS prefixes, enum
|
|
modules, and beamline-specific details. Only the scan metadata access pattern
|
|
should be changed to match the Debye v4 migration pattern.
|
|
|
|
## Shared helper
|
|
|
|
Add `superxas_bec/superxas_bec/devices/utils/utils.py` with Debye's
|
|
`fetch_scan_info(scan_info)` helper.
|
|
|
|
The helper should:
|
|
|
|
- read `scan_info.msg.info`
|
|
- convert list-valued `positions` back to `numpy.ndarray`
|
|
- validate the message as `bec_server.scan_server.scans.scan_base.ScanInfo`
|
|
- fall back for legacy scan messages by converting old `"fly"` scan type to
|
|
`"hardware_triggered"` and other old scan types to `"software_triggered"`
|
|
|
|
This keeps devices compatible during the migration window where both old and v4
|
|
scan status messages may still appear.
|
|
|
|
## `mo1_bragg` migration
|
|
|
|
Current SuperXAS behavior:
|
|
|
|
- reads the scan name from `self.scan_info.msg.scan_name`
|
|
- populates a local `ScanParameter` pydantic model from
|
|
`self.scan_info.msg.request_inputs["inputs"]` and `["kwargs"]`
|
|
- reads old-style parameters such as `scan_parameter.start`,
|
|
`scan_parameter.stop`, `scan_parameter.scan_time`, and
|
|
`scan_parameter.scan_duration`
|
|
|
|
Target v4 behavior:
|
|
|
|
- import `ScanInfo as ScanServerScanInfo`
|
|
- store `self.scan_parameters: ScanServerScanInfo | None`
|
|
- call `self.scan_parameters = fetch_scan_info(self.scan_info)` at the start of
|
|
`on_stage`
|
|
- validate the scan with `_check_if_scan_name_is_valid(self.scan_parameters)`
|
|
- read start/stop from `self.scan_parameters.positions`
|
|
- read scan arguments from
|
|
`self.scan_parameters.additional_scan_parameters`
|
|
|
|
For the scans migrated in step 2:
|
|
|
|
- `xas_simple_scan`
|
|
- required: `positions`, `scan_time`, `scan_duration`
|
|
- configure simple XAS settings
|
|
- disable trigger settings
|
|
- set scan-control mode to `ScanControlMode.SIMPLE`
|
|
- `xas_advanced_scan`
|
|
- required: `positions`, `scan_time`, `scan_duration`, `p_kink`, `e_kink`
|
|
- configure advanced XAS settings
|
|
- disable trigger settings
|
|
- set scan-control mode to `ScanControlMode.ADVANCED`
|
|
|
|
Keep SuperXAS-specific hardware behavior:
|
|
|
|
- keep the SuperXAS prefix and imports
|
|
- keep `set_trig_settings(...)` matching the current SuperXAS IOC API unless
|
|
XRD scan classes are reintroduced in the scan migration
|
|
- keep `convert_angle_energy(...)` available for the v4 scan's gonio centering
|
|
- consider adding `"convert_angle_energy"` to `USER_ACCESS`, matching Debye,
|
|
because the scan migration now relies on the method being callable through the
|
|
device container/device manager path
|
|
|
|
Remove or stop using `_update_scan_parameter()` and the old `ScanParameter`
|
|
model once all parameter reads come from `self.scan_parameters`.
|
|
|
|
## `nidaq` migration
|
|
|
|
Current SuperXAS behavior:
|
|
|
|
- checks scan validity through `self.scan_info.msg.scan_name`
|
|
- reads continuous scan settings from
|
|
`self.scan_info.msg.scan_parameters["scan_duration"]` and
|
|
`["compression"]`
|
|
- `_progress_update` also reads `self.scan_info.msg.scan_parameters`
|
|
|
|
Target v4 behavior:
|
|
|
|
- import `ScanInfo as ScanServerScanInfo`
|
|
- store `self.scan_parameters: ScanServerScanInfo | None`
|
|
- call `self.scan_parameters = fetch_scan_info(self.scan_info)` at the start of
|
|
`on_stage`
|
|
- change `_check_if_scan_name_is_valid(...)` to accept the normalized
|
|
`scan_parameters`
|
|
- read the scan name from `self.scan_parameters.scan_name`
|
|
- read continuous scan settings from
|
|
`self.scan_parameters.additional_scan_parameters`
|
|
- make `_progress_update` use
|
|
`self.scan_parameters.additional_scan_parameters.get("scan_duration")`
|
|
|
|
The Debye runtime behavior should be mirrored:
|
|
|
|
- invalid scan names return without touching the IOC
|
|
- non-continuous XAS scans stage NIDAQ as triggered, duration `0`,
|
|
compression enabled
|
|
- `nidaq_continuous_scan` stages NIDAQ as continuous and applies
|
|
`scan_duration` plus `compression`
|
|
- non-continuous XAS scans kick off during stage
|
|
- `nidaq_continuous_scan` waits for explicit scan-core kickoff
|
|
- `on_complete` stops the backend only for non-continuous scans
|
|
|
|
## Tests to migrate or add
|
|
|
|
Use Debye's NIDAQ device tests as the starting point and adapt imports to
|
|
SuperXAS:
|
|
|
|
- verify `fetch_scan_info` accepts v4 scan info and legacy fly scan info
|
|
- verify NIDAQ valid/invalid scan name checks
|
|
- verify NIDAQ pre-scan and complete behavior for XAS versus
|
|
`nidaq_continuous_scan`
|
|
- add a focused `mo1_bragg` staging test that feeds v4 scan info and asserts the
|
|
correct settings methods are called for `xas_simple_scan` and
|
|
`xas_advanced_scan`
|
|
|
|
Keep the test blast radius focused on metadata parsing and device decisions.
|
|
The EPICS signal behavior is already covered by existing device-level patterns.
|
|
|