This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
# 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.
|
||||
|
||||
Reference in New Issue
Block a user