Skip to content

Implement EPICS-backed Polynomial ID Device for I06#2016

Open
Relm-Arrowny wants to merge 51 commits intomainfrom
2003-add-apple2-energy-device-to-i06
Open

Implement EPICS-backed Polynomial ID Device for I06#2016
Relm-Arrowny wants to merge 51 commits intomainfrom
2003-add-apple2-energy-device-to-i06

Conversation

@Relm-Arrowny
Copy link
Copy Markdown
Contributor

@Relm-Arrowny Relm-Arrowny commented Apr 17, 2026

Fixes #2003

  • Introduced I06EpicsPolynomialDevice to construct EnergyMotorLookup tables dynamically from EPICS PVs.
  • Added an optional inverse EnergyMotorConverter to Apple2Controller for bidirectional gap/energy calculations.
  • Renamed EnergyMotorConverter parameters from energy to value to better support generic bidirectional conversions (e.g., Motor ↔ Energy).

Instructions to reviewer on how to test:

  1. Do thing x
  2. Confirm thing y happens

Checks for reviewer

  • Would the PR title make sense to a scientist on a set of release notes
  • If a new device has been added does it follow the standards
  • If changing the API for a pre-existing device, ensure that any beamlines using this device have updated their Bluesky plans accordingly
  • Have the connection tests for the relevant beamline(s) been run via dodal connect ${BEAMLINE}

@Relm-Arrowny Relm-Arrowny linked an issue Apr 17, 2026 that may be closed by this pull request
7 tasks
Copy link
Copy Markdown
Contributor

@oliwenmandiamond oliwenmandiamond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. Just think the variable name needs to be changed + need to add the config

Comment thread src/dodal/devices/insertion_device/apple2_controller.py Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.12%. Comparing base (d4c4ae9) to head (a58f709).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2016   +/-   ##
=======================================
  Coverage   99.11%   99.12%           
=======================================
  Files         328      330    +2     
  Lines       12774    12873   +99     
=======================================
+ Hits        12661    12760   +99     
  Misses        113      113           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Relm-Arrowny Relm-Arrowny changed the title add gap to energy coverter to controller add i06 apple2 and energy controllers Apr 23, 2026
@Relm-Arrowny Relm-Arrowny changed the title add i06 apple2 and energy controllers Implement EPICS-backed Polynomial ID Device for I06 Apr 23, 2026
@Relm-Arrowny Relm-Arrowny marked this pull request as ready for review April 23, 2026 16:15
@Relm-Arrowny Relm-Arrowny requested a review from a team as a code owner April 23, 2026 16:15
Copy link
Copy Markdown
Contributor

@oliwenmandiamond oliwenmandiamond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, is a good first start but I think the design needs a bit more work. Please see my comments

Comment thread src/dodal/devices/beamlines/i06_shared/i06_apple2_controller.py Outdated
Comment on lines +49 to +58
def _get_apple2_value(self, gap: float, phase: float, pol: Pol) -> Apple2Val:
return Apple2Val(
gap=gap,
phase=Apple2PhasesVal(
top_outer=phase,
top_inner=0.0,
btm_inner=phase,
btm_outer=0.0,
),
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shares the same return as Apple2EnforceLHMoveController. I wonder if there is a better way we could do this or just accept the duplication. Maybe create a another controller called FourArmApple2Controller or UnlockedApple2Controller which this and Apple2EnforceLHMoveController inherit from.

Copy link
Copy Markdown
Contributor Author

@Relm-Arrowny Relm-Arrowny Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this will be moot when we add LA and extra lookup correct i06 has.

Comment thread src/dodal/beamlines/i06_shared.py Outdated
Comment thread src/dodal/beamlines/i06_shared.py Outdated
}


class I06EpicsPolynomialDevice(Device, Triggerable):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class seems confused to me. This should be inheriting from EnergyMotorLookup.

I think this possibly needs to be restructured so that we have three classes of this, one for EnergyGapEpicsMotorLookup, EnergyPhaseEpicsMotorLookup, and GapMotorEpicsEnergyLookup and then create an instance of each one. This way each logic is more focused and smaller.

Then we can also update base class method EnergyMotorLookup.update_lookup to be async and then create each one to then give to the controller. We could even make it automatically update by adding a monitor and then forcing an update table if detects a change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EpicsPolynomialEnergyMotorLookup now inherits from EnergyMotorLookup via a new shared StaticPolynomialEnergyMotorLookup class. I opted not to create three separate classes since their functions are identical, instead I make I06EpicsPolynomialDevice as a composition of EnergyMotorLookup.

We do not really want a autoupdate to prevent energy calibrations from changing without an explicit request through the triggerable interface. Not 100% if we want triggerable or not but it seem to me it much easier to do yield from bps.trigger(device) Then working out how to make blueapi do await device.update_lookup().

Comment thread src/dodal/devices/insertion_device/apple2_controller.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add apple2 energy device to i06

2 participants