Files
superxas_bec/docs/device_v4_migration_plan.md
T
appel_c e42dc75c38
CI for superxas_bec / test (push) Successful in 1m29s
WIP agent step 4: plan device v4 migration
2026-05-28 08:24:04 +02:00

5.0 KiB

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.